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.image.GhostscriptUtil;
018    import com.liferay.portal.kernel.lar.PortletDataContext;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.messaging.DestinationNames;
022    import com.liferay.portal.kernel.process.ClassPathUtil;
023    import com.liferay.portal.kernel.process.ProcessCallable;
024    import com.liferay.portal.kernel.process.ProcessException;
025    import com.liferay.portal.kernel.process.ProcessExecutor;
026    import com.liferay.portal.kernel.repository.model.FileEntry;
027    import com.liferay.portal.kernel.repository.model.FileVersion;
028    import com.liferay.portal.kernel.util.ContentTypes;
029    import com.liferay.portal.kernel.util.FileUtil;
030    import com.liferay.portal.kernel.util.GetterUtil;
031    import com.liferay.portal.kernel.util.MimeTypesUtil;
032    import com.liferay.portal.kernel.util.PropsKeys;
033    import com.liferay.portal.kernel.util.ServerDetector;
034    import com.liferay.portal.kernel.util.StreamUtil;
035    import com.liferay.portal.kernel.util.StringPool;
036    import com.liferay.portal.kernel.util.SystemEnv;
037    import com.liferay.portal.kernel.util.Validator;
038    import com.liferay.portal.kernel.xml.Element;
039    import com.liferay.portal.log.Log4jLogFactoryImpl;
040    import com.liferay.portal.repository.liferayrepository.model.LiferayFileVersion;
041    import com.liferay.portal.util.PropsUtil;
042    import com.liferay.portal.util.PropsValues;
043    import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
044    import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
045    import com.liferay.util.log4j.Log4JUtil;
046    
047    import java.io.File;
048    import java.io.InputStream;
049    
050    import java.util.ArrayList;
051    import java.util.Arrays;
052    import java.util.List;
053    import java.util.Map;
054    import java.util.Properties;
055    import java.util.Set;
056    import java.util.Vector;
057    import java.util.concurrent.Future;
058    import java.util.concurrent.TimeUnit;
059    import java.util.concurrent.TimeoutException;
060    
061    import org.apache.commons.lang.time.StopWatch;
062    import org.apache.pdfbox.pdmodel.PDDocument;
063    
064    /**
065     * @author Alexander Chow
066     * @author Mika Koivisto
067     * @author Juan Gonz??lez
068     * @author Sergio Gonz??lez
069     * @author Ivica Cardic
070     */
071    public class PDFProcessorImpl
072            extends DLPreviewableProcessor implements PDFProcessor {
073    
074            @Override
075            public void afterPropertiesSet() throws Exception {
076                    FileUtil.mkdirs(PREVIEW_TMP_PATH);
077                    FileUtil.mkdirs(THUMBNAIL_TMP_PATH);
078            }
079    
080            @Override
081            public void generateImages(
082                            FileVersion sourceFileVersion, FileVersion destinationFileVersion)
083                    throws Exception {
084    
085                    _generateImages(sourceFileVersion, destinationFileVersion);
086            }
087    
088            @Override
089            public InputStream getPreviewAsStream(FileVersion fileVersion, int index)
090                    throws Exception {
091    
092                    return doGetPreviewAsStream(fileVersion, index, PREVIEW_TYPE);
093            }
094    
095            @Override
096            public int getPreviewFileCount(FileVersion fileVersion) {
097                    try {
098                            return doGetPreviewFileCount(fileVersion);
099                    }
100                    catch (Exception e) {
101                            _log.error(e, e);
102                    }
103    
104                    return 0;
105            }
106    
107            @Override
108            public long getPreviewFileSize(FileVersion fileVersion, int index)
109                    throws Exception {
110    
111                    return doGetPreviewFileSize(fileVersion, index);
112            }
113    
114            @Override
115            public InputStream getThumbnailAsStream(FileVersion fileVersion, int index)
116                    throws Exception {
117    
118                    return doGetThumbnailAsStream(fileVersion, index);
119            }
120    
121            @Override
122            public long getThumbnailFileSize(FileVersion fileVersion, int index)
123                    throws Exception {
124    
125                    return doGetThumbnailFileSize(fileVersion, index);
126            }
127    
128            @Override
129            public boolean hasImages(FileVersion fileVersion) {
130                    boolean hasImages = false;
131    
132                    try {
133                            hasImages = _hasImages(fileVersion);
134    
135                            if (!hasImages && isSupported(fileVersion)) {
136                                    _queueGeneration(null, fileVersion);
137                            }
138                    }
139                    catch (Exception e) {
140                            _log.error(e, e);
141                    }
142    
143                    return hasImages;
144            }
145    
146            @Override
147            public boolean isDocumentSupported(FileVersion fileVersion) {
148                    return isSupported(fileVersion);
149            }
150    
151            @Override
152            public boolean isDocumentSupported(String mimeType) {
153                    return isSupported(mimeType);
154            }
155    
156            @Override
157            public boolean isSupported(String mimeType) {
158                    if (Validator.isNull(mimeType)) {
159                            return false;
160                    }
161    
162                    if (mimeType.equals(ContentTypes.APPLICATION_PDF) ||
163                            mimeType.equals(ContentTypes.APPLICATION_X_PDF)) {
164    
165                            return true;
166                    }
167    
168                    if (DocumentConversionUtil.isEnabled()) {
169                            Set<String> extensions = MimeTypesUtil.getExtensions(mimeType);
170    
171                            for (String extension : extensions) {
172                                    extension = extension.substring(1);
173    
174                                    String[] targetExtensions =
175                                            DocumentConversionUtil.getConversions(extension);
176    
177                                    if (Arrays.binarySearch(targetExtensions, "pdf") >= 0) {
178                                            return true;
179                                    }
180                            }
181                    }
182    
183                    return false;
184            }
185    
186            @Override
187            public void trigger(
188                    FileVersion sourceFileVersion, FileVersion destinationFileVersion) {
189    
190                    super.trigger(sourceFileVersion, destinationFileVersion);
191    
192                    _queueGeneration(sourceFileVersion, destinationFileVersion);
193            }
194    
195            @Override
196            protected void copyPreviews(
197                    FileVersion sourceFileVersion, FileVersion destinationFileVersion) {
198    
199                    if (!PropsValues.DL_FILE_ENTRY_PREVIEW_ENABLED) {
200                            return;
201                    }
202    
203                    try {
204                            if (hasPreview(sourceFileVersion) &&
205                                    !hasPreview(destinationFileVersion)) {
206    
207                                    int count = getPreviewFileCount(sourceFileVersion);
208    
209                                    for (int i = 0; i < count; i++) {
210                                            String previewFilePath = getPreviewFilePath(
211                                                    destinationFileVersion, i + 1);
212    
213                                            InputStream is = doGetPreviewAsStream(
214                                                    sourceFileVersion, i + 1, PREVIEW_TYPE);
215    
216                                            addFileToStore(
217                                                    destinationFileVersion.getCompanyId(), PREVIEW_PATH,
218                                                    previewFilePath, is);
219                                    }
220                            }
221                    }
222                    catch (Exception e) {
223                            _log.error(e, e);
224                    }
225            }
226    
227            @Override
228            protected void doExportGeneratedFiles(
229                            PortletDataContext portletDataContext, FileEntry fileEntry,
230                            Element fileEntryElement)
231                    throws Exception {
232    
233                    exportThumbnails(
234                            portletDataContext, fileEntry, fileEntryElement, "pdf");
235    
236                    exportPreviews(portletDataContext, fileEntry, fileEntryElement);
237            }
238    
239            @Override
240            protected void doImportGeneratedFiles(
241                            PortletDataContext portletDataContext, FileEntry fileEntry,
242                            FileEntry importedFileEntry, Element fileEntryElement)
243                    throws Exception {
244    
245                    importThumbnails(
246                            portletDataContext, fileEntry, importedFileEntry, fileEntryElement,
247                            "pdf");
248    
249                    importPreviews(
250                            portletDataContext, fileEntry, importedFileEntry, fileEntryElement);
251            }
252    
253            protected void exportPreviews(
254                            PortletDataContext portletDataContext, FileEntry fileEntry,
255                            Element fileEntryElement)
256                    throws Exception {
257    
258                    FileVersion fileVersion = fileEntry.getFileVersion();
259    
260                    if (!isSupported(fileVersion) || !_hasImages(fileVersion)) {
261                            return;
262                    }
263    
264                    if (!portletDataContext.isPerformDirectBinaryImport()) {
265                            int previewFileCount = getPreviewFileCount(fileVersion);
266    
267                            fileEntryElement.addAttribute(
268                                    "bin-path-pdf-preview-count", String.valueOf(previewFileCount));
269    
270                            for (int i = 0; i < previewFileCount; i++) {
271                                    exportPreview(
272                                            portletDataContext, fileEntry, fileEntryElement, "pdf",
273                                            PREVIEW_TYPE, i);
274                            }
275                    }
276            }
277    
278            @Override
279            protected List<Long> getFileVersionIds() {
280                    return _fileVersionIds;
281            }
282    
283            @Override
284            protected String getPreviewType(FileVersion fileVersion) {
285                    return PREVIEW_TYPE;
286            }
287    
288            @Override
289            protected String getThumbnailType(FileVersion fileVersion) {
290                    return THUMBNAIL_TYPE;
291            }
292    
293            protected boolean hasPreview(FileVersion fileVersion) throws Exception {
294                    return hasPreview(fileVersion, null);
295            }
296    
297            @Override
298            protected boolean hasPreview(FileVersion fileVersion, String type)
299                    throws Exception {
300    
301                    String previewFilePath = getPreviewFilePath(fileVersion, 1);
302    
303                    return DLStoreUtil.hasFile(
304                            fileVersion.getCompanyId(), REPOSITORY_ID, previewFilePath);
305            }
306    
307            protected void importPreviews(
308                            PortletDataContext portletDataContext, FileEntry fileEntry,
309                            FileEntry importedFileEntry, Element fileEntryElement)
310                    throws Exception {
311    
312                    int previewFileCount = GetterUtil.getInteger(
313                            fileEntryElement.attributeValue("bin-path-pdf-preview-count"));
314    
315                    for (int i = 0; i < previewFileCount; i++) {
316                            importPreview(
317                                    portletDataContext, fileEntry, importedFileEntry,
318                                    fileEntryElement, "pdf", PREVIEW_TYPE, i);
319                    }
320            }
321    
322            private void _generateImages(FileVersion fileVersion, File file)
323                    throws Exception {
324    
325                    if (GhostscriptUtil.isEnabled()) {
326                            if (!_ghostscriptInitialized) {
327                                    GhostscriptUtil.reset();
328    
329                                    _ghostscriptInitialized = true;
330                            }
331    
332                            _generateImagesGS(fileVersion, file);
333                    }
334                    else {
335                            _generateImagesPB(fileVersion, file);
336                    }
337            }
338    
339            private void _generateImages(
340                            FileVersion sourceFileVersion, FileVersion destinationFileVersion)
341                    throws Exception {
342    
343                    InputStream inputStream = null;
344    
345                    try {
346                            if (sourceFileVersion != null) {
347                                    copy(sourceFileVersion, destinationFileVersion);
348    
349                                    return;
350                            }
351    
352                            if (_hasImages(destinationFileVersion)) {
353                                    return;
354                            }
355    
356                            String extension = destinationFileVersion.getExtension();
357    
358                            if (extension.equals("pdf")) {
359                                    if (destinationFileVersion instanceof LiferayFileVersion) {
360                                            try {
361                                                    LiferayFileVersion liferayFileVersion =
362                                                            (LiferayFileVersion)destinationFileVersion;
363    
364                                                    File file = liferayFileVersion.getFile(false);
365    
366                                                    _generateImages(destinationFileVersion, file);
367    
368                                                    return;
369                                            }
370                                            catch (UnsupportedOperationException uoe) {
371                                            }
372                                    }
373    
374                                    inputStream = destinationFileVersion.getContentStream(false);
375    
376                                    _generateImages(destinationFileVersion, inputStream);
377                            }
378                            else if (DocumentConversionUtil.isEnabled()) {
379                                    inputStream = destinationFileVersion.getContentStream(false);
380    
381                                    String tempFileId = DLUtil.getTempFileId(
382                                            destinationFileVersion.getFileEntryId(),
383                                            destinationFileVersion.getVersion());
384    
385                                    File file = DocumentConversionUtil.convert(
386                                            tempFileId, inputStream, extension, "pdf");
387    
388                                    _generateImages(destinationFileVersion, file);
389                            }
390                    }
391                    catch (NoSuchFileEntryException nsfee) {
392                    }
393                    finally {
394                            StreamUtil.cleanUp(inputStream);
395    
396                            _fileVersionIds.remove(destinationFileVersion.getFileVersionId());
397                    }
398            }
399    
400            private void _generateImages(
401                            FileVersion fileVersion, InputStream inputStream)
402                    throws Exception {
403    
404                    if (GhostscriptUtil.isEnabled()) {
405                            _generateImagesGS(fileVersion, inputStream);
406                    }
407                    else {
408                            _generateImagesPB(fileVersion, inputStream);
409                    }
410            }
411    
412            private void _generateImagesGS(FileVersion fileVersion, File file)
413                    throws Exception {
414    
415                    if (_isGeneratePreview(fileVersion)) {
416                            StopWatch stopWatch = new StopWatch();
417    
418                            stopWatch.start();
419    
420                            _generateImagesGS(fileVersion, file, false);
421    
422                            if (_log.isInfoEnabled()) {
423                                    int previewFileCount = getPreviewFileCount(fileVersion);
424    
425                                    _log.info(
426                                            "Ghostscript generated " + previewFileCount +
427                                                    " preview pages for " + fileVersion.getTitle() +
428                                                            " in " + stopWatch.getTime() + " ms");
429                            }
430                    }
431    
432                    if (_isGenerateThumbnail(fileVersion)) {
433                            StopWatch stopWatch = new StopWatch();
434    
435                            stopWatch.start();
436    
437                            _generateImagesGS(fileVersion, file, true);
438    
439                            if (_log.isInfoEnabled()) {
440                                    _log.info(
441                                            "Ghostscript generated a thumbnail for " +
442                                                    fileVersion.getTitle() + " in " + stopWatch.getTime() +
443                                                            " ms");
444                            }
445                    }
446            }
447    
448            private void _generateImagesGS(
449                            FileVersion fileVersion, File file, boolean thumbnail)
450                    throws Exception {
451    
452                    // Generate images
453    
454                    String tempFileId = DLUtil.getTempFileId(
455                            fileVersion.getFileEntryId(), fileVersion.getVersion());
456    
457                    List<String> arguments = new ArrayList<String>();
458    
459                    arguments.add("-sDEVICE=png16m");
460    
461                    if (thumbnail) {
462                            arguments.add(
463                                    "-sOutputFile=" + getThumbnailTempFilePath(tempFileId));
464                            arguments.add("-dFirstPage=1");
465                            arguments.add("-dLastPage=1");
466                    }
467                    else {
468                            arguments.add(
469                                    "-sOutputFile=" + getPreviewTempFilePath(tempFileId, -1));
470                    }
471    
472                    arguments.add("-dPDFFitPage");
473                    arguments.add("-dTextAlphaBits=4");
474                    arguments.add("-dGraphicsAlphaBits=4");
475                    arguments.add("-r" + PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_DPI);
476    
477                    if (PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_WIDTH != 0) {
478                            arguments.add(
479                                    "-dDEVICEWIDTH=" +
480                                            PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_WIDTH);
481                    }
482    
483                    if (PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_HEIGHT != 0) {
484                            arguments.add(
485                                    "-dDEVICEHEIGHT=" +
486                                            PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_HEIGHT);
487                    }
488    
489                    arguments.add(file.getPath());
490    
491                    Future<?> future = GhostscriptUtil.execute(arguments);
492    
493                    String processIdentity = String.valueOf(fileVersion.getFileVersionId());
494    
495                    long ghostscriptTimeout =
496                            PropsValues.DL_FILE_ENTRY_PREVIEW_GENERATION_TIMEOUT_GHOSTSCRIPT;
497    
498                    if (_log.isDebugEnabled()) {
499                            if (thumbnail) {
500                                    _log.debug(
501                                            "Waiting for " + ghostscriptTimeout +
502                                                    " seconds to generate thumbnail for " + file.getPath());
503                            }
504                            else {
505                                    _log.debug(
506                                            "Waiting for " + ghostscriptTimeout +
507                                                    " seconds to generate preview for " + file.getPath());
508                            }
509                    }
510    
511                    try {
512                            future.get(ghostscriptTimeout, TimeUnit.SECONDS);
513    
514                            futures.put(processIdentity, future);
515                    }
516                    catch (TimeoutException te) {
517                            String errorMessage =
518                                    "Timeout when generating preview for " + file.getPath();
519    
520                            if (thumbnail) {
521                                    errorMessage =
522                                            "Timeout when generating thumbanil for " + file.getPath();
523                            }
524    
525                            if (future.cancel(true)) {
526                                    errorMessage += " resulted in a canceled timeout for " + future;
527                            }
528    
529                            _log.error(errorMessage);
530    
531                            throw te;
532                    }
533                    catch (Exception e) {
534                            _log.error(e, e);
535    
536                            throw e;
537                    }
538    
539                    // Store images
540    
541                    if (thumbnail) {
542                            File thumbnailTempFile = getThumbnailTempFile(tempFileId);
543    
544                            try {
545                                    storeThumbnailImages(fileVersion, thumbnailTempFile);
546                            }
547                            finally {
548                                    FileUtil.delete(thumbnailTempFile);
549                            }
550                    }
551                    else {
552                            int total = getPreviewTempFileCount(fileVersion);
553    
554                            for (int i = 0; i < total; i++) {
555                                    File previewTempFile = getPreviewTempFile(tempFileId, i + 2);
556    
557                                    try {
558                                            addFileToStore(
559                                                    fileVersion.getCompanyId(), PREVIEW_PATH,
560                                                    getPreviewFilePath(fileVersion, i + 1),
561                                                    previewTempFile);
562                                    }
563                                    finally {
564                                            FileUtil.delete(previewTempFile);
565                                    }
566                            }
567                    }
568            }
569    
570            private void _generateImagesGS(
571                            FileVersion fileVersion, InputStream inputStream)
572                    throws Exception {
573    
574                    File file = null;
575    
576                    try {
577                            file = FileUtil.createTempFile(inputStream);
578    
579                            _generateImagesGS(fileVersion, file);
580                    }
581                    finally {
582                            FileUtil.delete(file);
583                    }
584            }
585    
586            private void _generateImagesPB(FileVersion fileVersion, File file)
587                    throws Exception {
588    
589                    String tempFileId = DLUtil.getTempFileId(
590                            fileVersion.getFileEntryId(), fileVersion.getVersion());
591    
592                    File thumbnailFile = getThumbnailTempFile(tempFileId);
593    
594                    int previewFilesCount = 0;
595    
596                    PDDocument pdDocument = null;
597    
598                    try {
599                            pdDocument = PDDocument.load(file);
600    
601                            if (pdDocument.isEncrypted()) {
602                                    _log.error(
603                                            "PDF document is encrypted for file version " +
604                                                    fileVersion.getFileVersionId());
605    
606                                    return;
607                            }
608    
609                            previewFilesCount = pdDocument.getNumberOfPages();
610                    }
611                    finally {
612                            if (pdDocument != null) {
613                                    pdDocument.close();
614                            }
615                    }
616    
617                    File[] previewFiles = new File[previewFilesCount];
618    
619                    for (int i = 0; i < previewFilesCount; i++) {
620                            previewFiles[i] = getPreviewTempFile(tempFileId, i);
621                    }
622    
623                    boolean generatePreview = _isGeneratePreview(fileVersion);
624                    boolean generateThumbnail = _isGenerateThumbnail(fileVersion);
625    
626                    StopWatch stopWatch = new StopWatch();
627    
628                    stopWatch.start();
629    
630                    if (PropsValues.DL_FILE_ENTRY_PREVIEW_FORK_PROCESS_ENABLED) {
631                            ProcessCallable<String> processCallable =
632                                    new LiferayPDFBoxProcessCallable(
633                                            ServerDetector.getServerId(),
634                                            PropsUtil.get(PropsKeys.LIFERAY_HOME),
635                                            Log4JUtil.getCustomLogSettings(), file, thumbnailFile,
636                                            previewFiles, getThumbnailType(fileVersion),
637                                            getPreviewType(fileVersion),
638                                            PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_DPI,
639                                            PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_HEIGHT,
640                                            PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_WIDTH,
641                                            generatePreview, generateThumbnail);
642    
643                            Future<String> future = ProcessExecutor.execute(
644                                    ClassPathUtil.getPortalClassPath(), processCallable);
645    
646                            String processIdentity = String.valueOf(
647                                    fileVersion.getFileVersionId());
648    
649                            long pdfBoxTimeout =
650                                    PropsValues.DL_FILE_ENTRY_PREVIEW_GENERATION_TIMEOUT_PDFBOX;
651    
652                            if (_log.isDebugEnabled()) {
653                                    if (generateThumbnail && generatePreview) {
654                                            _log.debug(
655                                                    "Waiting for " + pdfBoxTimeout +
656                                                            " seconds to generate thumbnail and preview for " +
657                                                                    file.getPath());
658                                    }
659                                    else {
660                                            if (generateThumbnail) {
661                                                    _log.debug(
662                                                            "Waiting for " + pdfBoxTimeout +
663                                                                    " seconds to generate thumbnail for " +
664                                                                            file.getPath());
665                                            }
666    
667                                            if (generatePreview) {
668                                                    _log.debug(
669                                                            "Waiting for " + pdfBoxTimeout +
670                                                                    " seconds to generate preview for " +
671                                                                            file.getPath());
672                                            }
673                                    }
674                            }
675    
676                            try {
677                                    future.get(pdfBoxTimeout, TimeUnit.SECONDS);
678    
679                                    futures.put(processIdentity, future);
680                            }
681                            catch (TimeoutException te) {
682                                    String errorMessage = null;
683    
684                                    if (generateThumbnail && generatePreview) {
685                                            errorMessage =
686                                                    "Timeout when generating thumbnail and preview for " +
687                                                            file.getPath();
688                                    }
689                                    else {
690                                            if (generateThumbnail) {
691                                                    errorMessage =
692                                                            "Timeout when generating thumbnail for " +
693                                                                    file.getPath();
694                                            }
695    
696                                            if (generatePreview) {
697                                                    errorMessage =
698                                                            "Timeout when generating preview for " +
699                                                                    file.getPath();
700                                            }
701                                    }
702    
703                                    if (future.cancel(true)) {
704                                            errorMessage +=
705                                                    " resulted in a canceled timeout for " + future;
706                                    }
707    
708                                    _log.error(errorMessage);
709    
710                                    throw te;
711                            }
712                            catch (Exception e) {
713                                    _log.error(e, e);
714    
715                                    throw e;
716                            }
717                    }
718                    else {
719                            LiferayPDFBoxConverter liferayConverter =
720                                    new LiferayPDFBoxConverter(
721                                            file, thumbnailFile, previewFiles,
722                                            getPreviewType(fileVersion), getThumbnailType(fileVersion),
723                                            PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_DPI,
724                                            PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_HEIGHT,
725                                            PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_WIDTH,
726                                            generatePreview, generateThumbnail);
727    
728                            liferayConverter.generateImagesPB();
729                    }
730    
731                    if (generateThumbnail) {
732                            try {
733                                    storeThumbnailImages(fileVersion, thumbnailFile);
734                            }
735                            finally {
736                                    FileUtil.delete(thumbnailFile);
737                            }
738                    }
739    
740                    if (generatePreview) {
741                            int index = 0;
742    
743                            for (File previewFile : previewFiles) {
744                                    try {
745                                            addFileToStore(
746                                                    fileVersion.getCompanyId(), PREVIEW_PATH,
747                                                    getPreviewFilePath(fileVersion, index + 1),
748                                                    previewFile);
749                                    }
750                                    finally {
751                                            FileUtil.delete(previewFile);
752                                    }
753    
754                                    index++;
755                            }
756                    }
757    
758                    if (_log.isInfoEnabled()) {
759                            long fileVersionId = fileVersion.getFileVersionId();
760                            int previewFileCount = getPreviewFileCount(fileVersion);
761                            long time = stopWatch.getTime();
762    
763                            if (generateThumbnail && generatePreview) {
764                                    _log.info(
765                                            "PDFBox generated a thumbnail and " + previewFileCount +
766                                                    " preview pages for " + fileVersionId + " in " + time +
767                                                            " ms");
768                            }
769                            else {
770                                    if (generateThumbnail) {
771                                            _log.info(
772                                                    "PDFBox generated a thumbnail for " + fileVersionId +
773                                                            " in " + time + " ms");
774                                    }
775    
776                                    if (generatePreview) {
777                                            _log.info(
778                                                    "PDFBox generated " + previewFileCount +
779                                                            " preview pages for " + fileVersionId + " in " +
780                                                                    time + " ms");
781                                    }
782                            }
783                    }
784            }
785    
786            private void _generateImagesPB(
787                            FileVersion fileVersion, InputStream inputStream)
788                    throws Exception {
789    
790                    File file = null;
791    
792                    try {
793                            file = FileUtil.createTempFile(inputStream);
794    
795                            _generateImagesPB(fileVersion, file);
796                    }
797                    finally {
798                            FileUtil.delete(file);
799                    }
800            }
801    
802            private boolean _hasImages(FileVersion fileVersion) throws Exception {
803                    if (PropsValues.DL_FILE_ENTRY_PREVIEW_ENABLED) {
804                            if (!hasPreview(fileVersion)) {
805                                    return false;
806                            }
807                    }
808    
809                    return hasThumbnails(fileVersion);
810            }
811    
812            private boolean _isGeneratePreview(FileVersion fileVersion)
813                    throws Exception {
814    
815                    if (PropsValues.DL_FILE_ENTRY_PREVIEW_ENABLED &&
816                            !hasPreview(fileVersion)) {
817    
818                            return true;
819                    }
820                    else {
821                            return false;
822                    }
823            }
824    
825            private boolean _isGenerateThumbnail(FileVersion fileVersion)
826                    throws Exception {
827    
828                    if (PropsValues.DL_FILE_ENTRY_THUMBNAIL_ENABLED &&
829                            !hasThumbnail(fileVersion, THUMBNAIL_INDEX_DEFAULT)) {
830    
831                            return true;
832                    }
833                    else {
834                            return false;
835                    }
836            }
837    
838            private void _queueGeneration(
839                    FileVersion sourceFileVersion, FileVersion destinationFileVersion) {
840    
841                    if (_fileVersionIds.contains(
842                                    destinationFileVersion.getFileVersionId())) {
843    
844                            return;
845                    }
846    
847                    boolean generateImages = false;
848    
849                    String extension = destinationFileVersion.getExtension();
850    
851                    if (extension.equals("pdf")) {
852                            generateImages = true;
853                    }
854                    else if (DocumentConversionUtil.isEnabled()) {
855                            String[] conversions = DocumentConversionUtil.getConversions(
856                                    extension);
857    
858                            for (String conversion : conversions) {
859                                    if (conversion.equals("pdf")) {
860                                            generateImages = true;
861    
862                                            break;
863                                    }
864                            }
865                    }
866    
867                    if (generateImages) {
868                            _fileVersionIds.add(destinationFileVersion.getFileVersionId());
869    
870                            sendGenerationMessage(
871                                    DestinationNames.DOCUMENT_LIBRARY_PDF_PROCESSOR,
872                                    sourceFileVersion, destinationFileVersion);
873                    }
874            }
875    
876            private static Log _log = LogFactoryUtil.getLog(PDFProcessorImpl.class);
877    
878            private List<Long> _fileVersionIds = new Vector<Long>();
879            private boolean _ghostscriptInitialized = false;
880    
881            private static class LiferayPDFBoxProcessCallable
882                    implements ProcessCallable<String> {
883    
884                    public LiferayPDFBoxProcessCallable(
885                            String serverId, String liferayHome,
886                            Map<String, String> customLogSettings, File inputFile,
887                            File thumbnailFile, File[] previewFiles, String extension,
888                            String thumbnailExtension, int dpi, int height, int width,
889                            boolean generatePreview, boolean generateThumbnail) {
890    
891                            _serverId = serverId;
892                            _liferayHome = liferayHome;
893                            _customLogSettings = customLogSettings;
894                            _inputFile = inputFile;
895                            _thumbnailFile = thumbnailFile;
896                            _previewFiles = previewFiles;
897                            _extension = extension;
898                            _thumbnailExtension = thumbnailExtension;
899                            _dpi = dpi;
900                            _height = height;
901                            _width = width;
902                            _generatePreview = generatePreview;
903                            _generateThumbnail = generateThumbnail;
904                    }
905    
906                    @Override
907                    public String call() throws ProcessException {
908                            Properties systemProperties = System.getProperties();
909    
910                            SystemEnv.setProperties(systemProperties);
911    
912                            Class<?> clazz = getClass();
913    
914                            ClassLoader classLoader = clazz.getClassLoader();
915    
916                            Log4JUtil.initLog4J(
917                                    _serverId, _liferayHome, classLoader, new Log4jLogFactoryImpl(),
918                                    _customLogSettings);
919    
920                            try {
921                                    LiferayPDFBoxConverter liferayConverter =
922                                            new LiferayPDFBoxConverter(
923                                                    _inputFile, _thumbnailFile, _previewFiles, _extension,
924                                                    _thumbnailExtension, _dpi, _height, _width,
925                                                    _generatePreview, _generateThumbnail);
926    
927                                    liferayConverter.generateImagesPB();
928                            }
929                            catch (Exception e) {
930                                    throw new ProcessException(e);
931                            }
932    
933                            return StringPool.BLANK;
934                    }
935    
936                    private static final long serialVersionUID = 1L;
937    
938                    private Map<String, String> _customLogSettings;
939                    private int _dpi;
940                    private String _extension;
941                    private boolean _generatePreview;
942                    private boolean _generateThumbnail;
943                    private int _height;
944                    private File _inputFile;
945                    private String _liferayHome;
946                    private File[] _previewFiles;
947                    private String _serverId;
948                    private String _thumbnailExtension;
949                    private File _thumbnailFile;
950                    private int _width;
951    
952            }
953    
954    }