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