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