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.configuration.Filter;
018    import com.liferay.portal.kernel.image.ImageToolUtil;
019    import com.liferay.portal.kernel.lar.PortletDataContext;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.messaging.DestinationNames;
023    import com.liferay.portal.kernel.messaging.MessageBusException;
024    import com.liferay.portal.kernel.messaging.MessageBusUtil;
025    import com.liferay.portal.kernel.process.ClassPathUtil;
026    import com.liferay.portal.kernel.process.ProcessCallable;
027    import com.liferay.portal.kernel.process.ProcessException;
028    import com.liferay.portal.kernel.process.ProcessExecutor;
029    import com.liferay.portal.kernel.repository.model.FileEntry;
030    import com.liferay.portal.kernel.repository.model.FileVersion;
031    import com.liferay.portal.kernel.util.ContentTypes;
032    import com.liferay.portal.kernel.util.FileUtil;
033    import com.liferay.portal.kernel.util.GetterUtil;
034    import com.liferay.portal.kernel.util.MimeTypesUtil;
035    import com.liferay.portal.kernel.util.OSDetector;
036    import com.liferay.portal.kernel.util.PropsKeys;
037    import com.liferay.portal.kernel.util.StreamUtil;
038    import com.liferay.portal.kernel.util.StringBundler;
039    import com.liferay.portal.kernel.util.StringPool;
040    import com.liferay.portal.kernel.util.SystemEnv;
041    import com.liferay.portal.kernel.util.Validator;
042    import com.liferay.portal.kernel.xml.Element;
043    import com.liferay.portal.repository.liferayrepository.model.LiferayFileVersion;
044    import com.liferay.portal.util.PrefsPropsUtil;
045    import com.liferay.portal.util.PropsUtil;
046    import com.liferay.portal.util.PropsValues;
047    import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
048    import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
049    
050    import java.awt.image.BufferedImage;
051    import java.awt.image.RenderedImage;
052    
053    import java.io.File;
054    import java.io.FileInputStream;
055    import java.io.FileOutputStream;
056    import java.io.InputStream;
057    
058    import java.util.Arrays;
059    import java.util.LinkedList;
060    import java.util.List;
061    import java.util.Properties;
062    import java.util.Set;
063    import java.util.Vector;
064    
065    import javax.imageio.ImageIO;
066    
067    import javax.portlet.PortletPreferences;
068    
069    import org.apache.commons.lang.time.StopWatch;
070    import org.apache.pdfbox.pdmodel.PDDocument;
071    import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
072    import org.apache.pdfbox.pdmodel.PDPage;
073    
074    import org.im4java.core.IMOperation;
075    
076    /**
077     * @author Alexander Chow
078     * @author Mika Koivisto
079     * @author Juan Gonz??lez
080     * @author Sergio Gonz??lez
081     */
082    public class PDFProcessorImpl
083            extends DLPreviewableProcessor implements PDFProcessor {
084    
085            @Override
086            public void afterPropertiesSet() throws Exception {
087                    FileUtil.mkdirs(PREVIEW_TMP_PATH);
088                    FileUtil.mkdirs(THUMBNAIL_TMP_PATH);
089    
090                    reset();
091            }
092    
093            @Override
094            public void generateImages(FileVersion fileVersion) throws Exception {
095                    _generateImages(fileVersion);
096            }
097    
098            @Override
099            public String getGlobalSearchPath() throws Exception {
100                    try {
101                            PortletPreferences preferences = PrefsPropsUtil.getPreferences();
102    
103                            String globalSearchPath = preferences.getValue(
104                                    PropsKeys.IMAGEMAGICK_GLOBAL_SEARCH_PATH, null);
105    
106                            if (Validator.isNotNull(globalSearchPath)) {
107                                    return globalSearchPath;
108                            }
109                    }
110                    catch (Exception e) {
111                    }
112    
113                    String filterName = null;
114    
115                    if (OSDetector.isApple()) {
116                            filterName = "apple";
117                    }
118                    else if (OSDetector.isWindows()) {
119                            filterName = "windows";
120                    }
121                    else {
122                            filterName = "unix";
123                    }
124    
125                    return PropsUtil.get(
126                            PropsKeys.IMAGEMAGICK_GLOBAL_SEARCH_PATH, new Filter(filterName));
127            }
128    
129            @Override
130            public InputStream getPreviewAsStream(FileVersion fileVersion, int index)
131                    throws Exception {
132    
133                    return doGetPreviewAsStream(fileVersion, index, PREVIEW_TYPE);
134            }
135    
136            @Override
137            public int getPreviewFileCount(FileVersion fileVersion) {
138                    try {
139                            return doGetPreviewFileCount(fileVersion);
140                    }
141                    catch (Exception e) {
142                            _log.error(e, e);
143                    }
144    
145                    return 0;
146            }
147    
148            @Override
149            public long getPreviewFileSize(FileVersion fileVersion, int index)
150                    throws Exception {
151    
152                    return doGetPreviewFileSize(fileVersion, index);
153            }
154    
155            @Override
156            public Properties getResourceLimitsProperties() throws Exception {
157                    try {
158                            Properties resourceLimitsProperties = PrefsPropsUtil.getProperties(
159                                    PropsKeys.IMAGEMAGICK_RESOURCE_LIMIT, true);
160    
161                            if (!resourceLimitsProperties.isEmpty()) {
162                                    return resourceLimitsProperties;
163                            }
164                    }
165                    catch (Exception e) {
166                    }
167    
168                    return PropsUtil.getProperties(
169                            PropsKeys.IMAGEMAGICK_RESOURCE_LIMIT, true);
170            }
171    
172            @Override
173            public InputStream getThumbnailAsStream(FileVersion fileVersion, int index)
174                    throws Exception {
175    
176                    return doGetThumbnailAsStream(fileVersion, index);
177            }
178    
179            @Override
180            public long getThumbnailFileSize(FileVersion fileVersion, int index)
181                    throws Exception {
182    
183                    return doGetThumbnailFileSize(fileVersion, index);
184            }
185    
186            @Override
187            public boolean hasImages(FileVersion fileVersion) {
188                    boolean hasImages = false;
189    
190                    try {
191                            hasImages = _hasImages(fileVersion);
192    
193                            if (!hasImages && isSupported(fileVersion)) {
194                                    _queueGeneration(fileVersion);
195                            }
196                    }
197                    catch (Exception e) {
198                            _log.error(e, e);
199                    }
200    
201                    return hasImages;
202            }
203    
204            @Override
205            public boolean isDocumentSupported(FileVersion fileVersion) {
206                    return isSupported(fileVersion);
207            }
208    
209            @Override
210            public boolean isDocumentSupported(String mimeType) {
211                    return isSupported(mimeType);
212            }
213    
214            @Override
215            public boolean isImageMagickEnabled() throws Exception {
216                    boolean enabled = false;
217    
218                    try {
219                            enabled = PrefsPropsUtil.getBoolean(PropsKeys.IMAGEMAGICK_ENABLED);
220                    }
221                    catch (Exception e) {
222                            enabled = PropsValues.IMAGEMAGICK_ENABLED;
223                    }
224    
225                    if (!enabled && !_warned) {
226                            StringBundler sb = new StringBundler(6);
227    
228                            sb.append("Liferay is not configured to use ImageMagick. For ");
229                            sb.append("better quality document and image previews, install ");
230                            sb.append("ImageMagick and enable it in portal-ext.properties or ");
231                            sb.append("in the Server Administration control panel at: ");
232                            sb.append("http://<server>/group/control_panel/manage/-/server/");
233                            sb.append("external-services");
234    
235                            _log.warn(sb.toString());
236    
237                            _warned = true;
238                    }
239    
240                    return enabled;
241            }
242    
243            @Override
244            public boolean isSupported(String mimeType) {
245                    if (Validator.isNull(mimeType)) {
246                            return false;
247                    }
248    
249                    if (mimeType.equals(ContentTypes.APPLICATION_PDF) ||
250                            mimeType.equals(ContentTypes.APPLICATION_X_PDF)) {
251    
252                            return true;
253                    }
254    
255                    if (DocumentConversionUtil.isEnabled()) {
256                            Set<String> extensions = MimeTypesUtil.getExtensions(mimeType);
257    
258                            for (String extension : extensions) {
259                                    extension = extension.substring(1);
260    
261                                    String[] targetExtensions =
262                                            DocumentConversionUtil.getConversions(extension);
263    
264                                    if (Arrays.binarySearch(targetExtensions, "pdf") >= 0) {
265                                            return true;
266                                    }
267                            }
268                    }
269    
270                    return false;
271            }
272    
273            @Override
274            public void reset() throws Exception {
275                    if (isImageMagickEnabled()) {
276                            _globalSearchPath = getGlobalSearchPath();
277    
278                            _resourceLimitsProperties = getResourceLimitsProperties();
279                    }
280            }
281    
282            @Override
283            public void trigger(FileVersion fileVersion) {
284                    _queueGeneration(fileVersion);
285            }
286    
287            @Override
288            protected void doExportGeneratedFiles(
289                            PortletDataContext portletDataContext, FileEntry fileEntry,
290                            Element fileEntryElement)
291                    throws Exception {
292    
293                    exportThumbnails(
294                            portletDataContext, fileEntry, fileEntryElement, "pdf");
295    
296                    exportPreviews(portletDataContext, fileEntry, fileEntryElement);
297            }
298    
299            @Override
300            protected void doImportGeneratedFiles(
301                            PortletDataContext portletDataContext, FileEntry fileEntry,
302                            FileEntry importedFileEntry, Element fileEntryElement)
303                    throws Exception {
304    
305                    importThumbnails(
306                            portletDataContext, fileEntry, importedFileEntry, fileEntryElement,
307                            "pdf");
308    
309                    importPreviews(
310                            portletDataContext, fileEntry, importedFileEntry, fileEntryElement);
311            }
312    
313            protected void exportPreviews(
314                            PortletDataContext portletDataContext, FileEntry fileEntry,
315                            Element fileEntryElement)
316                    throws Exception {
317    
318                    FileVersion fileVersion = fileEntry.getFileVersion();
319    
320                    if (!isSupported(fileVersion) || !_hasImages(fileVersion)) {
321                            return;
322                    }
323    
324                    if (!portletDataContext.isPerformDirectBinaryImport()) {
325                            int previewFileCount = getPreviewFileCount(fileVersion);
326    
327                            fileEntryElement.addAttribute(
328                                    "bin-path-pdf-preview-count", String.valueOf(previewFileCount));
329    
330                            for (int i = 0; i < previewFileCount; i++) {
331                                    exportPreview(
332                                            portletDataContext, fileEntry, fileEntryElement, "pdf",
333                                            PREVIEW_TYPE, i);
334                            }
335                    }
336            }
337    
338            @Override
339            protected String getPreviewType(FileVersion fileVersion) {
340                    return PREVIEW_TYPE;
341            }
342    
343            @Override
344            protected String getThumbnailType(FileVersion fileVersion) {
345                    return THUMBNAIL_TYPE;
346            }
347    
348            protected void importPreviews(
349                            PortletDataContext portletDataContext, FileEntry fileEntry,
350                            FileEntry importedFileEntry, Element fileEntryElement)
351                    throws Exception {
352    
353                    int previewFileCount = GetterUtil.getInteger(
354                            fileEntryElement.attributeValue("bin-path-pdf-preview-count"));
355    
356                    for (int i = 0; i < previewFileCount; i++) {
357                            importPreview(
358                                    portletDataContext, fileEntry, importedFileEntry,
359                                    fileEntryElement, "pdf", PREVIEW_TYPE, i);
360                    }
361            }
362    
363            private void _generateImages(FileVersion fileVersion) throws Exception {
364                    InputStream inputStream = null;
365    
366                    try {
367                            if (_hasImages(fileVersion)) {
368                                    return;
369                            }
370    
371                            String extension = fileVersion.getExtension();
372    
373                            if (extension.equals("pdf")) {
374                                    if (fileVersion instanceof LiferayFileVersion) {
375                                            try {
376                                                    LiferayFileVersion liferayFileVersion =
377                                                            (LiferayFileVersion)fileVersion;
378    
379                                                    File file = liferayFileVersion.getFile(false);
380    
381                                                    _generateImages(fileVersion, file);
382    
383                                                    return;
384                                            }
385                                            catch (UnsupportedOperationException uoe) {
386                                            }
387                                    }
388    
389                                    inputStream = fileVersion.getContentStream(false);
390    
391                                    _generateImages(fileVersion, inputStream);
392                            }
393                            else if (DocumentConversionUtil.isEnabled()) {
394                                    inputStream = fileVersion.getContentStream(false);
395    
396                                    String tempFileId = DLUtil.getTempFileId(
397                                            fileVersion.getFileEntryId(), fileVersion.getVersion());
398    
399                                    File file = DocumentConversionUtil.convert(
400                                            tempFileId, inputStream, extension, "pdf");
401    
402                                    _generateImages(fileVersion, file);
403                            }
404                    }
405                    catch (NoSuchFileEntryException nsfee) {
406                    }
407                    finally {
408                            StreamUtil.cleanUp(inputStream);
409    
410                            _fileVersionIds.remove(fileVersion.getFileVersionId());
411                    }
412            }
413    
414            private void _generateImages(FileVersion fileVersion, File file)
415                    throws Exception {
416    
417                    if (isImageMagickEnabled()) {
418                            _generateImagesIM(fileVersion, file);
419                    }
420                    else {
421                            _generateImagesPB(fileVersion, file);
422                    }
423            }
424    
425            private void _generateImages(
426                            FileVersion fileVersion, InputStream inputStream)
427                    throws Exception {
428    
429                    if (isImageMagickEnabled()) {
430                            _generateImagesIM(fileVersion, inputStream);
431                    }
432                    else {
433                            _generateImagesPB(fileVersion, inputStream);
434                    }
435            }
436    
437            private void _generateImagesIM(FileVersion fileVersion, File file)
438                    throws Exception {
439    
440                    if (_isGeneratePreview(fileVersion)) {
441                            StopWatch stopWatch = null;
442    
443                            if (_log.isInfoEnabled()) {
444                                    stopWatch = new StopWatch();
445    
446                                    stopWatch.start();
447                            }
448    
449                            _generateImagesIM(fileVersion, file, false);
450    
451                            if (_log.isInfoEnabled()) {
452                                    int previewFileCount = getPreviewFileCount(fileVersion);
453    
454                                    _log.info(
455                                            "ImageMagick generated " + previewFileCount +
456                                                    " preview pages for " + fileVersion.getTitle() +
457                                                            " in " + stopWatch);
458                            }
459                    }
460    
461                    if (_isGenerateThumbnail(fileVersion)) {
462                            StopWatch stopWatch = null;
463    
464                            if (_log.isInfoEnabled()) {
465                                    stopWatch = new StopWatch();
466    
467                                    stopWatch.start();
468                            }
469    
470                            _generateImagesIM(fileVersion, file, true);
471    
472                            if (_log.isInfoEnabled()) {
473                                    _log.info(
474                                            "ImageMagick generated a thumbnail for " +
475                                                    fileVersion.getTitle() + " in " + stopWatch);
476                            }
477                    }
478            }
479    
480            private void _generateImagesIM(
481                            FileVersion fileVersion, File file, boolean thumbnail)
482                    throws Exception {
483    
484                    // Generate images
485    
486                    String tempFileId = DLUtil.getTempFileId(
487                            fileVersion.getFileEntryId(), fileVersion.getVersion());
488    
489                    IMOperation imOperation = new IMOperation();
490    
491                    imOperation.alpha("off");
492    
493                    imOperation.density(
494                            PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_DPI,
495                            PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_DPI);
496    
497                    if (PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_HEIGHT != 0) {
498                            imOperation.adaptiveResize(
499                                    PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_WIDTH,
500                                    PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_HEIGHT);
501                    }
502                    else {
503                            imOperation.adaptiveResize(
504                                    PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_WIDTH);
505                    }
506    
507                    imOperation.depth(PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_DEPTH);
508    
509                    if (thumbnail) {
510                            imOperation.addImage(file.getPath() + "[0]");
511                            imOperation.addImage(getThumbnailTempFilePath(tempFileId));
512                    }
513                    else {
514                            imOperation.addImage(file.getPath());
515                            imOperation.addImage(getPreviewTempFilePath(tempFileId, -1));
516                    }
517    
518                    if (PropsValues.DL_FILE_ENTRY_PREVIEW_FORK_PROCESS_ENABLED) {
519                            ProcessCallable<String> processCallable =
520                                    new ImageMagickProcessCallable(
521                                            _globalSearchPath, _resourceLimitsProperties,
522                                            imOperation.getCmdArgs());
523    
524                            ProcessExecutor.execute(
525                                    processCallable, ClassPathUtil.getPortalClassPath());
526                    }
527                    else {
528                            LiferayConvertCmd.run(
529                                    _globalSearchPath, _resourceLimitsProperties,
530                                    imOperation.getCmdArgs());
531                    }
532    
533                    // Store images
534    
535                    if (thumbnail) {
536                            File thumbnailTempFile = getThumbnailTempFile(tempFileId);
537    
538                            try {
539                                    storeThumbnailImages(fileVersion, thumbnailTempFile);
540                            }
541                            finally {
542                                    FileUtil.delete(thumbnailTempFile);
543                            }
544                    }
545                    else {
546    
547                            // ImageMagick converts single page PDFs without appending an index.
548                            // Rename file for consistency.
549    
550                            File singlePagePreviewFile = getPreviewTempFile(tempFileId, -1);
551    
552                            if (singlePagePreviewFile.exists()) {
553                                    singlePagePreviewFile.renameTo(
554                                            getPreviewTempFile(tempFileId, 1));
555                            }
556    
557                            int total = getPreviewTempFileCount(fileVersion);
558    
559                            for (int i = 0; i < total; i++) {
560                                    File previewTempFile = getPreviewTempFile(tempFileId, i + 1);
561    
562                                    try {
563                                            addFileToStore(
564                                                    fileVersion.getCompanyId(), PREVIEW_PATH,
565                                                    getPreviewFilePath(fileVersion, i + 1),
566                                                    previewTempFile);
567                                    }
568                                    finally {
569                                            FileUtil.delete(previewTempFile);
570                                    }
571                            }
572                    }
573            }
574    
575            private void _generateImagesIM(
576                            FileVersion fileVersion, InputStream inputStream)
577                    throws Exception {
578    
579                    File file = null;
580    
581                    try {
582                            file = FileUtil.createTempFile(inputStream);
583    
584                            _generateImagesIM(fileVersion, file);
585                    }
586                    finally {
587                            FileUtil.delete(file);
588                    }
589            }
590    
591            private void _generateImagesPB(FileVersion fileVersion, File file)
592                    throws Exception {
593    
594                    _generateImagesPB(fileVersion, new FileInputStream(file));
595            }
596    
597            private void _generateImagesPB(
598                            FileVersion fileVersion, InputStream inputStream)
599                    throws Exception {
600    
601                    boolean generatePreview = _isGeneratePreview(fileVersion);
602                    boolean generateThumbnail = _isGenerateThumbnail(fileVersion);
603    
604                    PDDocument pdDocument = null;
605    
606                    try {
607                            pdDocument = PDDocument.load(inputStream);
608    
609                            PDDocumentCatalog pdDocumentCatalog =
610                                    pdDocument.getDocumentCatalog();
611    
612                            List<PDPage> pdPages = pdDocumentCatalog.getAllPages();
613    
614                            for (int i = 0; i < pdPages.size(); i++) {
615                                    PDPage pdPage = pdPages.get(i);
616    
617                                    if (generateThumbnail && (i == 0)) {
618                                            _generateImagesPB(fileVersion, pdPage, i);
619    
620                                            if (_log.isInfoEnabled()) {
621                                                    _log.info(
622                                                            "PDFBox generated a thumbnail for " +
623                                                                    fileVersion.getFileVersionId());
624                                            }
625                                    }
626    
627                                    if (!generatePreview) {
628                                            break;
629                                    }
630    
631                                    _generateImagesPB(fileVersion, pdPage, i + 1);
632                            }
633    
634                            if (_log.isInfoEnabled() && generatePreview) {
635                                    _log.info(
636                                            "PDFBox generated " +
637                                                    getPreviewFileCount(fileVersion) +
638                                                            " preview pages for " +
639                                                                    fileVersion.getFileVersionId());
640                            }
641                    }
642                    finally {
643                            if (pdDocument != null) {
644                                    pdDocument.close();
645                            }
646                    }
647            }
648    
649            private void _generateImagesPB(
650                            FileVersion fileVersion, PDPage pdPage, int index)
651                    throws Exception {
652    
653                    // Generate images
654    
655                    RenderedImage renderedImage = pdPage.convertToImage(
656                            BufferedImage.TYPE_INT_RGB,
657                            PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_DPI);
658    
659                    if (PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_HEIGHT != 0) {
660                            renderedImage = ImageToolUtil.scale(
661                                    renderedImage,
662                                    PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_WIDTH,
663                                    PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_HEIGHT);
664                    }
665                    else {
666                            renderedImage = ImageToolUtil.scale(
667                                    renderedImage,
668                                    PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_WIDTH);
669                    }
670    
671                    // Store images
672    
673                    if (index == 0) {
674                            storeThumbnailImages(fileVersion, renderedImage);
675                    }
676                    else {
677                            File tempFile = null;
678    
679                            try {
680                                    String tempFileId = DLUtil.getTempFileId(
681                                            fileVersion.getFileEntryId(), fileVersion.getVersion());
682    
683                                    tempFile = getPreviewTempFile(tempFileId, index);
684    
685                                    tempFile.createNewFile();
686    
687                                    ImageIO.write(
688                                            renderedImage, PREVIEW_TYPE,
689                                            new FileOutputStream(tempFile));
690    
691                                    addFileToStore(
692                                            fileVersion.getCompanyId(), PREVIEW_PATH,
693                                            getPreviewFilePath(fileVersion, index), tempFile);
694                            }
695                            finally {
696                                    FileUtil.delete(tempFile);
697                            }
698                    }
699            }
700    
701            private boolean _hasImages(FileVersion fileVersion) throws Exception {
702                    if (PropsValues.DL_FILE_ENTRY_PREVIEW_ENABLED) {
703                            if (!DLStoreUtil.hasFile(
704                                            fileVersion.getCompanyId(), REPOSITORY_ID,
705                                            getPreviewFilePath(fileVersion, 1))) {
706    
707                                    return false;
708                            }
709                    }
710    
711                    return hasThumbnails(fileVersion);
712            }
713    
714            private boolean _isGeneratePreview(FileVersion fileVersion)
715                    throws Exception {
716    
717                    String previewFilePath = getPreviewFilePath(fileVersion, 1);
718    
719                    if (PropsValues.DL_FILE_ENTRY_PREVIEW_ENABLED &&
720                            !DLStoreUtil.hasFile(
721                                    fileVersion.getCompanyId(), REPOSITORY_ID, previewFilePath)) {
722    
723                            return true;
724                    }
725                    else {
726                            return false;
727                    }
728            }
729    
730            private boolean _isGenerateThumbnail(FileVersion fileVersion)
731                    throws Exception {
732    
733                    String thumbnailFilePath = getThumbnailFilePath(
734                            fileVersion, THUMBNAIL_INDEX_DEFAULT);
735    
736                    if (PropsValues.DL_FILE_ENTRY_THUMBNAIL_ENABLED &&
737                            !DLStoreUtil.hasFile(
738                                    fileVersion.getCompanyId(), REPOSITORY_ID, thumbnailFilePath)) {
739    
740                            return true;
741                    }
742                    else {
743                            return false;
744                    }
745            }
746    
747            private void _queueGeneration(FileVersion fileVersion) {
748                    if (_fileVersionIds.contains(fileVersion.getFileVersionId())) {
749                            return;
750                    }
751    
752                    boolean generateImages = false;
753    
754                    String extension = fileVersion.getExtension();
755    
756                    if (extension.equals("pdf")) {
757                            generateImages = true;
758                    }
759                    else if (DocumentConversionUtil.isEnabled()) {
760                            String[] conversions = DocumentConversionUtil.getConversions(
761                                    extension);
762    
763                            for (String conversion : conversions) {
764                                    if (conversion.equals("pdf")) {
765                                            generateImages = true;
766    
767                                            break;
768                                    }
769                            }
770                    }
771    
772                    if (generateImages) {
773                            _fileVersionIds.add(fileVersion.getFileVersionId());
774    
775                            if (PropsValues.DL_FILE_ENTRY_PROCESSORS_TRIGGER_SYNCHRONOUSLY) {
776                                    try {
777                                            MessageBusUtil.sendSynchronousMessage(
778                                                    DestinationNames.DOCUMENT_LIBRARY_PDF_PROCESSOR,
779                                                    fileVersion);
780                                    }
781                                    catch (MessageBusException mbe) {
782                                            if (_log.isWarnEnabled()) {
783                                                    _log.warn(mbe, mbe);
784                                            }
785                                    }
786                            }
787                            else {
788                                    MessageBusUtil.sendMessage(
789                                            DestinationNames.DOCUMENT_LIBRARY_PDF_PROCESSOR,
790                                            fileVersion);
791                            }
792                    }
793            }
794    
795            private static Log _log = LogFactoryUtil.getLog(PDFProcessorImpl.class);
796    
797            private List<Long> _fileVersionIds = new Vector<Long>();
798            private String _globalSearchPath;
799            private Properties _resourceLimitsProperties;
800            private boolean _warned;
801    
802            private static class ImageMagickProcessCallable
803                    implements ProcessCallable<String> {
804    
805                    public ImageMagickProcessCallable(
806                            String globalSearchPath, Properties resourceLimits,
807                            LinkedList<String> commandArguments) {
808    
809                            _globalSearchPath = globalSearchPath;
810                            _commandArguments = commandArguments;
811                            _resourceLimits = resourceLimits;
812                    }
813    
814                    public String call() throws ProcessException {
815                            Properties systemProperties = System.getProperties();
816    
817                            SystemEnv.setProperties(systemProperties);
818    
819                            try {
820                                    LiferayConvertCmd.run(
821                                            _globalSearchPath, _resourceLimits, _commandArguments);
822                            }
823                            catch (Exception e) {
824                                    throw new ProcessException(e);
825                            }
826    
827                            return StringPool.BLANK;
828                    }
829    
830                    private static final long serialVersionUID = 1L;
831    
832                    private LinkedList<String> _commandArguments;
833                    private String _globalSearchPath;
834                    private Properties _resourceLimits;
835    
836            }
837    
838    }