001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portlet.documentlibrary.util;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.messaging.DestinationNames;
020    import com.liferay.portal.kernel.messaging.MessageBusUtil;
021    import com.liferay.portal.kernel.repository.model.FileVersion;
022    import com.liferay.portal.kernel.util.FileUtil;
023    import com.liferay.portal.kernel.util.PropsKeys;
024    import com.liferay.portal.kernel.util.SetUtil;
025    import com.liferay.portal.kernel.util.StringBundler;
026    import com.liferay.portal.kernel.util.StringPool;
027    import com.liferay.portal.repository.liferayrepository.model.LiferayFileVersion;
028    import com.liferay.portal.util.PrefsPropsUtil;
029    import com.liferay.portal.util.PropsValues;
030    import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
031    import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
032    
033    import java.io.File;
034    import java.io.InputStream;
035    
036    import java.util.List;
037    import java.util.Set;
038    import java.util.Vector;
039    
040    /**
041     * @author Juan González
042     * @author Sergio González
043     * @author Mika Koivisto
044     */
045    public class AudioProcessor extends DefaultPreviewableProcessor {
046    
047            public static final String PREVIEW_TYPE = "mp3";
048    
049            public static void generateAudio(FileVersion fileVersion) throws Exception {
050                    _instance._generateAudio(fileVersion);
051            }
052    
053            public static Set<String> getAudioMimeTypes() {
054                    return _audioMimeTypes;
055            }
056    
057            public static DLProcessor getInstance() {
058                    return _instance;
059            }
060    
061            public static InputStream getPreviewAsStream(FileVersion fileVersion)
062                    throws Exception {
063    
064                    return _instance.doGetPreviewAsStream(fileVersion);
065            }
066    
067            public static long getPreviewFileSize(FileVersion fileVersion)
068                    throws Exception {
069    
070                    return _instance.doGetPreviewFileSize(fileVersion);
071            }
072    
073            public static boolean hasAudio(FileVersion fileVersion) {
074                    boolean hasAudio = false;
075    
076                    try {
077                            hasAudio = _instance._hasAudio(fileVersion);
078    
079                            if (!hasAudio && _instance.isSupported(fileVersion)) {
080                                    _instance._queueGeneration(fileVersion);
081                            }
082                    }
083                    catch (Exception e) {
084                            _log.error(e, e);
085                    }
086    
087                    return hasAudio;
088            }
089    
090            public AudioProcessor() {
091                    FileUtil.mkdirs(PREVIEW_TMP_PATH);
092            }
093    
094            public boolean isSupported(String mimeType) {
095                    return _audioMimeTypes.contains(mimeType);
096            }
097    
098            public void trigger(FileVersion fileVersion) {
099                    _instance._queueGeneration(fileVersion);
100            }
101    
102            @Override
103            protected String getPreviewType() {
104                    return PREVIEW_TYPE;
105            }
106    
107            private void _generateAudio(FileVersion fileVersion) throws Exception {
108                    String tempFileId = DLUtil.getTempFileId(
109                            fileVersion.getFileEntryId(), fileVersion.getVersion());
110    
111                    File audioTempFile = _getAudioTempFile(
112                            tempFileId, fileVersion.getExtension());
113                    File previewTempFile = getPreviewTempFile(tempFileId);
114    
115                    try {
116                            if (!PrefsPropsUtil.getBoolean(
117                                            PropsKeys.XUGGLER_ENABLED, PropsValues.XUGGLER_ENABLED) ||
118                                    _hasAudio(fileVersion)) {
119    
120                                    return;
121                            }
122    
123                            if (_isGeneratePreview(fileVersion)) {
124                                    File file = null;
125    
126                                    if (fileVersion instanceof LiferayFileVersion) {
127                                            try {
128                                                    LiferayFileVersion liferayFileVersion =
129                                                            (LiferayFileVersion)fileVersion;
130    
131                                                    file = liferayFileVersion.getFile(false);
132                                            }
133                                            catch (UnsupportedOperationException uoe) {
134                                            }
135                                    }
136    
137                                    if (file == null) {
138                                            InputStream inputStream = fileVersion.getContentStream(
139                                                    false);
140    
141                                            FileUtil.write(audioTempFile, inputStream);
142    
143                                            file = audioTempFile;
144                                    }
145    
146                                    try {
147                                            _generateAudioXuggler(fileVersion, file, previewTempFile);
148                                    }
149                                    catch (Exception e) {
150                                            _log.error(e, e);
151                                    }
152                            }
153                    }
154                    catch (NoSuchFileEntryException nsfee) {
155                    }
156                    finally {
157                            _fileVersionIds.remove(fileVersion.getFileVersionId());
158    
159                            FileUtil.delete(audioTempFile);
160                            FileUtil.delete(previewTempFile);
161                    }
162            }
163    
164            private void _generateAudioXuggler(
165                            FileVersion fileVersion, File srcFile, File destFile)
166                    throws Exception {
167    
168                    try {
169                            LiferayAudioConverter liferayAudioConverter =
170                                    new LiferayAudioConverter(
171                                            srcFile.getCanonicalPath(), destFile.getCanonicalPath(),
172                                            _SAMPLE_RATE);
173    
174                            liferayAudioConverter.convert();
175                    }
176                    catch (Exception e) {
177                            _log.error(e, e);
178                    }
179    
180                    addFileToStore(
181                            fileVersion.getCompanyId(), PREVIEW_PATH,
182                            getPreviewFilePath(fileVersion), destFile);
183    
184                    if (_log.isInfoEnabled()) {
185                            _log.info(
186                                    "Xuggler generated a preview audio for " +
187                                            fileVersion.getFileVersionId());
188                    }
189            }
190    
191            private File _getAudioTempFile(String tempFileId, String targetExtension) {
192                    String audioTempFilePath = _getAudioTempFilePath(
193                            tempFileId, targetExtension);
194    
195                    return new File(audioTempFilePath);
196            }
197    
198            private String _getAudioTempFilePath(
199                    String tempFileId, String targetExtension) {
200    
201                    StringBundler sb = new StringBundler(5);
202    
203                    sb.append(PREVIEW_TMP_PATH);
204                    sb.append(tempFileId);
205    
206                    if (PREVIEW_TYPE.equals(targetExtension)) {
207                            sb.append("_tmp");
208                    }
209    
210                    sb.append(StringPool.PERIOD);
211                    sb.append(targetExtension);
212    
213                    return sb.toString();
214            }
215    
216            private boolean _hasAudio(FileVersion fileVersion) throws Exception {
217                    if (!isSupported(fileVersion)) {
218                            return false;
219                    }
220    
221                    boolean previewExists = DLStoreUtil.hasFile(
222                            fileVersion.getCompanyId(), REPOSITORY_ID,
223                            getPreviewFilePath(fileVersion));
224    
225                    if (PropsValues.DL_FILE_ENTRY_PREVIEW_ENABLED && previewExists) {
226                            return true;
227                    }
228    
229                    return false;
230            }
231    
232            private boolean _isGeneratePreview(FileVersion fileVersion)
233                    throws Exception {
234    
235                    String previewFilePath = getPreviewFilePath(fileVersion);
236    
237                    if (PropsValues.DL_FILE_ENTRY_PREVIEW_ENABLED &&
238                            !DLStoreUtil.hasFile(
239                                    fileVersion.getCompanyId(), REPOSITORY_ID, previewFilePath)) {
240    
241                            return true;
242                    }
243                    else {
244                            return false;
245                    }
246            }
247    
248            private void _queueGeneration(FileVersion fileVersion) {
249                    if (_fileVersionIds.contains(fileVersion.getFileVersionId()) ||
250                            !isSupported(fileVersion)) {
251    
252                            return;
253                    }
254    
255                    _fileVersionIds.add(fileVersion.getFileVersionId());
256    
257                    MessageBusUtil.sendMessage(
258                            DestinationNames.DOCUMENT_LIBRARY_AUDIO_PROCESSOR, fileVersion);
259            }
260    
261            private static int _SAMPLE_RATE = 44100;
262    
263            private static Log _log = LogFactoryUtil.getLog(AudioProcessor.class);
264    
265            private static AudioProcessor _instance = new AudioProcessor();
266    
267            private static Set<String> _audioMimeTypes = SetUtil.fromArray(
268                    PropsValues.DL_FILE_ENTRY_PREVIEW_AUDIO_MIME_TYPES);
269            private static List<Long> _fileVersionIds = new Vector<Long>();
270    
271    }