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                            previewFilesCount = pdDocument.getNumberOfPages();
602                    }
603                    finally {
604                            if (pdDocument != null) {
605                                    pdDocument.close();
606                            }
607                    }
608    
609                    File[] previewFiles = new File[previewFilesCount];
610    
611                    for (int i = 0; i < previewFilesCount; i++) {
612                            previewFiles[i] = getPreviewTempFile(tempFileId, i);
613                    }
614    
615                    boolean generatePreview = _isGeneratePreview(fileVersion);
616                    boolean generateThumbnail = _isGenerateThumbnail(fileVersion);
617    
618                    StopWatch stopWatch = new StopWatch();
619    
620                    stopWatch.start();
621    
622                    if (PropsValues.DL_FILE_ENTRY_PREVIEW_FORK_PROCESS_ENABLED) {
623                            ProcessCallable<String> processCallable =
624                                    new LiferayPDFBoxProcessCallable(
625                                            ServerDetector.getServerId(),
626                                            PropsUtil.get(PropsKeys.LIFERAY_HOME),
627                                            Log4JUtil.getCustomLogSettings(), file, thumbnailFile,
628                                            previewFiles, getThumbnailType(fileVersion),
629                                            getPreviewType(fileVersion),
630                                            PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_DPI,
631                                            PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_HEIGHT,
632                                            PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_WIDTH,
633                                            generatePreview, generateThumbnail);
634    
635                            Future<String> future = ProcessExecutor.execute(
636                                    ClassPathUtil.getPortalClassPath(), processCallable);
637    
638                            String processIdentity = String.valueOf(
639                                    fileVersion.getFileVersionId());
640    
641                            long pdfBoxTimeout =
642                                    PropsValues.DL_FILE_ENTRY_PREVIEW_GENERATION_TIMEOUT_PDFBOX;
643    
644                            if (_log.isDebugEnabled()) {
645                                    if (generateThumbnail && generatePreview) {
646                                            _log.debug(
647                                                    "Waiting for " + pdfBoxTimeout +
648                                                            " seconds to generate thumbnail and preview for " +
649                                                                    file.getPath());
650                                    }
651                                    else {
652                                            if (generateThumbnail) {
653                                                    _log.debug(
654                                                            "Waiting for " + pdfBoxTimeout +
655                                                                    " seconds to generate thumbnail for " +
656                                                                            file.getPath());
657                                            }
658    
659                                            if (generatePreview) {
660                                                    _log.debug(
661                                                            "Waiting for " + pdfBoxTimeout +
662                                                                    " seconds to generate preview for " +
663                                                                            file.getPath());
664                                            }
665                                    }
666                            }
667    
668                            try {
669                                    future.get(pdfBoxTimeout, TimeUnit.SECONDS);
670    
671                                    futures.put(processIdentity, future);
672                            }
673                            catch (TimeoutException te) {
674                                    String errorMessage = null;
675    
676                                    if (generateThumbnail && generatePreview) {
677                                            errorMessage =
678                                                    "Timeout when generating thumbnail and preview for " +
679                                                            file.getPath();
680                                    }
681                                    else {
682                                            if (generateThumbnail) {
683                                                    errorMessage =
684                                                            "Timeout when generating thumbnail for " +
685                                                                    file.getPath();
686                                            }
687    
688                                            if (generatePreview) {
689                                                    errorMessage =
690                                                            "Timeout when generating preview for " +
691                                                                    file.getPath();
692                                            }
693                                    }
694    
695                                    if (future.cancel(true)) {
696                                            errorMessage +=
697                                                    " resulted in a canceled timeout for " + future;
698                                    }
699    
700                                    _log.error(errorMessage);
701    
702                                    throw te;
703                            }
704                            catch (Exception e) {
705                                    _log.error(e, e);
706    
707                                    throw e;
708                            }
709                    }
710                    else {
711                            LiferayPDFBoxConverter liferayConverter =
712                                    new LiferayPDFBoxConverter(
713                                            file, thumbnailFile, previewFiles,
714                                            getPreviewType(fileVersion), getThumbnailType(fileVersion),
715                                            PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_DPI,
716                                            PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_HEIGHT,
717                                            PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_WIDTH,
718                                            generatePreview, generateThumbnail);
719    
720                            liferayConverter.generateImagesPB();
721                    }
722    
723                    if (generateThumbnail) {
724                            try {
725                                    storeThumbnailImages(fileVersion, thumbnailFile);
726                            }
727                            finally {
728                                    FileUtil.delete(thumbnailFile);
729                            }
730                    }
731    
732                    if (generatePreview) {
733                            int index = 0;
734    
735                            for (File previewFile : previewFiles) {
736                                    try {
737                                            addFileToStore(
738                                                    fileVersion.getCompanyId(), PREVIEW_PATH,
739                                                    getPreviewFilePath(fileVersion, index +1), previewFile);
740                                    }
741                                    finally {
742                                            FileUtil.delete(previewFile);
743                                    }
744    
745                                    index++;
746                            }
747                    }
748    
749                    if (_log.isInfoEnabled()) {
750                            long fileVersionId = fileVersion.getFileVersionId();
751                            int previewFileCount = getPreviewFileCount(fileVersion);
752                            long time = stopWatch.getTime();
753    
754                            if (generateThumbnail && generatePreview) {
755                                    _log.info(
756                                            "PDFBox generated a thumbnail and " + previewFileCount +
757                                                    " preview pages for " + fileVersionId + " in " + time +
758                                                            " ms");
759                            }
760                            else {
761                                    if (generateThumbnail) {
762                                            _log.info(
763                                                    "PDFBox generated a thumbnail for " + fileVersionId +
764                                                            " in " + time + " ms");
765                                    }
766    
767                                    if (generatePreview) {
768                                            _log.info(
769                                                    "PDFBox generated " + previewFileCount +
770                                                            " preview pages for " + fileVersionId + " in " +
771                                                                    time + " ms");
772                                    }
773                            }
774                    }
775            }
776    
777            private void _generateImagesPB(
778                            FileVersion fileVersion, InputStream inputStream)
779                    throws Exception {
780    
781                    File file = null;
782    
783                    try {
784                            file = FileUtil.createTempFile(inputStream);
785    
786                            _generateImagesPB(fileVersion, file);
787                    }
788                    finally {
789                            FileUtil.delete(file);
790                    }
791            }
792    
793            private boolean _hasImages(FileVersion fileVersion) throws Exception {
794                    if (PropsValues.DL_FILE_ENTRY_PREVIEW_ENABLED) {
795                            if (!hasPreview(fileVersion)) {
796                                    return false;
797                            }
798                    }
799    
800                    return hasThumbnails(fileVersion);
801            }
802    
803            private boolean _isGeneratePreview(FileVersion fileVersion)
804                    throws Exception {
805    
806                    if (PropsValues.DL_FILE_ENTRY_PREVIEW_ENABLED &&
807                            !hasPreview(fileVersion)) {
808    
809                            return true;
810                    }
811                    else {
812                            return false;
813                    }
814            }
815    
816            private boolean _isGenerateThumbnail(FileVersion fileVersion)
817                    throws Exception {
818    
819                    if (PropsValues.DL_FILE_ENTRY_THUMBNAIL_ENABLED &&
820                            !hasThumbnail(fileVersion, THUMBNAIL_INDEX_DEFAULT)) {
821    
822                            return true;
823                    }
824                    else {
825                            return false;
826                    }
827            }
828    
829            private void _queueGeneration(
830                    FileVersion sourceFileVersion, FileVersion destinationFileVersion) {
831    
832                    if (_fileVersionIds.contains(
833                                    destinationFileVersion.getFileVersionId())) {
834    
835                            return;
836                    }
837    
838                    boolean generateImages = false;
839    
840                    String extension = destinationFileVersion.getExtension();
841    
842                    if (extension.equals("pdf")) {
843                            generateImages = true;
844                    }
845                    else if (DocumentConversionUtil.isEnabled()) {
846                            String[] conversions = DocumentConversionUtil.getConversions(
847                                    extension);
848    
849                            for (String conversion : conversions) {
850                                    if (conversion.equals("pdf")) {
851                                            generateImages = true;
852    
853                                            break;
854                                    }
855                            }
856                    }
857    
858                    if (generateImages) {
859                            _fileVersionIds.add(destinationFileVersion.getFileVersionId());
860    
861                            sendGenerationMessage(
862                                    DestinationNames.DOCUMENT_LIBRARY_PDF_PROCESSOR,
863                                    sourceFileVersion, destinationFileVersion);
864                    }
865            }
866    
867            private static Log _log = LogFactoryUtil.getLog(PDFProcessorImpl.class);
868    
869            private List<Long> _fileVersionIds = new Vector<Long>();
870            private boolean _ghostscriptInitialized = false;
871    
872            private static class LiferayPDFBoxProcessCallable
873                    implements ProcessCallable<String> {
874    
875                    public LiferayPDFBoxProcessCallable(
876                            String serverId, String liferayHome,
877                            Map<String, String> customLogSettings, File inputFile,
878                            File thumbnailFile, File[] previewFiles, String extension,
879                            String thumbnailExtension, int dpi, int height, int width,
880                            boolean generatePreview, boolean generateThumbnail) {
881    
882                            _serverId = serverId;
883                            _liferayHome = liferayHome;
884                            _customLogSettings = customLogSettings;
885                            _inputFile = inputFile;
886                            _thumbnailFile = thumbnailFile;
887                            _previewFiles = previewFiles;
888                            _extension = extension;
889                            _thumbnailExtension = thumbnailExtension;
890                            _dpi = dpi;
891                            _height = height;
892                            _width = width;
893                            _generatePreview = generatePreview;
894                            _generateThumbnail = generateThumbnail;
895                    }
896    
897                    @Override
898                    public String call() throws ProcessException {
899                            Properties systemProperties = System.getProperties();
900    
901                            SystemEnv.setProperties(systemProperties);
902    
903                            Class<?> clazz = getClass();
904    
905                            ClassLoader classLoader = clazz.getClassLoader();
906    
907                            Log4JUtil.initLog4J(
908                                    _serverId, _liferayHome, classLoader, new Log4jLogFactoryImpl(),
909                                    _customLogSettings);
910    
911                            try {
912                                    LiferayPDFBoxConverter liferayConverter =
913                                            new LiferayPDFBoxConverter(
914                                                    _inputFile, _thumbnailFile, _previewFiles, _extension,
915                                                    _thumbnailExtension, _dpi, _height, _width,
916                                                    _generatePreview, _generateThumbnail);
917    
918                                    liferayConverter.generateImagesPB();
919                            }
920                            catch (Exception e) {
921                                    throw new ProcessException(e);
922                            }
923    
924                            return StringPool.BLANK;
925                    }
926    
927                    private static final long serialVersionUID = 1L;
928    
929                    private Map<String, String> _customLogSettings;
930                    private int _dpi;
931                    private String _extension;
932                    private boolean _generatePreview;
933                    private boolean _generateThumbnail;
934                    private int _height;
935                    private File _inputFile;
936                    private String _liferayHome;
937                    private File[] _previewFiles;
938                    private String _serverId;
939                    private String _thumbnailExtension;
940                    private File _thumbnailFile;
941                    private int _width;
942    
943            }
944    
945    }