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.exception.PortalException;
018    import com.liferay.portal.kernel.image.ImageBag;
019    import com.liferay.portal.kernel.image.ImageToolUtil;
020    import com.liferay.portal.kernel.io.FileFilter;
021    import com.liferay.portal.kernel.lar.ExportImportPathUtil;
022    import com.liferay.portal.kernel.lar.PortletDataContext;
023    import com.liferay.portal.kernel.log.Log;
024    import com.liferay.portal.kernel.log.LogFactoryUtil;
025    import com.liferay.portal.kernel.messaging.MessageBusUtil;
026    import com.liferay.portal.kernel.repository.model.FileEntry;
027    import com.liferay.portal.kernel.repository.model.FileVersion;
028    import com.liferay.portal.kernel.util.FileUtil;
029    import com.liferay.portal.kernel.util.GetterUtil;
030    import com.liferay.portal.kernel.util.PrefsPropsUtil;
031    import com.liferay.portal.kernel.util.PropsKeys;
032    import com.liferay.portal.kernel.util.PropsUtil;
033    import com.liferay.portal.kernel.util.StreamUtil;
034    import com.liferay.portal.kernel.util.StringBundler;
035    import com.liferay.portal.kernel.util.StringPool;
036    import com.liferay.portal.kernel.util.SystemProperties;
037    import com.liferay.portal.kernel.util.Validator;
038    import com.liferay.portal.kernel.xml.Element;
039    import com.liferay.portal.model.CompanyConstants;
040    import com.liferay.portal.util.PortalUtil;
041    import com.liferay.portal.util.PortletKeys;
042    import com.liferay.portlet.documentlibrary.DuplicateDirectoryException;
043    import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
044    
045    import java.awt.image.RenderedImage;
046    
047    import java.io.File;
048    import java.io.InputStream;
049    
050    import java.util.List;
051    import java.util.Map;
052    import java.util.concurrent.ConcurrentHashMap;
053    import java.util.concurrent.Future;
054    
055    /**
056     * @author Alexander Chow
057     * @author Ivica Cardic
058     */
059    public abstract class DLPreviewableProcessor implements DLProcessor {
060    
061            public static final String PREVIEW_PATH = "document_preview/";
062    
063            public static final String PREVIEW_TMP_PATH =
064                    SystemProperties.get(SystemProperties.TMP_DIR) +
065                            "/liferay/" + PREVIEW_PATH;
066    
067            public static final long REPOSITORY_ID = CompanyConstants.SYSTEM;
068    
069            public static final int THUMBNAIL_INDEX_CUSTOM_1 = 1;
070    
071            public static final int THUMBNAIL_INDEX_CUSTOM_2 = 2;
072    
073            public static final int THUMBNAIL_INDEX_DEFAULT = 0;
074    
075            public static final String THUMBNAIL_PATH = "document_thumbnail/";
076    
077            public static final String THUMBNAIL_TMP_PATH =
078                    SystemProperties.get(SystemProperties.TMP_DIR) +
079                            "/liferay/" + THUMBNAIL_PATH;
080    
081            public static void deleteFiles() {
082                    long[] companyIds = PortalUtil.getCompanyIds();
083    
084                    for (long companyId : companyIds) {
085                            try {
086                                    DLStoreUtil.deleteDirectory(
087                                            companyId, REPOSITORY_ID, PREVIEW_PATH);
088                            }
089                            catch (Exception e) {
090                            }
091    
092                            try {
093                                    DLStoreUtil.deleteDirectory(
094                                            companyId, REPOSITORY_ID, THUMBNAIL_PATH);
095                            }
096                            catch (Exception e) {
097                            }
098                    }
099            }
100    
101            @Override
102            public void cleanUp(FileEntry fileEntry) {
103                    deleteFiles(fileEntry, getThumbnailType());
104            }
105    
106            @Override
107            public void cleanUp(FileVersion fileVersion) {
108                    deleteFiles(fileVersion, getThumbnailType());
109            }
110    
111            @Override
112            public void copy(
113                    FileVersion sourceFileVersion, FileVersion destinationFileVersion) {
114    
115                    if (sourceFileVersion.getFileVersionId() ==
116                                    destinationFileVersion.getFileVersionId()) {
117    
118                            return;
119                    }
120    
121                    copyPreviews(sourceFileVersion, destinationFileVersion);
122                    copyThumbnails(sourceFileVersion, destinationFileVersion);
123            }
124    
125            public void deleteFiles(FileEntry fileEntry, String thumbnailType) {
126                    deleteFiles(
127                            fileEntry.getCompanyId(), fileEntry.getGroupId(),
128                            fileEntry.getFileEntryId(), -1, thumbnailType);
129            }
130    
131            public void deleteFiles(FileVersion fileVersion, String thumbnailType) {
132                    deleteFiles(
133                            fileVersion.getCompanyId(), fileVersion.getGroupId(),
134                            fileVersion.getFileEntryId(), fileVersion.getFileVersionId(),
135                            thumbnailType);
136            }
137    
138            @Override
139            public void exportGeneratedFiles(
140                            PortletDataContext portletDataContext, FileEntry fileEntry,
141                            Element fileEntryElement)
142                    throws Exception {
143    
144                    doExportGeneratedFiles(portletDataContext, fileEntry, fileEntryElement);
145            }
146    
147            @Override
148            public void importGeneratedFiles(
149                            PortletDataContext portletDataContext, FileEntry fileEntry,
150                            FileEntry importedFileEntry, Element fileEntryElement)
151                    throws Exception {
152    
153                    cleanUp(importedFileEntry.getFileVersion());
154    
155                    doImportGeneratedFiles(
156                            portletDataContext, fileEntry, importedFileEntry, fileEntryElement);
157            }
158    
159            @Override
160            public boolean isSupported(FileVersion fileVersion) {
161                    if (fileVersion == null) {
162                            return false;
163                    }
164    
165                    if (!DLProcessorRegistryUtil.isPreviewableSize(fileVersion)) {
166                            return false;
167                    }
168    
169                    return isSupported(fileVersion.getMimeType());
170            }
171    
172            @Override
173            public void trigger(
174                    FileVersion sourceFileVersion, FileVersion destinationFileVersion) {
175    
176                    if (getFileVersionIds().contains(
177                                    destinationFileVersion.getFileVersionId())) {
178    
179                            String processIdentity = Long.toString(
180                                    destinationFileVersion.getFileVersionId());
181    
182                            destroyProcess(processIdentity);
183    
184                            getFileVersionIds().remove(
185                                    destinationFileVersion.getFileVersionId());
186                    }
187            }
188    
189            protected static String getPathSegment(
190                    FileVersion fileVersion, boolean preview) {
191    
192                    return getPathSegment(
193                            fileVersion.getGroupId(), fileVersion.getFileEntryId(),
194                            fileVersion.getFileVersionId(), preview);
195            }
196    
197            protected static String getPathSegment(
198                    long groupId, long fileEntryId, long fileVersionId, boolean preview) {
199    
200                    StringBundler sb = null;
201    
202                    if (fileVersionId > 0) {
203                            sb = new StringBundler(5);
204                    }
205                    else {
206                            sb = new StringBundler(3);
207                    }
208    
209                    if (preview) {
210                            sb.append(PREVIEW_PATH);
211                    }
212                    else {
213                            sb.append(THUMBNAIL_PATH);
214                    }
215    
216                    sb.append(groupId);
217                    sb.append(DLUtil.getDividedPath(fileEntryId));
218    
219                    if (fileVersionId > 0) {
220                            sb.append(StringPool.SLASH);
221                            sb.append(fileVersionId);
222                    }
223    
224                    return sb.toString();
225            }
226    
227            protected void addFileToStore(
228                            long companyId, String dirName, String filePath, File srcFile)
229                    throws PortalException {
230    
231                    try {
232                            DLStoreUtil.addDirectory(companyId, REPOSITORY_ID, dirName);
233                    }
234                    catch (DuplicateDirectoryException dde) {
235                    }
236    
237                    DLStoreUtil.addFile(companyId, REPOSITORY_ID, filePath, false, srcFile);
238            }
239    
240            protected void addFileToStore(
241                            long companyId, String dirName, String filePath, InputStream is)
242                    throws PortalException {
243    
244                    try {
245                            DLStoreUtil.addDirectory(companyId, REPOSITORY_ID, dirName);
246                    }
247                    catch (DuplicateDirectoryException dde) {
248                    }
249    
250                    DLStoreUtil.addFile(companyId, REPOSITORY_ID, filePath, false, is);
251            }
252    
253            protected void copyPreviews(
254                    FileVersion sourceFileVersion, FileVersion destinationFileVersion) {
255    
256                    try {
257                            String[] previewTypes = getPreviewTypes();
258    
259                            for (String previewType : previewTypes) {
260                                    if (hasPreview(sourceFileVersion, previewType) &&
261                                            !hasPreview(destinationFileVersion, previewType)) {
262    
263                                            String previewFilePath = getPreviewFilePath(
264                                                    destinationFileVersion, previewType);
265    
266                                            InputStream is = doGetPreviewAsStream(
267                                                    sourceFileVersion, previewType);
268    
269                                            addFileToStore(
270                                                    destinationFileVersion.getCompanyId(), PREVIEW_PATH,
271                                                    previewFilePath, is);
272                                    }
273                            }
274                    }
275                    catch (Exception e) {
276                            _log.error(e, e);
277                    }
278            }
279    
280            protected void copyThumbnail(
281                    FileVersion sourceFileVersion, FileVersion destinationFileVersion,
282                    int index) {
283    
284                    try {
285                            if (isThumbnailEnabled(index) &&
286                                    hasThumbnail(sourceFileVersion, index) &&
287                                    !hasThumbnail(destinationFileVersion, index)) {
288    
289                                    InputStream is = doGetThumbnailAsStream(
290                                            sourceFileVersion, index);
291    
292                                    String thumbnailFilePath = getThumbnailFilePath(
293                                            destinationFileVersion,
294                                            getThumbnailType(destinationFileVersion), index);
295    
296                                    addFileToStore(
297                                            destinationFileVersion.getCompanyId(), THUMBNAIL_PATH,
298                                            thumbnailFilePath, is);
299                            }
300                    }
301                    catch (Exception e) {
302                            _log.error(e, e);
303                    }
304            }
305    
306            protected void copyThumbnails(
307                    FileVersion sourceFileVersion, FileVersion destinationFileVersion) {
308    
309                    copyThumbnail(
310                            sourceFileVersion, destinationFileVersion, THUMBNAIL_INDEX_DEFAULT);
311                    copyThumbnail(
312                            sourceFileVersion, destinationFileVersion,
313                            THUMBNAIL_INDEX_CUSTOM_1);
314                    copyThumbnail(
315                            sourceFileVersion, destinationFileVersion,
316                            THUMBNAIL_INDEX_CUSTOM_2);
317            }
318    
319            protected void deleteFiles(
320                    long companyId, long groupId, long fileEntryId, long fileVersionId,
321                    String thumbnailType) {
322    
323                    deletePreviews(companyId, groupId, fileEntryId, fileVersionId);
324                    deleteThumbnails(
325                            companyId, groupId, fileEntryId, fileVersionId, thumbnailType);
326            }
327    
328            protected void deletePreviews(
329                    long companyId, long groupId, long fileEntryId, long fileVersionId) {
330    
331                    String previewFilePath = getPreviewFilePath(
332                            groupId, fileEntryId, fileVersionId, null);
333    
334                    try {
335                            DLStoreUtil.deleteDirectory(
336                                    companyId, REPOSITORY_ID, previewFilePath);
337                    }
338                    catch (Exception e) {
339                    }
340            }
341    
342            protected void deleteThumbnail(
343                    long companyId, long groupId, long fileEntryId, long fileVersionId,
344                    String thumbnailType, int index) {
345    
346                    try {
347                            String thumbnailFilePath = getThumbnailFilePath(
348                                    groupId, fileEntryId, fileVersionId, thumbnailType, index);
349    
350                            DLStoreUtil.deleteFile(companyId, REPOSITORY_ID, thumbnailFilePath);
351                    }
352                    catch (Exception e) {
353                    }
354            }
355    
356            protected void deleteThumbnails(
357                    long companyId, long groupId, long fileEntryId, long fileVersionId,
358                    String thumbnailType) {
359    
360                    deleteThumbnail(
361                            companyId, groupId, fileEntryId, fileVersionId, thumbnailType,
362                            THUMBNAIL_INDEX_DEFAULT);
363                    deleteThumbnail(
364                            companyId, groupId, fileEntryId, fileVersionId, thumbnailType,
365                            THUMBNAIL_INDEX_CUSTOM_1);
366                    deleteThumbnail(
367                            companyId, groupId, fileEntryId, fileVersionId, thumbnailType,
368                            THUMBNAIL_INDEX_CUSTOM_2);
369            }
370    
371            protected void destroyProcess(String processIdentity) {
372                    Future<?> future = futures.remove(processIdentity);
373    
374                    if (future != null) {
375                            future.cancel(true);
376    
377                            if (_log.isInfoEnabled()) {
378                                    _log.info("Cancellation requested for " + processIdentity);
379                            }
380                    }
381            }
382    
383            protected abstract void doExportGeneratedFiles(
384                            PortletDataContext portletDataContext, FileEntry fileEntry,
385                            Element fileEntryElement)
386                    throws Exception;
387    
388            protected InputStream doGetPreviewAsStream(
389                            FileVersion fileVersion, int index, String type)
390                    throws PortalException {
391    
392                    return DLStoreUtil.getFileAsStream(
393                            fileVersion.getCompanyId(), CompanyConstants.SYSTEM,
394                            getPreviewFilePath(fileVersion, index, type));
395            }
396    
397            protected InputStream doGetPreviewAsStream(
398                            FileVersion fileVersion, String type)
399                    throws PortalException {
400    
401                    return doGetPreviewAsStream(fileVersion, 0, type);
402            }
403    
404            protected int doGetPreviewFileCount(FileVersion fileVersion)
405                    throws Exception {
406    
407                    try {
408                            String[] fileNames = DLStoreUtil.getFileNames(
409                                    fileVersion.getCompanyId(), REPOSITORY_ID,
410                                    getPathSegment(fileVersion, true));
411    
412                            return fileNames.length;
413                    }
414                    catch (Exception e) {
415                    }
416    
417                    return 0;
418            }
419    
420            protected long doGetPreviewFileSize(FileVersion fileVersion, int index)
421                    throws PortalException {
422    
423                    return doGetPreviewFileSize(fileVersion, index, getPreviewType());
424            }
425    
426            protected long doGetPreviewFileSize(
427                            FileVersion fileVersion, int index, String type)
428                    throws PortalException {
429    
430                    return DLStoreUtil.getFileSize(
431                            fileVersion.getCompanyId(), CompanyConstants.SYSTEM,
432                            getPreviewFilePath(fileVersion, index, type));
433            }
434    
435            protected long doGetPreviewFileSize(FileVersion fileVersion, String type)
436                    throws PortalException {
437    
438                    return doGetPreviewFileSize(fileVersion, 0, type);
439            }
440    
441            protected InputStream doGetThumbnailAsStream(
442                            FileVersion fileVersion, int index)
443                    throws PortalException {
444    
445                    String type = getThumbnailType(fileVersion);
446    
447                    return DLStoreUtil.getFileAsStream(
448                            fileVersion.getCompanyId(), CompanyConstants.SYSTEM,
449                            getThumbnailFilePath(fileVersion, type, index));
450            }
451    
452            protected long doGetThumbnailFileSize(FileVersion fileVersion, int index)
453                    throws PortalException {
454    
455                    String type = getThumbnailType(fileVersion);
456    
457                    return DLStoreUtil.getFileSize(
458                            fileVersion.getCompanyId(), CompanyConstants.SYSTEM,
459                            getThumbnailFilePath(fileVersion, type, index));
460            }
461    
462            protected abstract void doImportGeneratedFiles(
463                            PortletDataContext portletDataContext, FileEntry fileEntry,
464                            FileEntry importedFileEntry, Element fileEntryElement)
465                    throws Exception;
466    
467            protected void exportBinary(
468                    PortletDataContext portletDataContext, Element fileEntryElement,
469                    FileVersion fileVersion, InputStream is, String binPath,
470                    String binPathName) {
471    
472                    fileEntryElement.addAttribute(binPathName, binPath);
473    
474                    if (is == null) {
475                            if (_log.isWarnEnabled()) {
476                                    _log.warn(
477                                            "No input stream found for file entry " +
478                                                    fileVersion.getFileEntryId());
479                            }
480    
481                            fileEntryElement.detach();
482    
483                            return;
484                    }
485    
486                    portletDataContext.addZipEntry(binPath, is);
487            }
488    
489            protected void exportPreview(
490                            PortletDataContext portletDataContext, FileEntry fileEntry,
491                            Element fileEntryElement, String binPathSuffix, String previewType)
492                    throws Exception {
493    
494                    exportPreview(
495                            portletDataContext, fileEntry, fileEntryElement, binPathSuffix,
496                            previewType, -1);
497            }
498    
499            protected void exportPreview(
500                            PortletDataContext portletDataContext, FileEntry fileEntry,
501                            Element fileEntryElement, String binPathSuffix, String previewType,
502                            int fileIndex)
503                    throws Exception {
504    
505                    if (portletDataContext.isPerformDirectBinaryImport()) {
506                            return;
507                    }
508    
509                    FileVersion fileVersion = fileEntry.getFileVersion();
510    
511                    if (!hasPreview(fileVersion, previewType)) {
512                            if (_log.isWarnEnabled()) {
513                                    _log.warn(
514                                            "No preview found for file entry " +
515                                                    fileEntry.getFileEntryId());
516                            }
517    
518                            return;
519                    }
520    
521                    String binPathSegment = null;
522    
523                    if (fileIndex < 0) {
524                            binPathSegment = previewType;
525                    }
526                    else {
527                            binPathSegment = Integer.toString(fileIndex + 1);
528                    }
529    
530                    String binPath = getBinPath(
531                            portletDataContext, fileEntry, binPathSegment);
532    
533                    StringBundler sb = new StringBundler(4);
534    
535                    sb.append("bin-path-preview-");
536                    sb.append(binPathSegment);
537                    sb.append("-");
538                    sb.append(binPathSuffix);
539    
540                    String binPathName = sb.toString();
541    
542                    fileEntryElement.addAttribute(binPathName, binPath);
543    
544                    InputStream is = null;
545    
546                    try {
547                            if (fileIndex < 0) {
548                                    is = doGetPreviewAsStream(fileVersion, previewType);
549                            }
550                            else {
551                                    is = doGetPreviewAsStream(
552                                            fileVersion, fileIndex + 1, previewType);
553                            }
554    
555                            exportBinary(
556                                    portletDataContext, fileEntryElement, fileVersion, is, binPath,
557                                    binPathName);
558                    }
559                    finally {
560                            StreamUtil.cleanUp(is);
561                    }
562            }
563    
564            protected void exportThumbnail(
565                            PortletDataContext portletDataContext, FileEntry fileEntry,
566                            Element fileEntryElement, String binPathName, int index)
567                    throws PortalException {
568    
569                    if (!isThumbnailEnabled(index)) {
570                            return;
571                    }
572    
573                    FileVersion fileVersion = fileEntry.getFileVersion();
574    
575                    if (!hasThumbnail(fileVersion, index)) {
576                            if (_log.isWarnEnabled()) {
577                                    _log.warn(
578                                            "No thumbnail found for file entry " +
579                                                    fileEntry.getFileEntryId());
580                            }
581    
582                            return;
583                    }
584    
585                    InputStream is = null;
586    
587                    try {
588                            is = doGetThumbnailAsStream(fileVersion, index);
589    
590                            String binPath = getBinPath(portletDataContext, fileEntry, index);
591    
592                            fileEntryElement.addAttribute(binPathName, binPath);
593    
594                            exportBinary(
595                                    portletDataContext, fileEntryElement, fileVersion, is, binPath,
596                                    binPathName);
597                    }
598                    finally {
599                            StreamUtil.cleanUp(is);
600                    }
601            }
602    
603            protected void exportThumbnails(
604                            PortletDataContext portletDataContext, FileEntry fileEntry,
605                            Element fileEntryElement, String binPathSuffix)
606                    throws PortalException {
607    
608                    FileVersion fileVersion = fileEntry.getFileVersion();
609    
610                    if (!isSupported(fileVersion)) {
611                            return;
612                    }
613    
614                    if (!portletDataContext.isPerformDirectBinaryImport()) {
615                            exportThumbnail(
616                                    portletDataContext, fileEntry, fileEntryElement,
617                                    "bin-path-thumbnail-default-" + binPathSuffix,
618                                    THUMBNAIL_INDEX_DEFAULT);
619                            exportThumbnail(
620                                    portletDataContext, fileEntry, fileEntryElement,
621                                    "bin-path-thumbnail-custom-1-" + binPathSuffix,
622                                    THUMBNAIL_INDEX_CUSTOM_1);
623                            exportThumbnail(
624                                    portletDataContext, fileEntry, fileEntryElement,
625                                    "bin-path-thumbnail-custom-2-" + binPathSuffix,
626                                    THUMBNAIL_INDEX_CUSTOM_2);
627                    }
628            }
629    
630            protected String getBinPath(
631                    PortletDataContext portletDataContext, FileEntry fileEntry, int index) {
632    
633                    StringBundler sb = new StringBundler(8);
634    
635                    sb.append(
636                            ExportImportPathUtil.getPortletPath(
637                                    portletDataContext, PortletKeys.DOCUMENT_LIBRARY));
638                    sb.append("/bin/");
639                    sb.append(fileEntry.getFileEntryId());
640                    sb.append(StringPool.SLASH);
641                    sb.append(THUMBNAIL_PATH);
642                    sb.append(fileEntry.getVersion());
643                    sb.append(StringPool.SLASH);
644                    sb.append(index);
645    
646                    return sb.toString();
647            }
648    
649            protected String getBinPath(
650                    PortletDataContext portletDataContext, FileEntry fileEntry,
651                    String type) {
652    
653                    StringBundler sb = new StringBundler(8);
654    
655                    sb.append(
656                            ExportImportPathUtil.getPortletPath(
657                                    portletDataContext, PortletKeys.DOCUMENT_LIBRARY));
658                    sb.append("/bin/");
659                    sb.append(fileEntry.getFileEntryId());
660                    sb.append(StringPool.SLASH);
661                    sb.append(PREVIEW_PATH);
662                    sb.append(fileEntry.getVersion());
663                    sb.append(StringPool.SLASH);
664                    sb.append(type);
665    
666                    return sb.toString();
667            }
668    
669            protected abstract List<Long> getFileVersionIds();
670    
671            protected String getPreviewFilePath(FileVersion fileVersion) {
672                    return getPreviewFilePath(fileVersion, 0);
673            }
674    
675            protected String getPreviewFilePath(FileVersion fileVersion, int index) {
676                    return getPreviewFilePath(fileVersion, index, getPreviewType());
677            }
678    
679            protected String getPreviewFilePath(
680                    FileVersion fileVersion, int index, String type) {
681    
682                    return getPreviewFilePath(
683                            fileVersion.getGroupId(), fileVersion.getFileEntryId(),
684                            fileVersion.getFileVersionId(), index, type);
685            }
686    
687            protected String getPreviewFilePath(FileVersion fileVersion, String type) {
688                    return getPreviewFilePath(fileVersion, 0, type);
689            }
690    
691            protected String getPreviewFilePath(
692                    long groupId, long fileEntryId, long fileVersionId, int index,
693                    String type) {
694    
695                    StringBundler sb = null;
696    
697                    if (index > 0) {
698                            sb = new StringBundler(5);
699                    }
700                    else {
701                            sb = new StringBundler(3);
702                    }
703    
704                    sb.append(getPathSegment(groupId, fileEntryId, fileVersionId, true));
705    
706                    if (index > 0) {
707                            sb.append(StringPool.SLASH);
708                            sb.append(index - 1);
709                    }
710    
711                    if (Validator.isNotNull(type)) {
712                            sb.append(StringPool.PERIOD);
713                            sb.append(type);
714                    }
715    
716                    return sb.toString();
717            }
718    
719            protected String getPreviewFilePath(
720                    long groupId, long fileEntryId, long fileVersionId, String type) {
721    
722                    return getPreviewFilePath(groupId, fileEntryId, fileVersionId, 0, type);
723            }
724    
725            protected File getPreviewTempFile(String id) {
726                    return getPreviewTempFile(id, 0);
727            }
728    
729            protected File getPreviewTempFile(String id, int index) {
730                    return getPreviewTempFile(id, index, getPreviewType());
731            }
732    
733            protected File getPreviewTempFile(String id, int index, String type) {
734                    String previewTempFilePath = getPreviewTempFilePath(id, index, type);
735    
736                    return new File(previewTempFilePath);
737            }
738    
739            protected File getPreviewTempFile(String id, String type) {
740                    return getPreviewTempFile(id, 0, type);
741            }
742    
743            protected int getPreviewTempFileCount(FileVersion fileVersion) {
744                    return getPreviewTempFileCount(fileVersion, getPreviewType());
745            }
746    
747            protected int getPreviewTempFileCount(
748                    FileVersion fileVersion, String type) {
749    
750                    String tempFileId = DLUtil.getTempFileId(
751                            fileVersion.getFileEntryId(), fileVersion.getVersion());
752    
753                    StringBundler sb = new StringBundler(5);
754    
755                    sb.append(tempFileId);
756                    sb.append(StringPool.DASH);
757                    sb.append("(.*)");
758    
759                    if (Validator.isNotNull(type)) {
760                            sb.append(StringPool.PERIOD);
761                            sb.append(type);
762                    }
763    
764                    File dir = new File(PREVIEW_TMP_PATH);
765    
766                    File[] files = dir.listFiles(new FileFilter(sb.toString()));
767    
768                    if (_log.isDebugEnabled()) {
769                            for (File file : files) {
770                                    _log.debug("Preview page for " + tempFileId + " " + file);
771                            }
772                    }
773    
774                    return files.length;
775            }
776    
777            protected String getPreviewTempFilePath(String id) {
778                    return getPreviewTempFilePath(id, 0);
779            }
780    
781            protected String getPreviewTempFilePath(String id, int index) {
782                    return getPreviewTempFilePath(id, index, getPreviewType());
783            }
784    
785            protected String getPreviewTempFilePath(String id, int index, String type) {
786                    StringBundler sb = null;
787    
788                    if (index > 0) {
789                            sb = new StringBundler(6);
790                    }
791                    else {
792                            sb = new StringBundler(4);
793                    }
794    
795                    sb.append(PREVIEW_TMP_PATH);
796                    sb.append(id);
797    
798                    if (index > 0) {
799                            sb.append(StringPool.DASH);
800                            sb.append(index - 1);
801                    }
802                    else if (index == -1) {
803                            sb.append("-%d");
804                    }
805    
806                    if (Validator.isNotNull(type)) {
807                            sb.append(StringPool.PERIOD);
808                            sb.append(type);
809                    }
810    
811                    return sb.toString();
812            }
813    
814            protected String getPreviewTempFilePath(String id, String type) {
815                    return getPreviewTempFilePath(id, 0, type);
816            }
817    
818            protected String getPreviewType() {
819                    return getPreviewType(null);
820            }
821    
822            protected abstract String getPreviewType(FileVersion fileVersion);
823    
824            protected String getPreviewType(int index) {
825                    String[] previewTypes = getPreviewTypes();
826    
827                    if ((previewTypes != null) && (previewTypes.length > index)) {
828                            return previewTypes[index];
829                    }
830                    else {
831                            return getPreviewType();
832                    }
833            }
834    
835            protected String[] getPreviewTypes() {
836                    return new String[] {getPreviewType()};
837            }
838    
839            protected String getThumbnailFilePath(FileVersion fileVersion, int index) {
840                    return getThumbnailFilePath(fileVersion, getThumbnailType(), index);
841            }
842    
843            protected String getThumbnailFilePath(
844                    FileVersion fileVersion, String type, int index) {
845    
846                    return getThumbnailFilePath(
847                            fileVersion.getGroupId(), fileVersion.getFileEntryId(),
848                            fileVersion.getFileVersionId(), type, index);
849            }
850    
851            protected String getThumbnailFilePath(
852                    long groupId, long fileEntryId, long fileVersionId,
853                    String thumbnailType, int index) {
854    
855                    StringBundler sb = new StringBundler(5);
856    
857                    sb.append(getPathSegment(groupId, fileEntryId, fileVersionId, false));
858    
859                    if (index != THUMBNAIL_INDEX_DEFAULT) {
860                            sb.append(StringPool.DASH);
861                            sb.append(index);
862                    }
863    
864                    if ((fileVersionId > 0) && Validator.isNotNull(thumbnailType)) {
865                            sb.append(StringPool.PERIOD);
866                            sb.append(thumbnailType);
867                    }
868    
869                    return sb.toString();
870            }
871    
872            protected File getThumbnailTempFile(String id) {
873                    return getThumbnailTempFile(id, getThumbnailType());
874            }
875    
876            protected File getThumbnailTempFile(String id, String type) {
877                    String thumbnailTempFilePath = getThumbnailTempFilePath(id, type);
878    
879                    return new File(thumbnailTempFilePath);
880            }
881    
882            protected String getThumbnailTempFilePath(String id) {
883                    return getThumbnailTempFilePath(id, getThumbnailType());
884            }
885    
886            protected String getThumbnailTempFilePath(String id, String type) {
887                    StringBundler sb = new StringBundler(4);
888    
889                    sb.append(THUMBNAIL_TMP_PATH);
890                    sb.append(id);
891    
892                    if (Validator.isNotNull(type)) {
893                            sb.append(StringPool.PERIOD);
894                            sb.append(type);
895                    }
896    
897                    return sb.toString();
898            }
899    
900            protected String getThumbnailType() {
901                    return getThumbnailType(null);
902            }
903    
904            protected abstract String getThumbnailType(FileVersion fileVersion);
905    
906            protected boolean hasPreview(FileVersion fileVersion, String type)
907                    throws Exception {
908    
909                    String previewFilePath = getPreviewFilePath(fileVersion, type);
910    
911                    if (DLStoreUtil.hasFile(
912                                    fileVersion.getCompanyId(), REPOSITORY_ID, previewFilePath)) {
913    
914                            return true;
915                    }
916                    else {
917                            return false;
918                    }
919            }
920    
921            protected boolean hasPreviews(FileVersion fileVersion) throws Exception {
922                    int count = 0;
923    
924                    String[] previewTypes = getPreviewTypes();
925    
926                    for (String previewType : previewTypes) {
927                            if (hasPreview(fileVersion, previewType)) {
928                                    count++;
929                            }
930                    }
931    
932                    if (count == previewTypes.length) {
933                            return true;
934                    }
935                    else {
936                            return false;
937                    }
938            }
939    
940            protected boolean hasThumbnail(FileVersion fileVersion, int index) {
941                    try {
942                            String imageType = getThumbnailType(fileVersion);
943    
944                            return DLStoreUtil.hasFile(
945                                    fileVersion.getCompanyId(), REPOSITORY_ID,
946                                    getThumbnailFilePath(fileVersion, imageType, index));
947                    }
948                    catch (Exception e) {
949                            _log.error(e, e);
950                    }
951    
952                    return false;
953            }
954    
955            protected boolean hasThumbnails(FileVersion fileVersion) {
956                    if ((isThumbnailEnabled(THUMBNAIL_INDEX_DEFAULT) &&
957                             !hasThumbnail(fileVersion, THUMBNAIL_INDEX_DEFAULT)) ||
958                            (isThumbnailEnabled(THUMBNAIL_INDEX_CUSTOM_1) &&
959                             !hasThumbnail(fileVersion, THUMBNAIL_INDEX_CUSTOM_1)) ||
960                            (isThumbnailEnabled(THUMBNAIL_INDEX_CUSTOM_2) &&
961                             !hasThumbnail(fileVersion, THUMBNAIL_INDEX_CUSTOM_2))) {
962    
963                            return false;
964                    }
965    
966                    return true;
967            }
968    
969            protected void importPreview(
970                            PortletDataContext portletDataContext, FileEntry fileEntry,
971                            FileEntry importedFileEntry, Element fileEntryElement,
972                            String binPathSuffix, String previewType)
973                    throws Exception {
974    
975                    importPreview(
976                            portletDataContext, fileEntry, importedFileEntry, fileEntryElement,
977                            binPathSuffix, previewType, -1);
978            }
979    
980            protected void importPreview(
981                            PortletDataContext portletDataContext, FileEntry fileEntry,
982                            FileEntry importedFileEntry, Element fileEntryElement,
983                            String binPathSuffix, String previewType, int fileIndex)
984                    throws Exception {
985    
986                    if (!portletDataContext.isPerformDirectBinaryImport()) {
987                            importPreviewFromLAR(
988                                    portletDataContext, importedFileEntry, fileEntryElement,
989                                    binPathSuffix, previewType, fileIndex);
990                    }
991                    else {
992                            FileVersion importedFileVersion =
993                                    importedFileEntry.getFileVersion();
994    
995                            String previewFilePath = getPreviewFilePath(
996                                    importedFileVersion, previewType);
997    
998                            FileVersion fileVersion = fileEntry.getFileVersion();
999    
1000                            if (!hasPreview(fileVersion, previewType)) {
1001                                    return;
1002                            }
1003    
1004                            InputStream is = null;
1005    
1006                            try {
1007                                    if (fileIndex < 0) {
1008                                            is = doGetPreviewAsStream(fileVersion, previewType);
1009                                    }
1010                                    else {
1011                                            is = doGetPreviewAsStream(
1012                                                    fileVersion, fileIndex, previewType);
1013                                    }
1014    
1015                                    addFileToStore(
1016                                            portletDataContext.getCompanyId(), PREVIEW_PATH,
1017                                            previewFilePath, is);
1018                            }
1019                            finally {
1020                                    StreamUtil.cleanUp(is);
1021                            }
1022                    }
1023            }
1024    
1025            protected void importPreviewFromLAR(
1026                            PortletDataContext portletDataContext, FileEntry fileEntry,
1027                            Element fileEntryElement, String binPathSuffix, String previewType,
1028                            int fileIndex)
1029                    throws Exception {
1030    
1031                    FileVersion fileVersion = fileEntry.getFileVersion();
1032    
1033                    String binPathSegment = null;
1034    
1035                    if (fileIndex < 0) {
1036                            binPathSegment = previewType;
1037                    }
1038                    else {
1039                            binPathSegment = Integer.toString(fileIndex + 1);
1040                    }
1041    
1042                    StringBundler sb = new StringBundler(4);
1043    
1044                    sb.append("bin-path-preview-");
1045                    sb.append(binPathSegment);
1046                    sb.append("-");
1047                    sb.append(binPathSuffix);
1048    
1049                    String binPathName = sb.toString();
1050    
1051                    String binPath = fileEntryElement.attributeValue(binPathName);
1052    
1053                    InputStream is = null;
1054    
1055                    try {
1056                            is = portletDataContext.getZipEntryAsInputStream(binPath);
1057    
1058                            if (is == null) {
1059                                    return;
1060                            }
1061    
1062                            String previewFilePath = null;
1063    
1064                            if (fileIndex < 0) {
1065                                    previewFilePath = getPreviewFilePath(fileVersion, previewType);
1066                            }
1067                            else {
1068                                    previewFilePath = getPreviewFilePath(
1069                                            fileVersion, fileIndex + 1);
1070                            }
1071    
1072                            addFileToStore(
1073                                    portletDataContext.getCompanyId(), PREVIEW_PATH,
1074                                    previewFilePath, is);
1075                    }
1076                    finally {
1077                            StreamUtil.cleanUp(is);
1078                    }
1079            }
1080    
1081            protected void importThumbnail(
1082                            PortletDataContext portletDataContext, FileEntry fileEntry,
1083                            FileEntry importedFileEntry, Element fileEntryElement,
1084                            String binPathName, int index)
1085                    throws Exception {
1086    
1087                    if (!isThumbnailEnabled(index)) {
1088                            return;
1089                    }
1090    
1091                    if (!portletDataContext.isPerformDirectBinaryImport()) {
1092                            importThumbnailFromLAR(
1093                                    portletDataContext, importedFileEntry, fileEntryElement,
1094                                    binPathName, index);
1095                    }
1096                    else {
1097                            FileVersion fileVersion = fileEntry.getFileVersion();
1098    
1099                            if (!hasThumbnail(fileVersion, index)) {
1100                                    return;
1101                            }
1102    
1103                            InputStream is = null;
1104    
1105                            try {
1106                                    is = doGetThumbnailAsStream(fileVersion, index);
1107    
1108                                    FileVersion importedFileVersion =
1109                                            importedFileEntry.getFileVersion();
1110    
1111                                    String thumbnailFilePath = getThumbnailFilePath(
1112                                            importedFileVersion, getThumbnailType(importedFileVersion),
1113                                            index);
1114    
1115                                    addFileToStore(
1116                                            portletDataContext.getCompanyId(), THUMBNAIL_PATH,
1117                                            thumbnailFilePath, is);
1118                            }
1119                            finally {
1120                                    StreamUtil.cleanUp(is);
1121                            }
1122                    }
1123            }
1124    
1125            protected void importThumbnailFromLAR(
1126                            PortletDataContext portletDataContext, FileEntry fileEntry,
1127                            Element fileEntryElement, String binPathName, int index)
1128                    throws Exception {
1129    
1130                    FileVersion fileVersion = fileEntry.getFileVersion();
1131    
1132                    String binPath = fileEntryElement.attributeValue(binPathName);
1133    
1134                    InputStream is = null;
1135    
1136                    try {
1137                            is = portletDataContext.getZipEntryAsInputStream(binPath);
1138    
1139                            if (is == null) {
1140                                    return;
1141                            }
1142    
1143                            String thumbnailFilePath = getThumbnailFilePath(
1144                                    fileVersion, getThumbnailType(fileVersion), index);
1145    
1146                            addFileToStore(
1147                                    portletDataContext.getCompanyId(), THUMBNAIL_PATH,
1148                                    thumbnailFilePath, is);
1149                    }
1150                    finally {
1151                            StreamUtil.cleanUp(is);
1152                    }
1153            }
1154    
1155            protected void importThumbnails(
1156                            PortletDataContext portletDataContext, FileEntry fileEntry,
1157                            FileEntry importedFileEntry, Element fileEntryElement,
1158                            String binPathSuffix)
1159                    throws Exception {
1160    
1161                    importThumbnail(
1162                            portletDataContext, fileEntry, importedFileEntry, fileEntryElement,
1163                            "bin-path-thumbnail-default-" + binPathSuffix,
1164                            THUMBNAIL_INDEX_DEFAULT);
1165                    importThumbnail(
1166                            portletDataContext, fileEntry, importedFileEntry, fileEntryElement,
1167                            "bin-path-thumbnail-custom-1-" + binPathSuffix,
1168                            THUMBNAIL_INDEX_CUSTOM_1);
1169                    importThumbnail(
1170                            portletDataContext, fileEntry, importedFileEntry, fileEntryElement,
1171                            "bin-path-thumbnail-custom-2-" + binPathSuffix,
1172                            THUMBNAIL_INDEX_CUSTOM_2);
1173            }
1174    
1175            protected boolean isThumbnailEnabled(int index) {
1176                    if ((index == THUMBNAIL_INDEX_DEFAULT) &&
1177                            GetterUtil.getBoolean(
1178                                    PropsUtil.get(PropsKeys.DL_FILE_ENTRY_THUMBNAIL_ENABLED))) {
1179    
1180                            return true;
1181                    }
1182                    else if ((index == THUMBNAIL_INDEX_CUSTOM_1) &&
1183                                     ((PrefsPropsUtil.getInteger(
1184                                             PropsKeys.
1185                                                     DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_HEIGHT) > 0) ||
1186                                      (PrefsPropsUtil.getInteger(
1187                                              PropsKeys.
1188                                                      DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_WIDTH) > 0))) {
1189    
1190                            return true;
1191                    }
1192                    else if ((index == THUMBNAIL_INDEX_CUSTOM_2) &&
1193                                     ((PrefsPropsUtil.getInteger(
1194                                             PropsKeys.
1195                                                     DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_HEIGHT) > 0) ||
1196                                      (PrefsPropsUtil.getInteger(
1197                                              PropsKeys.
1198                                                      DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_WIDTH) > 0))) {
1199    
1200                            return true;
1201                    }
1202    
1203                    return false;
1204            }
1205    
1206            protected void sendGenerationMessage(
1207                    String destinationName, FileVersion sourceFileVersion,
1208                    FileVersion destinationFileVersion) {
1209    
1210                    Object[] payload = {sourceFileVersion, destinationFileVersion};
1211    
1212                    MessageBusUtil.sendMessage(destinationName, payload);
1213            }
1214    
1215            protected void storeThumbnailImage(
1216                            FileVersion fileVersion, RenderedImage renderedImage, int index)
1217                    throws Exception {
1218    
1219                    if (!isThumbnailEnabled(index) || hasThumbnail(fileVersion, index)) {
1220                            return;
1221                    }
1222    
1223                    String type = getThumbnailType(fileVersion);
1224    
1225                    String maxHeightPropsKey = PropsKeys.DL_FILE_ENTRY_THUMBNAIL_MAX_HEIGHT;
1226                    String maxWidthPropsKey = PropsKeys.DL_FILE_ENTRY_THUMBNAIL_MAX_WIDTH;
1227    
1228                    if (index == THUMBNAIL_INDEX_CUSTOM_1) {
1229                            maxHeightPropsKey =
1230                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_HEIGHT;
1231                            maxWidthPropsKey =
1232                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_WIDTH;
1233                    }
1234                    else if (index == THUMBNAIL_INDEX_CUSTOM_2) {
1235                            maxHeightPropsKey =
1236                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_HEIGHT;
1237                            maxWidthPropsKey =
1238                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_WIDTH;
1239                    }
1240    
1241                    RenderedImage thumbnailRenderedImage = ImageToolUtil.scale(
1242                            renderedImage, PrefsPropsUtil.getInteger(maxHeightPropsKey),
1243                            PrefsPropsUtil.getInteger(maxWidthPropsKey));
1244    
1245                    byte[] bytes = ImageToolUtil.getBytes(thumbnailRenderedImage, type);
1246    
1247                    File file = null;
1248    
1249                    try {
1250                            file = FileUtil.createTempFile(bytes);
1251    
1252                            addFileToStore(
1253                                    fileVersion.getCompanyId(), THUMBNAIL_PATH,
1254                                    getThumbnailFilePath(fileVersion, type, index), file);
1255                    }
1256                    finally {
1257                            FileUtil.delete(file);
1258                    }
1259            }
1260    
1261            protected void storeThumbnailImages(FileVersion fileVersion, File file)
1262                    throws Exception {
1263    
1264                    ImageBag imageBag = ImageToolUtil.read(file);
1265    
1266                    RenderedImage renderedImage = imageBag.getRenderedImage();
1267    
1268                    storeThumbnailImages(fileVersion, renderedImage);
1269            }
1270    
1271            protected void storeThumbnailImages(
1272                            FileVersion fileVersion, RenderedImage renderedImage)
1273                    throws Exception {
1274    
1275                    storeThumbnailImage(
1276                            fileVersion, renderedImage, THUMBNAIL_INDEX_DEFAULT);
1277                    storeThumbnailImage(
1278                            fileVersion, renderedImage, THUMBNAIL_INDEX_CUSTOM_1);
1279                    storeThumbnailImage(
1280                            fileVersion, renderedImage, THUMBNAIL_INDEX_CUSTOM_2);
1281            }
1282    
1283            protected Map<String, Future<?>> futures =
1284                    new ConcurrentHashMap<String, Future<?>>();
1285    
1286            private static Log _log = LogFactoryUtil.getLog(
1287                    DLPreviewableProcessor.class);
1288    
1289    }