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