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