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