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