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