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