001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.documentlibrary.util;
016    
017    import com.liferay.portal.fabric.InputResource;
018    import com.liferay.portal.fabric.OutputResource;
019    import com.liferay.portal.kernel.exception.SystemException;
020    import com.liferay.portal.kernel.image.ImageBag;
021    import com.liferay.portal.kernel.image.ImageToolUtil;
022    import com.liferay.portal.kernel.lar.PortletDataContext;
023    import com.liferay.portal.kernel.log.Log;
024    import com.liferay.portal.kernel.log.LogFactoryUtil;
025    import com.liferay.portal.kernel.messaging.DestinationNames;
026    import com.liferay.portal.kernel.process.ClassPathUtil;
027    import com.liferay.portal.kernel.process.ProcessCallable;
028    import com.liferay.portal.kernel.process.ProcessChannel;
029    import com.liferay.portal.kernel.process.ProcessException;
030    import com.liferay.portal.kernel.process.ProcessExecutorUtil;
031    import com.liferay.portal.kernel.repository.model.FileEntry;
032    import com.liferay.portal.kernel.repository.model.FileVersion;
033    import com.liferay.portal.kernel.util.FileUtil;
034    import com.liferay.portal.kernel.util.PropsKeys;
035    import com.liferay.portal.kernel.util.ServerDetector;
036    import com.liferay.portal.kernel.util.SetUtil;
037    import com.liferay.portal.kernel.util.StreamUtil;
038    import com.liferay.portal.kernel.util.StringBundler;
039    import com.liferay.portal.kernel.util.StringPool;
040    import com.liferay.portal.kernel.util.SystemEnv;
041    import com.liferay.portal.kernel.xml.Element;
042    import com.liferay.portal.kernel.xuggler.XugglerUtil;
043    import com.liferay.portal.log.Log4jLogFactoryImpl;
044    import com.liferay.portal.repository.liferayrepository.model.LiferayFileVersion;
045    import com.liferay.portal.util.PropsUtil;
046    import com.liferay.portal.util.PropsValues;
047    import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
048    import com.liferay.util.log4j.Log4JUtil;
049    
050    import java.awt.image.RenderedImage;
051    
052    import java.io.File;
053    import java.io.InputStream;
054    
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.CancellationException;
061    import java.util.concurrent.Future;
062    
063    import org.apache.commons.lang.time.StopWatch;
064    
065    /**
066     * @author Juan Gonz??lez
067     * @author Sergio Gonz??lez
068     * @author Mika Koivisto
069     * @author Ivica Cardic
070     */
071    public class VideoProcessorImpl
072            extends DLPreviewableProcessor implements VideoProcessor {
073    
074            @Override
075            public void afterPropertiesSet() {
076                    boolean valid = true;
077    
078                    if ((_PREVIEW_TYPES.length == 0) || (_PREVIEW_TYPES.length > 2)) {
079                            valid = false;
080                    }
081                    else {
082                            for (String previewType : _PREVIEW_TYPES) {
083                                    if (!previewType.equals("mp4") && !previewType.equals("ogv")) {
084                                            valid = false;
085    
086                                            break;
087                                    }
088                            }
089                    }
090    
091                    if (!valid && _log.isWarnEnabled()) {
092                            StringBundler sb = new StringBundler(5);
093    
094                            sb.append("Liferay is incorrectly configured to generate video ");
095                            sb.append("previews using video containers other than MP4 or ");
096                            sb.append("OGV. Please change the property ");
097                            sb.append(PropsKeys.DL_FILE_ENTRY_PREVIEW_VIDEO_CONTAINERS);
098                            sb.append(" in portal-ext.properties.");
099    
100                            _log.warn(sb.toString());
101                    }
102    
103                    FileUtil.mkdirs(PREVIEW_TMP_PATH);
104                    FileUtil.mkdirs(THUMBNAIL_TMP_PATH);
105            }
106    
107            @Override
108            public void generateVideo(
109                            FileVersion sourceFileVersion, FileVersion destinationFileVersion)
110                    throws Exception {
111    
112                    _generateVideo(sourceFileVersion, destinationFileVersion);
113            }
114    
115            @Override
116            public InputStream getPreviewAsStream(FileVersion fileVersion, String type)
117                    throws Exception {
118    
119                    return doGetPreviewAsStream(fileVersion, type);
120            }
121    
122            @Override
123            public long getPreviewFileSize(FileVersion fileVersion, String type)
124                    throws Exception {
125    
126                    return doGetPreviewFileSize(fileVersion, type);
127            }
128    
129            @Override
130            public InputStream getThumbnailAsStream(FileVersion fileVersion, int index)
131                    throws Exception {
132    
133                    return doGetThumbnailAsStream(fileVersion, index);
134            }
135    
136            @Override
137            public long getThumbnailFileSize(FileVersion fileVersion, int index)
138                    throws Exception {
139    
140                    return doGetThumbnailFileSize(fileVersion, index);
141            }
142    
143            @Override
144            public Set<String> getVideoMimeTypes() {
145                    return _videoMimeTypes;
146            }
147    
148            @Override
149            public boolean hasVideo(FileVersion fileVersion) {
150                    boolean hasVideo = false;
151    
152                    try {
153                            hasVideo = _hasVideo(fileVersion);
154    
155                            if (!hasVideo && isSupported(fileVersion)) {
156                                    _queueGeneration(null, fileVersion);
157                            }
158                    }
159                    catch (Exception e) {
160                            _log.error(e, e);
161                    }
162    
163                    return hasVideo;
164            }
165    
166            @Override
167            public boolean isSupported(String mimeType) {
168                    if (_videoMimeTypes.contains(mimeType) && XugglerUtil.isEnabled()) {
169                            return true;
170                    }
171    
172                    return false;
173            }
174    
175            @Override
176            public boolean isVideoSupported(FileVersion fileVersion) {
177                    return isSupported(fileVersion);
178            }
179    
180            @Override
181            public boolean isVideoSupported(String mimeType) {
182                    return isSupported(mimeType);
183            }
184    
185            @Override
186            public void trigger(
187                    FileVersion sourceFileVersion, FileVersion destinationFileVersion) {
188    
189                    super.trigger(sourceFileVersion, destinationFileVersion);
190    
191                    _queueGeneration(sourceFileVersion, destinationFileVersion);
192            }
193    
194            @Override
195            protected void doExportGeneratedFiles(
196                            PortletDataContext portletDataContext, FileEntry fileEntry,
197                            Element fileEntryElement)
198                    throws Exception {
199    
200                    exportThumbnails(
201                            portletDataContext, fileEntry, fileEntryElement, "video");
202    
203                    exportPreviews(portletDataContext, fileEntry, fileEntryElement);
204            }
205    
206            @Override
207            protected void doImportGeneratedFiles(
208                            PortletDataContext portletDataContext, FileEntry fileEntry,
209                            FileEntry importedFileEntry, Element fileEntryElement)
210                    throws Exception {
211    
212                    importThumbnails(
213                            portletDataContext, fileEntry, importedFileEntry, fileEntryElement,
214                            "video");
215    
216                    importPreviews(
217                            portletDataContext, fileEntry, importedFileEntry, fileEntryElement);
218            }
219    
220            protected void exportPreviews(
221                            PortletDataContext portletDataContext, FileEntry fileEntry,
222                            Element fileEntryElement)
223                    throws Exception {
224    
225                    FileVersion fileVersion = fileEntry.getFileVersion();
226    
227                    if (!isSupported(fileVersion) || !hasPreviews(fileVersion)) {
228                            return;
229                    }
230    
231                    if (!portletDataContext.isPerformDirectBinaryImport()) {
232                            if ((_PREVIEW_TYPES.length == 0) || (_PREVIEW_TYPES.length > 2)) {
233                                    return;
234                            }
235    
236                            for (String previewType : _PREVIEW_TYPES) {
237                                    if (previewType.equals("mp4") || previewType.equals("ogv")) {
238                                            exportPreview(
239                                                    portletDataContext, fileEntry, fileEntryElement,
240                                                    "video", previewType);
241                                    }
242                            }
243                    }
244            }
245    
246            @Override
247            protected List<Long> getFileVersionIds() {
248                    return _fileVersionIds;
249            }
250    
251            @Override
252            protected String getPreviewType(FileVersion fileVersion) {
253                    return _PREVIEW_TYPES[0];
254            }
255    
256            @Override
257            protected String[] getPreviewTypes() {
258                    return _PREVIEW_TYPES;
259            }
260    
261            @Override
262            protected String getThumbnailType(FileVersion fileVersion) {
263                    return THUMBNAIL_TYPE;
264            }
265    
266            protected void importPreviews(
267                            PortletDataContext portletDataContext, FileEntry fileEntry,
268                            FileEntry importedFileEntry, Element fileEntryElement)
269                    throws Exception {
270    
271                    if ((_PREVIEW_TYPES.length == 0) || (_PREVIEW_TYPES.length > 2)) {
272                            return;
273                    }
274    
275                    for (String previewType : _PREVIEW_TYPES) {
276                            if (previewType.equals("mp4") || previewType.equals("ogv")) {
277                                    importPreview(
278                                            portletDataContext, fileEntry, importedFileEntry,
279                                            fileEntryElement, "video", previewType);
280                            }
281                    }
282            }
283    
284            @Override
285            protected void storeThumbnailImages(FileVersion fileVersion, File file)
286                    throws Exception {
287    
288                    if (!hasThumbnail(fileVersion, THUMBNAIL_INDEX_DEFAULT)) {
289                            addFileToStore(
290                                    fileVersion.getCompanyId(), THUMBNAIL_PATH,
291                                    getThumbnailFilePath(fileVersion, THUMBNAIL_INDEX_DEFAULT),
292                                    file);
293                    }
294    
295                    if (isThumbnailEnabled(THUMBNAIL_INDEX_CUSTOM_1) ||
296                            isThumbnailEnabled(THUMBNAIL_INDEX_CUSTOM_2)) {
297    
298                            ImageBag imageBag = ImageToolUtil.read(file);
299    
300                            RenderedImage renderedImage = imageBag.getRenderedImage();
301    
302                            storeThumbnailImage(
303                                    fileVersion, renderedImage, THUMBNAIL_INDEX_CUSTOM_1);
304                            storeThumbnailImage(
305                                    fileVersion, renderedImage, THUMBNAIL_INDEX_CUSTOM_2);
306                    }
307            }
308    
309            private void _generateThumbnailXuggler(
310                            FileVersion fileVersion, File file, int height, int width)
311                    throws Exception {
312    
313                    StopWatch stopWatch = new StopWatch();
314    
315                    stopWatch.start();
316    
317                    String tempFileId = DLUtil.getTempFileId(
318                            fileVersion.getFileEntryId(), fileVersion.getVersion());
319    
320                    File thumbnailTempFile = getThumbnailTempFile(tempFileId);
321    
322                    try {
323                            try {
324                                    if (PropsValues.DL_FILE_ENTRY_PREVIEW_FORK_PROCESS_ENABLED) {
325                                            ProcessCallable<String> processCallable =
326                                                    new LiferayVideoThumbnailProcessCallable(
327                                                            ServerDetector.getServerId(),
328                                                            PropsUtil.get(PropsKeys.LIFERAY_HOME),
329                                                            Log4JUtil.getCustomLogSettings(), file,
330                                                            thumbnailTempFile, THUMBNAIL_TYPE, height, width,
331                                                            PropsValues.
332                                                                    DL_FILE_ENTRY_THUMBNAIL_VIDEO_FRAME_PERCENTAGE);
333    
334                                            ProcessChannel<String> processChannel =
335                                                    ProcessExecutorUtil.execute(
336                                                            ClassPathUtil.getPortalProcessConfig(),
337                                                            processCallable);
338    
339                                            Future<String> future =
340                                                    processChannel.getProcessNoticeableFuture();
341    
342                                            String processIdentity = String.valueOf(
343                                                    fileVersion.getFileVersionId());
344    
345                                            futures.put(processIdentity, future);
346    
347                                            future.get();
348                                    }
349                                    else {
350                                            LiferayConverter liferayConverter =
351                                                    new LiferayVideoThumbnailConverter(
352                                                            file.getCanonicalPath(), thumbnailTempFile,
353                                                            THUMBNAIL_TYPE, height, width,
354                                                            PropsValues.
355                                                                    DL_FILE_ENTRY_THUMBNAIL_VIDEO_FRAME_PERCENTAGE);
356    
357                                            liferayConverter.convert();
358                                    }
359                            }
360                            catch (CancellationException ce) {
361                                    if (_log.isInfoEnabled()) {
362                                            _log.info(
363                                                    "Cancellation received for " +
364                                                            fileVersion.getFileVersionId() + " " +
365                                                                    fileVersion.getTitle());
366                                    }
367                            }
368                            catch (Exception e) {
369                                    _log.error(e, e);
370                            }
371    
372                            storeThumbnailImages(fileVersion, thumbnailTempFile);
373    
374                            if (_log.isInfoEnabled()) {
375                                    _log.info(
376                                            "Xuggler generated a thumbnail for " +
377                                                    fileVersion.getTitle() + " in " + stopWatch.getTime() +
378                                                            " ms");
379                            }
380                    }
381                    catch (Exception e) {
382                            throw new SystemException(e);
383                    }
384                    finally {
385                            FileUtil.delete(thumbnailTempFile);
386                    }
387            }
388    
389            private void _generateVideo(
390                            FileVersion sourceFileVersion, FileVersion destinationFileVersion)
391                    throws Exception {
392    
393                    if (!XugglerUtil.isEnabled() || _hasVideo(destinationFileVersion)) {
394                            return;
395                    }
396    
397                    InputStream inputStream = null;
398    
399                    File[] previewTempFiles = new File[_PREVIEW_TYPES.length];
400    
401                    File videoTempFile = null;
402    
403                    try {
404                            if (sourceFileVersion != null) {
405                                    copy(sourceFileVersion, destinationFileVersion);
406    
407                                    return;
408                            }
409    
410                            File file = null;
411    
412                            if (!hasPreviews(destinationFileVersion) ||
413                                    !hasThumbnails(destinationFileVersion)) {
414    
415                                    if (destinationFileVersion instanceof LiferayFileVersion) {
416                                            try {
417                                                    LiferayFileVersion liferayFileVersion =
418                                                            (LiferayFileVersion)destinationFileVersion;
419    
420                                                    file = liferayFileVersion.getFile(false);
421                                            }
422                                            catch (UnsupportedOperationException uoe) {
423                                            }
424                                    }
425    
426                                    if (file == null) {
427                                            inputStream = destinationFileVersion.getContentStream(
428                                                    false);
429    
430                                            videoTempFile = FileUtil.createTempFile(
431                                                    destinationFileVersion.getExtension());
432    
433                                            FileUtil.write(videoTempFile, inputStream);
434    
435                                            file = videoTempFile;
436                                    }
437                            }
438    
439                            if (!hasPreviews(destinationFileVersion)) {
440                                    String tempFileId = DLUtil.getTempFileId(
441                                            destinationFileVersion.getFileEntryId(),
442                                            destinationFileVersion.getVersion());
443    
444                                    for (int i = 0; i < _PREVIEW_TYPES.length; i++) {
445                                            previewTempFiles[i] = getPreviewTempFile(
446                                                    tempFileId, _PREVIEW_TYPES[i]);
447                                    }
448    
449                                    try {
450                                            _generateVideoXuggler(
451                                                    destinationFileVersion, file, previewTempFiles);
452                                    }
453                                    catch (Exception e) {
454                                            _log.error(e, e);
455                                    }
456                            }
457    
458                            if (!hasThumbnails(destinationFileVersion)) {
459                                    try {
460                                            _generateThumbnailXuggler(
461                                                    destinationFileVersion, file,
462                                                    PropsValues.DL_FILE_ENTRY_PREVIEW_VIDEO_HEIGHT,
463                                                    PropsValues.DL_FILE_ENTRY_PREVIEW_VIDEO_WIDTH);
464                                    }
465                                    catch (Exception e) {
466                                            _log.error(e, e);
467                                    }
468                            }
469                    }
470                    catch (NoSuchFileEntryException nsfee) {
471                    }
472                    finally {
473                            StreamUtil.cleanUp(inputStream);
474    
475                            _fileVersionIds.remove(destinationFileVersion.getFileVersionId());
476    
477                            for (int i = 0; i < previewTempFiles.length; i++) {
478                                    FileUtil.delete(previewTempFiles[i]);
479                            }
480    
481                            FileUtil.delete(videoTempFile);
482                    }
483            }
484    
485            private void _generateVideoXuggler(
486                            FileVersion fileVersion, File sourceFile, File destinationFile,
487                            String containerType)
488                    throws Exception {
489    
490                    if (hasPreview(fileVersion, containerType)) {
491                            return;
492                    }
493    
494                    StopWatch stopWatch = new StopWatch();
495    
496                    stopWatch.start();
497    
498                    if (PropsValues.DL_FILE_ENTRY_PREVIEW_FORK_PROCESS_ENABLED) {
499                            ProcessCallable<String> processCallable =
500                                    new LiferayVideoProcessCallable(
501                                            ServerDetector.getServerId(),
502                                            PropsUtil.get(PropsKeys.LIFERAY_HOME),
503                                            Log4JUtil.getCustomLogSettings(), sourceFile,
504                                            destinationFile, containerType,
505                                            PropsUtil.getProperties(
506                                                    PropsKeys.DL_FILE_ENTRY_PREVIEW_VIDEO, false),
507                                            PropsUtil.getProperties(PropsKeys.XUGGLER_FFPRESET, true));
508    
509                            ProcessChannel<String> processChannel = ProcessExecutorUtil.execute(
510                                    ClassPathUtil.getPortalProcessConfig(), processCallable);
511    
512                            Future<String> future = processChannel.getProcessNoticeableFuture();
513    
514                            String processIdentity = String.valueOf(
515                                    fileVersion.getFileVersionId());
516    
517                            futures.put(processIdentity, future);
518    
519                            future.get();
520                    }
521                    else {
522                            LiferayConverter liferayConverter = new LiferayVideoConverter(
523                                    sourceFile.getCanonicalPath(),
524                                    destinationFile.getCanonicalPath(), containerType,
525                                    PropsUtil.getProperties(
526                                            PropsKeys.DL_FILE_ENTRY_PREVIEW_VIDEO, false),
527                                    PropsUtil.getProperties(PropsKeys.XUGGLER_FFPRESET, true));
528    
529                            liferayConverter.convert();
530                    }
531    
532                    addFileToStore(
533                            fileVersion.getCompanyId(), PREVIEW_PATH,
534                            getPreviewFilePath(fileVersion, containerType), destinationFile);
535    
536                    if (_log.isInfoEnabled()) {
537                            _log.info(
538                                    "Xuggler generated a " + containerType + " preview video for " +
539                                            fileVersion.getTitle() + " in " + stopWatch.getTime() +
540                                                    " ms");
541                    }
542            }
543    
544            private void _generateVideoXuggler(
545                    FileVersion fileVersion, File sourceFile, File[] destinationFiles) {
546    
547                    try {
548                            for (int i = 0; i < destinationFiles.length; i++) {
549                                    _generateVideoXuggler(
550                                            fileVersion, sourceFile, destinationFiles[i],
551                                            _PREVIEW_TYPES[i]);
552                            }
553                    }
554                    catch (CancellationException ce) {
555                            if (_log.isInfoEnabled()) {
556                                    _log.info(
557                                            "Cancellation received for " +
558                                                    fileVersion.getFileVersionId() + " " +
559                                                            fileVersion.getTitle());
560                            }
561                    }
562                    catch (Exception e) {
563                            _log.error(e, e);
564                    }
565            }
566    
567            private boolean _hasVideo(FileVersion fileVersion) throws Exception {
568                    if (!isSupported(fileVersion)) {
569                            return false;
570                    }
571    
572                    return hasPreviews(fileVersion) && hasThumbnails(fileVersion);
573            }
574    
575            private void _queueGeneration(
576                    FileVersion sourceFileVersion, FileVersion destinationFileVersion) {
577    
578                    if (_fileVersionIds.contains(
579                                    destinationFileVersion.getFileVersionId()) ||
580                            !isSupported(destinationFileVersion)) {
581    
582                            return;
583                    }
584    
585                    _fileVersionIds.add(destinationFileVersion.getFileVersionId());
586    
587                    sendGenerationMessage(
588                            DestinationNames.DOCUMENT_LIBRARY_VIDEO_PROCESSOR,
589                            sourceFileVersion, destinationFileVersion);
590            }
591    
592            private static final String[] _PREVIEW_TYPES =
593                    PropsValues.DL_FILE_ENTRY_PREVIEW_VIDEO_CONTAINERS;
594    
595            private static Log _log = LogFactoryUtil.getLog(VideoProcessorImpl.class);
596    
597            private List<Long> _fileVersionIds = new Vector<Long>();
598            private Set<String> _videoMimeTypes = SetUtil.fromArray(
599                    PropsValues.DL_FILE_ENTRY_PREVIEW_VIDEO_MIME_TYPES);
600    
601            private static class LiferayVideoProcessCallable
602                    implements ProcessCallable<String> {
603    
604                    public LiferayVideoProcessCallable(
605                            String serverId, String liferayHome,
606                            Map<String, String> customLogSettings, File inputFile,
607                            File outputFile, String videoContainer, Properties videoProperties,
608                            Properties ffpresetProperties) {
609    
610                            _serverId = serverId;
611                            _liferayHome = liferayHome;
612                            _customLogSettings = customLogSettings;
613                            _inputFile = inputFile;
614                            _outputFile = outputFile;
615                            _videoContainer = videoContainer;
616                            _videoProperties = videoProperties;
617                            _ffpresetProperties = ffpresetProperties;
618                    }
619    
620                    @Override
621                    public String call() throws ProcessException {
622                            XugglerAutoInstallHelper.installNativeLibraries();
623    
624                            Properties systemProperties = System.getProperties();
625    
626                            SystemEnv.setProperties(systemProperties);
627    
628                            Class<?> clazz = getClass();
629    
630                            ClassLoader classLoader = clazz.getClassLoader();
631    
632                            Log4JUtil.initLog4J(
633                                    _serverId, _liferayHome, classLoader, new Log4jLogFactoryImpl(),
634                                    _customLogSettings);
635    
636                            try {
637                                    LiferayConverter liferayConverter = new LiferayVideoConverter(
638                                            _inputFile.getCanonicalPath(),
639                                            _outputFile.getCanonicalPath(), _videoContainer,
640                                            _videoProperties, _ffpresetProperties);
641    
642                                    liferayConverter.convert();
643                            }
644                            catch (Exception e) {
645                                    throw new ProcessException(e);
646                            }
647    
648                            return StringPool.BLANK;
649                    }
650    
651                    private static final long serialVersionUID = 1L;
652    
653                    private Map<String, String> _customLogSettings;
654                    private Properties _ffpresetProperties;
655    
656                    @InputResource
657                    private File _inputFile;
658    
659                    private String _liferayHome;
660    
661                    @OutputResource
662                    private File _outputFile;
663    
664                    private String _serverId;
665                    private String _videoContainer;
666                    private Properties _videoProperties;
667    
668            }
669    
670            private static class LiferayVideoThumbnailProcessCallable
671                    implements ProcessCallable<String> {
672    
673                    public LiferayVideoThumbnailProcessCallable(
674                            String serverId, String liferayHome,
675                            Map<String, String> customLogSettings, File inputFile,
676                            File outputFile, String extension, int height, int width,
677                            int percentage) {
678    
679                            _serverId = serverId;
680                            _liferayHome = liferayHome;
681                            _customLogSettings = customLogSettings;
682                            _inputFile = inputFile;
683                            _outputFile = outputFile;
684                            _extension = extension;
685                            _height = height;
686                            _width = width;
687                            _percentage = percentage;
688                    }
689    
690                    @Override
691                    public String call() throws ProcessException {
692                            XugglerAutoInstallHelper.installNativeLibraries();
693    
694                            Class<?> clazz = getClass();
695    
696                            ClassLoader classLoader = clazz.getClassLoader();
697    
698                            Properties systemProperties = System.getProperties();
699                            SystemEnv.setProperties(systemProperties);
700    
701                            Log4JUtil.initLog4J(
702                                    _serverId, _liferayHome, classLoader, new Log4jLogFactoryImpl(),
703                                    _customLogSettings);
704    
705                            try {
706                                    LiferayConverter liferayConverter =
707                                            new LiferayVideoThumbnailConverter(
708                                                    _inputFile.getCanonicalPath(), _outputFile, _extension,
709                                                    _height, _width, _percentage);
710    
711                                    liferayConverter.convert();
712                            }
713                            catch (Exception e) {
714                                    throw new ProcessException(e);
715                            }
716    
717                            return StringPool.BLANK;
718                    }
719    
720                    private static final long serialVersionUID = 1L;
721    
722                    private Map<String, String> _customLogSettings;
723                    private String _extension;
724                    private int _height;
725    
726                    @InputResource
727                    private File _inputFile;
728    
729                    private String _liferayHome;
730    
731                    @OutputResource
732                    private File _outputFile;
733    
734                    private int _percentage;
735                    private String _serverId;
736                    private int _width;
737    
738            }
739    
740    }