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