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                    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 {
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 {
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 {
426    
427                    return doGetPreviewFileSize(fileVersion, index, getPreviewType());
428            }
429    
430            protected long doGetPreviewFileSize(
431                            FileVersion fileVersion, int index, String type)
432                    throws PortalException {
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 {
441    
442                    return doGetPreviewFileSize(fileVersion, 0, type);
443            }
444    
445            protected InputStream doGetThumbnailAsStream(
446                            FileVersion fileVersion, int index)
447                    throws PortalException {
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 {
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    
476                    fileEntryElement.addAttribute(binPathName, binPath);
477    
478                    if (is == null) {
479                            if (_log.isWarnEnabled()) {
480                                    _log.warn(
481                                            "No input stream found for file entry " +
482                                                    fileVersion.getFileEntryId());
483                            }
484    
485                            fileEntryElement.detach();
486    
487                            return;
488                    }
489    
490                    portletDataContext.addZipEntry(binPath, is);
491            }
492    
493            protected void exportPreview(
494                            PortletDataContext portletDataContext, FileEntry fileEntry,
495                            Element fileEntryElement, String binPathSuffix, String previewType)
496                    throws Exception {
497    
498                    exportPreview(
499                            portletDataContext, fileEntry, fileEntryElement, binPathSuffix,
500                            previewType, -1);
501            }
502    
503            protected void exportPreview(
504                            PortletDataContext portletDataContext, FileEntry fileEntry,
505                            Element fileEntryElement, String binPathSuffix, String previewType,
506                            int fileIndex)
507                    throws Exception {
508    
509                    if (portletDataContext.isPerformDirectBinaryImport()) {
510                            return;
511                    }
512    
513                    FileVersion fileVersion = fileEntry.getFileVersion();
514    
515                    if (!hasPreview(fileVersion, previewType)) {
516                            if (_log.isWarnEnabled()) {
517                                    _log.warn(
518                                            "No preview found for file entry " +
519                                                    fileEntry.getFileEntryId());
520                            }
521    
522                            return;
523                    }
524    
525                    String binPathSegment = null;
526    
527                    if (fileIndex < 0) {
528                            binPathSegment = previewType;
529                    }
530                    else {
531                            binPathSegment = Integer.toString(fileIndex + 1);
532                    }
533    
534                    String binPath = getBinPath(
535                            portletDataContext, fileEntry, binPathSegment);
536    
537                    StringBundler sb = new StringBundler(4);
538    
539                    sb.append("bin-path-preview-");
540                    sb.append(binPathSegment);
541                    sb.append("-");
542                    sb.append(binPathSuffix);
543    
544                    String binPathName = sb.toString();
545    
546                    fileEntryElement.addAttribute(binPathName, binPath);
547    
548                    InputStream is = null;
549    
550                    try {
551                            if (fileIndex < 0) {
552                                    is = doGetPreviewAsStream(fileVersion, previewType);
553                            }
554                            else {
555                                    is = doGetPreviewAsStream(
556                                            fileVersion, fileIndex + 1, previewType);
557                            }
558    
559                            exportBinary(
560                                    portletDataContext, fileEntryElement, fileVersion, is, binPath,
561                                    binPathName);
562                    }
563                    finally {
564                            StreamUtil.cleanUp(is);
565                    }
566            }
567    
568            protected void exportThumbnail(
569                            PortletDataContext portletDataContext, FileEntry fileEntry,
570                            Element fileEntryElement, String binPathName, int index)
571                    throws PortalException {
572    
573                    if (!isThumbnailEnabled(index)) {
574                            return;
575                    }
576    
577                    FileVersion fileVersion = fileEntry.getFileVersion();
578    
579                    if (!hasThumbnail(fileVersion, index)) {
580                            if (_log.isWarnEnabled()) {
581                                    _log.warn(
582                                            "No thumbnail found for file entry " +
583                                                    fileEntry.getFileEntryId());
584                            }
585    
586                            return;
587                    }
588    
589                    InputStream is = null;
590    
591                    try {
592                            is = doGetThumbnailAsStream(fileVersion, index);
593    
594                            String binPath = getBinPath(portletDataContext, fileEntry, index);
595    
596                            fileEntryElement.addAttribute(binPathName, binPath);
597    
598                            exportBinary(
599                                    portletDataContext, fileEntryElement, fileVersion, is, binPath,
600                                    binPathName);
601                    }
602                    finally {
603                            StreamUtil.cleanUp(is);
604                    }
605            }
606    
607            protected void exportThumbnails(
608                            PortletDataContext portletDataContext, FileEntry fileEntry,
609                            Element fileEntryElement, String binPathSuffix)
610                    throws PortalException {
611    
612                    FileVersion fileVersion = fileEntry.getFileVersion();
613    
614                    if (!isSupported(fileVersion)) {
615                            return;
616                    }
617    
618                    if (!portletDataContext.isPerformDirectBinaryImport()) {
619                            exportThumbnail(
620                                    portletDataContext, fileEntry, fileEntryElement,
621                                    "bin-path-thumbnail-default-" + binPathSuffix,
622                                    THUMBNAIL_INDEX_DEFAULT);
623                            exportThumbnail(
624                                    portletDataContext, fileEntry, fileEntryElement,
625                                    "bin-path-thumbnail-custom-1-" + binPathSuffix,
626                                    THUMBNAIL_INDEX_CUSTOM_1);
627                            exportThumbnail(
628                                    portletDataContext, fileEntry, fileEntryElement,
629                                    "bin-path-thumbnail-custom-2-" + binPathSuffix,
630                                    THUMBNAIL_INDEX_CUSTOM_2);
631                    }
632            }
633    
634            protected String getBinPath(
635                    PortletDataContext portletDataContext, FileEntry fileEntry, int index) {
636    
637                    StringBundler sb = new StringBundler(8);
638    
639                    sb.append(
640                            ExportImportPathUtil.getPortletPath(
641                                    portletDataContext, PortletKeys.DOCUMENT_LIBRARY));
642                    sb.append("/bin/");
643                    sb.append(fileEntry.getFileEntryId());
644                    sb.append(StringPool.SLASH);
645                    sb.append(THUMBNAIL_PATH);
646                    sb.append(fileEntry.getVersion());
647                    sb.append(StringPool.SLASH);
648                    sb.append(index);
649    
650                    return sb.toString();
651            }
652    
653            protected String getBinPath(
654                    PortletDataContext portletDataContext, FileEntry fileEntry,
655                    String type) {
656    
657                    StringBundler sb = new StringBundler(8);
658    
659                    sb.append(
660                            ExportImportPathUtil.getPortletPath(
661                                    portletDataContext, PortletKeys.DOCUMENT_LIBRARY));
662                    sb.append("/bin/");
663                    sb.append(fileEntry.getFileEntryId());
664                    sb.append(StringPool.SLASH);
665                    sb.append(PREVIEW_PATH);
666                    sb.append(fileEntry.getVersion());
667                    sb.append(StringPool.SLASH);
668                    sb.append(type);
669    
670                    return sb.toString();
671            }
672    
673            protected abstract List<Long> getFileVersionIds();
674    
675            protected String getPreviewFilePath(FileVersion fileVersion) {
676                    return getPreviewFilePath(fileVersion, 0);
677            }
678    
679            protected String getPreviewFilePath(FileVersion fileVersion, int index) {
680                    return getPreviewFilePath(fileVersion, index, getPreviewType());
681            }
682    
683            protected String getPreviewFilePath(
684                    FileVersion fileVersion, int index, String type) {
685    
686                    return getPreviewFilePath(
687                            fileVersion.getGroupId(), fileVersion.getFileEntryId(),
688                            fileVersion.getFileVersionId(), index, type);
689            }
690    
691            protected String getPreviewFilePath(FileVersion fileVersion, String type) {
692                    return getPreviewFilePath(fileVersion, 0, type);
693            }
694    
695            protected String getPreviewFilePath(
696                    long groupId, long fileEntryId, long fileVersionId, int index,
697                    String type) {
698    
699                    StringBundler sb = null;
700    
701                    if (index > 0) {
702                            sb = new StringBundler(5);
703                    }
704                    else {
705                            sb = new StringBundler(3);
706                    }
707    
708                    sb.append(getPathSegment(groupId, fileEntryId, fileVersionId, true));
709    
710                    if (index > 0) {
711                            sb.append(StringPool.SLASH);
712                            sb.append(index - 1);
713                    }
714    
715                    if (Validator.isNotNull(type)) {
716                            sb.append(StringPool.PERIOD);
717                            sb.append(type);
718                    }
719    
720                    return sb.toString();
721            }
722    
723            protected String getPreviewFilePath(
724                    long groupId, long fileEntryId, long fileVersionId, String type) {
725    
726                    return getPreviewFilePath(groupId, fileEntryId, fileVersionId, 0, type);
727            }
728    
729            protected File getPreviewTempFile(String id) {
730                    return getPreviewTempFile(id, 0);
731            }
732    
733            protected File getPreviewTempFile(String id, int index) {
734                    return getPreviewTempFile(id, index, getPreviewType());
735            }
736    
737            protected File getPreviewTempFile(String id, int index, String type) {
738                    String previewTempFilePath = getPreviewTempFilePath(id, index, type);
739    
740                    return new File(previewTempFilePath);
741            }
742    
743            protected File getPreviewTempFile(String id, String type) {
744                    return getPreviewTempFile(id, 0, type);
745            }
746    
747            protected int getPreviewTempFileCount(FileVersion fileVersion) {
748                    return getPreviewTempFileCount(fileVersion, getPreviewType());
749            }
750    
751            protected int getPreviewTempFileCount(
752                    FileVersion fileVersion, String type) {
753    
754                    String tempFileId = DLUtil.getTempFileId(
755                            fileVersion.getFileEntryId(), fileVersion.getVersion());
756    
757                    StringBundler sb = new StringBundler(5);
758    
759                    sb.append(tempFileId);
760                    sb.append(StringPool.DASH);
761                    sb.append("(.*)");
762    
763                    if (Validator.isNotNull(type)) {
764                            sb.append(StringPool.PERIOD);
765                            sb.append(type);
766                    }
767    
768                    File dir = new File(PREVIEW_TMP_PATH);
769    
770                    File[] files = dir.listFiles(new FileFilter(sb.toString()));
771    
772                    if (_log.isDebugEnabled()) {
773                            for (File file : files) {
774                                    _log.debug("Preview page for " + tempFileId + " " + file);
775                            }
776                    }
777    
778                    return files.length;
779            }
780    
781            protected String getPreviewTempFilePath(String id) {
782                    return getPreviewTempFilePath(id, 0);
783            }
784    
785            protected String getPreviewTempFilePath(String id, int index) {
786                    return getPreviewTempFilePath(id, index, getPreviewType());
787            }
788    
789            protected String getPreviewTempFilePath(String id, int index, String type) {
790                    StringBundler sb = null;
791    
792                    if (index > 0) {
793                            sb = new StringBundler(6);
794                    }
795                    else {
796                            sb = new StringBundler(4);
797                    }
798    
799                    sb.append(PREVIEW_TMP_PATH);
800                    sb.append(id);
801    
802                    if (index > 0) {
803                            sb.append(StringPool.DASH);
804                            sb.append(index - 1);
805                    }
806                    else if (index == -1) {
807                            sb.append("-%d");
808                    }
809    
810                    if (Validator.isNotNull(type)) {
811                            sb.append(StringPool.PERIOD);
812                            sb.append(type);
813                    }
814    
815                    return sb.toString();
816            }
817    
818            protected String getPreviewTempFilePath(String id, String type) {
819                    return getPreviewTempFilePath(id, 0, type);
820            }
821    
822            protected String getPreviewType() {
823                    return getPreviewType(null);
824            }
825    
826            protected abstract String getPreviewType(FileVersion fileVersion);
827    
828            protected String getPreviewType(int index) {
829                    String[] previewTypes = getPreviewTypes();
830    
831                    if ((previewTypes != null) && (previewTypes.length > index)) {
832                            return previewTypes[index];
833                    }
834                    else {
835                            return getPreviewType();
836                    }
837            }
838    
839            protected String[] getPreviewTypes() {
840                    return new String[] {getPreviewType()};
841            }
842    
843            protected String getThumbnailFilePath(FileVersion fileVersion, int index) {
844                    return getThumbnailFilePath(fileVersion, getThumbnailType(), index);
845            }
846    
847            protected String getThumbnailFilePath(
848                    FileVersion fileVersion, String type, int index) {
849    
850                    return getThumbnailFilePath(
851                            fileVersion.getGroupId(), fileVersion.getFileEntryId(),
852                            fileVersion.getFileVersionId(), type, index);
853            }
854    
855            protected String getThumbnailFilePath(
856                    long groupId, long fileEntryId, long fileVersionId,
857                    String thumbnailType, int index) {
858    
859                    StringBundler sb = new StringBundler(5);
860    
861                    sb.append(getPathSegment(groupId, fileEntryId, fileVersionId, false));
862    
863                    if (index != THUMBNAIL_INDEX_DEFAULT) {
864                            sb.append(StringPool.DASH);
865                            sb.append(index);
866                    }
867    
868                    if ((fileVersionId > 0) && Validator.isNotNull(thumbnailType)) {
869                            sb.append(StringPool.PERIOD);
870                            sb.append(thumbnailType);
871                    }
872    
873                    return sb.toString();
874            }
875    
876            protected File getThumbnailTempFile(String id) {
877                    return getThumbnailTempFile(id, getThumbnailType());
878            }
879    
880            protected File getThumbnailTempFile(String id, String type) {
881                    String thumbnailTempFilePath = getThumbnailTempFilePath(id, type);
882    
883                    return new File(thumbnailTempFilePath);
884            }
885    
886            protected String getThumbnailTempFilePath(String id) {
887                    return getThumbnailTempFilePath(id, getThumbnailType());
888            }
889    
890            protected String getThumbnailTempFilePath(String id, String type) {
891                    StringBundler sb = new StringBundler(4);
892    
893                    sb.append(THUMBNAIL_TMP_PATH);
894                    sb.append(id);
895    
896                    if (Validator.isNotNull(type)) {
897                            sb.append(StringPool.PERIOD);
898                            sb.append(type);
899                    }
900    
901                    return sb.toString();
902            }
903    
904            protected String getThumbnailType() {
905                    return getThumbnailType(null);
906            }
907    
908            protected abstract String getThumbnailType(FileVersion fileVersion);
909    
910            protected boolean hasPreview(FileVersion fileVersion, String type)
911                    throws Exception {
912    
913                    String previewFilePath = getPreviewFilePath(fileVersion, type);
914    
915                    if (DLStoreUtil.hasFile(
916                                    fileVersion.getCompanyId(), REPOSITORY_ID, previewFilePath)) {
917    
918                            return true;
919                    }
920                    else {
921                            return false;
922                    }
923            }
924    
925            protected boolean hasPreviews(FileVersion fileVersion) throws Exception {
926                    int count = 0;
927    
928                    String[] previewTypes = getPreviewTypes();
929    
930                    for (String previewType : previewTypes) {
931                            if (hasPreview(fileVersion, previewType)) {
932                                    count++;
933                            }
934                    }
935    
936                    if (count == previewTypes.length) {
937                            return true;
938                    }
939                    else {
940                            return false;
941                    }
942            }
943    
944            protected boolean hasThumbnail(FileVersion fileVersion, int index) {
945                    try {
946                            String imageType = getThumbnailType(fileVersion);
947    
948                            return DLStoreUtil.hasFile(
949                                    fileVersion.getCompanyId(), REPOSITORY_ID,
950                                    getThumbnailFilePath(fileVersion, imageType, index));
951                    }
952                    catch (Exception e) {
953                            _log.error(e, e);
954                    }
955    
956                    return false;
957            }
958    
959            protected boolean hasThumbnails(FileVersion fileVersion) {
960                    if ((isThumbnailEnabled(THUMBNAIL_INDEX_DEFAULT) &&
961                             !hasThumbnail(fileVersion, THUMBNAIL_INDEX_DEFAULT)) ||
962                            (isThumbnailEnabled(THUMBNAIL_INDEX_CUSTOM_1) &&
963                             !hasThumbnail(fileVersion, THUMBNAIL_INDEX_CUSTOM_1)) ||
964                            (isThumbnailEnabled(THUMBNAIL_INDEX_CUSTOM_2) &&
965                             !hasThumbnail(fileVersion, THUMBNAIL_INDEX_CUSTOM_2))) {
966    
967                            return false;
968                    }
969    
970                    return true;
971            }
972    
973            protected void importPreview(
974                            PortletDataContext portletDataContext, FileEntry fileEntry,
975                            FileEntry importedFileEntry, Element fileEntryElement,
976                            String binPathSuffix, String previewType)
977                    throws Exception {
978    
979                    importPreview(
980                            portletDataContext, fileEntry, importedFileEntry, fileEntryElement,
981                            binPathSuffix, previewType, -1);
982            }
983    
984            protected void importPreview(
985                            PortletDataContext portletDataContext, FileEntry fileEntry,
986                            FileEntry importedFileEntry, Element fileEntryElement,
987                            String binPathSuffix, String previewType, int fileIndex)
988                    throws Exception {
989    
990                    if (!portletDataContext.isPerformDirectBinaryImport()) {
991                            importPreviewFromLAR(
992                                    portletDataContext, importedFileEntry, fileEntryElement,
993                                    binPathSuffix, previewType, fileIndex);
994                    }
995                    else {
996                            FileVersion importedFileVersion =
997                                    importedFileEntry.getFileVersion();
998    
999                            String previewFilePath = getPreviewFilePath(
1000                                    importedFileVersion, previewType);
1001    
1002                            FileVersion fileVersion = fileEntry.getFileVersion();
1003    
1004                            if (!hasPreview(fileVersion, previewType)) {
1005                                    return;
1006                            }
1007    
1008                            InputStream is = null;
1009    
1010                            try {
1011                                    if (fileIndex < 0) {
1012                                            is = doGetPreviewAsStream(fileVersion, previewType);
1013                                    }
1014                                    else {
1015                                            is = doGetPreviewAsStream(
1016                                                    fileVersion, fileIndex, previewType);
1017                                    }
1018    
1019                                    addFileToStore(
1020                                            portletDataContext.getCompanyId(), PREVIEW_PATH,
1021                                            previewFilePath, is);
1022                            }
1023                            finally {
1024                                    StreamUtil.cleanUp(is);
1025                            }
1026                    }
1027            }
1028    
1029            protected void importPreviewFromLAR(
1030                            PortletDataContext portletDataContext, FileEntry fileEntry,
1031                            Element fileEntryElement, String binPathSuffix, String previewType,
1032                            int fileIndex)
1033                    throws Exception {
1034    
1035                    FileVersion fileVersion = fileEntry.getFileVersion();
1036    
1037                    String binPathSegment = null;
1038    
1039                    if (fileIndex < 0) {
1040                            binPathSegment = previewType;
1041                    }
1042                    else {
1043                            binPathSegment = Integer.toString(fileIndex + 1);
1044                    }
1045    
1046                    StringBundler sb = new StringBundler(4);
1047    
1048                    sb.append("bin-path-preview-");
1049                    sb.append(binPathSegment);
1050                    sb.append("-");
1051                    sb.append(binPathSuffix);
1052    
1053                    String binPathName = sb.toString();
1054    
1055                    String binPath = fileEntryElement.attributeValue(binPathName);
1056    
1057                    InputStream is = null;
1058    
1059                    try {
1060                            is = portletDataContext.getZipEntryAsInputStream(binPath);
1061    
1062                            if (is == null) {
1063                                    return;
1064                            }
1065    
1066                            String previewFilePath = null;
1067    
1068                            if (fileIndex < 0) {
1069                                    previewFilePath = getPreviewFilePath(fileVersion, previewType);
1070                            }
1071                            else {
1072                                    previewFilePath = getPreviewFilePath(
1073                                            fileVersion, fileIndex + 1);
1074                            }
1075    
1076                            addFileToStore(
1077                                    portletDataContext.getCompanyId(), PREVIEW_PATH,
1078                                    previewFilePath, is);
1079                    }
1080                    finally {
1081                            StreamUtil.cleanUp(is);
1082                    }
1083            }
1084    
1085            protected void importThumbnail(
1086                            PortletDataContext portletDataContext, FileEntry fileEntry,
1087                            FileEntry importedFileEntry, Element fileEntryElement,
1088                            String binPathName, int index)
1089                    throws Exception {
1090    
1091                    if (!isThumbnailEnabled(index)) {
1092                            return;
1093                    }
1094    
1095                    if (!portletDataContext.isPerformDirectBinaryImport()) {
1096                            importThumbnailFromLAR(
1097                                    portletDataContext, importedFileEntry, fileEntryElement,
1098                                    binPathName, index);
1099                    }
1100                    else {
1101                            FileVersion fileVersion = fileEntry.getFileVersion();
1102    
1103                            if (!hasThumbnail(fileVersion, index)) {
1104                                    return;
1105                            }
1106    
1107                            InputStream is = null;
1108    
1109                            try {
1110                                    is = doGetThumbnailAsStream(fileVersion, index);
1111    
1112                                    FileVersion importedFileVersion =
1113                                            importedFileEntry.getFileVersion();
1114    
1115                                    String thumbnailFilePath = getThumbnailFilePath(
1116                                            importedFileVersion, getThumbnailType(importedFileVersion),
1117                                            index);
1118    
1119                                    addFileToStore(
1120                                            portletDataContext.getCompanyId(), THUMBNAIL_PATH,
1121                                            thumbnailFilePath, is);
1122                            }
1123                            finally {
1124                                    StreamUtil.cleanUp(is);
1125                            }
1126                    }
1127            }
1128    
1129            protected void importThumbnailFromLAR(
1130                            PortletDataContext portletDataContext, FileEntry fileEntry,
1131                            Element fileEntryElement, String binPathName, int index)
1132                    throws Exception {
1133    
1134                    FileVersion fileVersion = fileEntry.getFileVersion();
1135    
1136                    String binPath = fileEntryElement.attributeValue(binPathName);
1137    
1138                    InputStream is = null;
1139    
1140                    try {
1141                            is = portletDataContext.getZipEntryAsInputStream(binPath);
1142    
1143                            if (is == null) {
1144                                    return;
1145                            }
1146    
1147                            String thumbnailFilePath = getThumbnailFilePath(
1148                                    fileVersion, getThumbnailType(fileVersion), index);
1149    
1150                            addFileToStore(
1151                                    portletDataContext.getCompanyId(), THUMBNAIL_PATH,
1152                                    thumbnailFilePath, is);
1153                    }
1154                    finally {
1155                            StreamUtil.cleanUp(is);
1156                    }
1157            }
1158    
1159            protected void importThumbnails(
1160                            PortletDataContext portletDataContext, FileEntry fileEntry,
1161                            FileEntry importedFileEntry, Element fileEntryElement,
1162                            String binPathSuffix)
1163                    throws Exception {
1164    
1165                    importThumbnail(
1166                            portletDataContext, fileEntry, importedFileEntry, fileEntryElement,
1167                            "bin-path-thumbnail-default-" + binPathSuffix,
1168                            THUMBNAIL_INDEX_DEFAULT);
1169                    importThumbnail(
1170                            portletDataContext, fileEntry, importedFileEntry, fileEntryElement,
1171                            "bin-path-thumbnail-custom-1-" + binPathSuffix,
1172                            THUMBNAIL_INDEX_CUSTOM_1);
1173                    importThumbnail(
1174                            portletDataContext, fileEntry, importedFileEntry, fileEntryElement,
1175                            "bin-path-thumbnail-custom-2-" + binPathSuffix,
1176                            THUMBNAIL_INDEX_CUSTOM_2);
1177            }
1178    
1179            protected boolean isThumbnailEnabled(int index) {
1180                    if ((index == THUMBNAIL_INDEX_DEFAULT) &&
1181                            GetterUtil.getBoolean(
1182                                    PropsUtil.get(PropsKeys.DL_FILE_ENTRY_THUMBNAIL_ENABLED))) {
1183    
1184                            return true;
1185                    }
1186                    else if ((index == THUMBNAIL_INDEX_CUSTOM_1) &&
1187                                     ((PrefsPropsUtil.getInteger(
1188                                             PropsKeys.
1189                                                     DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_HEIGHT) > 0) ||
1190                                      (PrefsPropsUtil.getInteger(
1191                                              PropsKeys.
1192                                                      DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_WIDTH) > 0))) {
1193    
1194                            return true;
1195                    }
1196                    else if ((index == THUMBNAIL_INDEX_CUSTOM_2) &&
1197                                     ((PrefsPropsUtil.getInteger(
1198                                             PropsKeys.
1199                                                     DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_HEIGHT) > 0) ||
1200                                      (PrefsPropsUtil.getInteger(
1201                                              PropsKeys.
1202                                                      DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_WIDTH) > 0))) {
1203    
1204                            return true;
1205                    }
1206    
1207                    return false;
1208            }
1209    
1210            protected void sendGenerationMessage(
1211                    String destinationName, FileVersion sourceFileVersion,
1212                    FileVersion destinationFileVersion) {
1213    
1214                    Object[] payload = {sourceFileVersion, destinationFileVersion};
1215    
1216                    MessageBusUtil.sendMessage(destinationName, payload);
1217            }
1218    
1219            protected void storeThumbnailImage(
1220                            FileVersion fileVersion, RenderedImage renderedImage, int index)
1221                    throws Exception {
1222    
1223                    if (!isThumbnailEnabled(index) || hasThumbnail(fileVersion, index)) {
1224                            return;
1225                    }
1226    
1227                    String type = getThumbnailType(fileVersion);
1228    
1229                    String maxHeightPropsKey = PropsKeys.DL_FILE_ENTRY_THUMBNAIL_MAX_HEIGHT;
1230                    String maxWidthPropsKey = PropsKeys.DL_FILE_ENTRY_THUMBNAIL_MAX_WIDTH;
1231    
1232                    if (index == THUMBNAIL_INDEX_CUSTOM_1) {
1233                            maxHeightPropsKey =
1234                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_HEIGHT;
1235                            maxWidthPropsKey =
1236                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_WIDTH;
1237                    }
1238                    else if (index == THUMBNAIL_INDEX_CUSTOM_2) {
1239                            maxHeightPropsKey =
1240                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_HEIGHT;
1241                            maxWidthPropsKey =
1242                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_WIDTH;
1243                    }
1244    
1245                    RenderedImage thumbnailRenderedImage = ImageToolUtil.scale(
1246                            renderedImage, PrefsPropsUtil.getInteger(maxHeightPropsKey),
1247                            PrefsPropsUtil.getInteger(maxWidthPropsKey));
1248    
1249                    byte[] bytes = ImageToolUtil.getBytes(thumbnailRenderedImage, type);
1250    
1251                    File file = null;
1252    
1253                    try {
1254                            file = FileUtil.createTempFile(bytes);
1255    
1256                            addFileToStore(
1257                                    fileVersion.getCompanyId(), THUMBNAIL_PATH,
1258                                    getThumbnailFilePath(fileVersion, type, index), file);
1259                    }
1260                    finally {
1261                            FileUtil.delete(file);
1262                    }
1263            }
1264    
1265            protected void storeThumbnailImages(FileVersion fileVersion, File file)
1266                    throws Exception {
1267    
1268                    ImageBag imageBag = ImageToolUtil.read(file);
1269    
1270                    RenderedImage renderedImage = imageBag.getRenderedImage();
1271    
1272                    storeThumbnailImages(fileVersion, renderedImage);
1273            }
1274    
1275            protected void storeThumbnailImages(
1276                            FileVersion fileVersion, RenderedImage renderedImage)
1277                    throws Exception {
1278    
1279                    storeThumbnailImage(
1280                            fileVersion, renderedImage, THUMBNAIL_INDEX_DEFAULT);
1281                    storeThumbnailImage(
1282                            fileVersion, renderedImage, THUMBNAIL_INDEX_CUSTOM_1);
1283                    storeThumbnailImage(
1284                            fileVersion, renderedImage, THUMBNAIL_INDEX_CUSTOM_2);
1285            }
1286    
1287            protected Map<String, Future<?>> futures =
1288                    new ConcurrentHashMap<String, Future<?>>();
1289    
1290            private static Log _log = LogFactoryUtil.getLog(
1291                    DLPreviewableProcessor.class);
1292    
1293    }