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