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.image.ImageBag;
018    import com.liferay.portal.kernel.image.ImageProcessorUtil;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.messaging.DestinationNames;
022    import com.liferay.portal.kernel.messaging.MessageBusUtil;
023    import com.liferay.portal.kernel.repository.model.FileEntry;
024    import com.liferay.portal.kernel.repository.model.FileVersion;
025    import com.liferay.portal.kernel.util.FileUtil;
026    import com.liferay.portal.kernel.util.PropsKeys;
027    import com.liferay.portal.kernel.util.SetUtil;
028    import com.liferay.portal.kernel.util.StringBundler;
029    import com.liferay.portal.kernel.util.StringPool;
030    import com.liferay.portal.model.CompanyConstants;
031    import com.liferay.portal.util.PrefsPropsUtil;
032    import com.liferay.portal.util.PropsValues;
033    import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
034    import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
035    
036    import java.awt.image.RenderedImage;
037    
038    import java.io.File;
039    import java.io.IOException;
040    import java.io.InputStream;
041    
042    import java.util.List;
043    import java.util.Set;
044    import java.util.Vector;
045    
046    /**
047     * @author Sergio González
048     * @author Alexander Chow
049     */
050    public class ImageProcessor extends DLPreviewableProcessor {
051    
052            public void cleanUp(FileEntry fileEntry) {
053                    deleteFiles(fileEntry, null);
054            }
055    
056            public void cleanUp(FileVersion fileVersion) {
057                    String type = _instance._getType(fileVersion);
058    
059                    deleteFiles(fileVersion, type);
060            }
061    
062            public static void generateImages(FileVersion fileVersion) {
063                    _instance._generateImages(fileVersion);
064            }
065    
066            public static InputStream getCustom1AsStream(FileVersion fileVersion)
067                    throws Exception {
068    
069                    String type = _instance._getType(fileVersion);
070    
071                    return _instance._getCustomAsStream(fileVersion, type, 1);
072            }
073    
074            public static long getCustom1FileSize(FileVersion fileVersion)
075                    throws Exception {
076    
077                    String type = _instance._getType(fileVersion);
078    
079                    return _instance._getCustomFileSize(fileVersion, type, 1);
080            }
081    
082            public static InputStream getCustom2AsStream(FileVersion fileVersion)
083                    throws Exception {
084    
085                    String type = _instance._getType(fileVersion);
086    
087                    return _instance._getCustomAsStream(fileVersion, type, 2);
088            }
089    
090            public static long getCustom2FileSize(FileVersion fileVersion)
091                    throws Exception {
092    
093                    String type = _instance._getType(fileVersion);
094    
095                    return _instance._getCustomFileSize(fileVersion, type, 2);
096            }
097    
098            public static Set<String> getImageMimeTypes() {
099                    return _imageMimeTypes;
100            }
101    
102            public static InputStream getThumbnailAsStream(FileVersion fileVersion)
103                    throws Exception {
104    
105                    String type = _instance._getType(fileVersion);
106    
107                    return _instance.doGetThumbnailAsStream(fileVersion, type);
108            }
109    
110            public static long getThumbnailFileSize(FileVersion fileVersion)
111                    throws Exception {
112    
113                    String type = _instance._getType(fileVersion);
114    
115                    return _instance.doGetThumbnailFileSize(fileVersion, type);
116            }
117    
118            public static boolean hasImages(FileVersion fileVersion) {
119                    if (!PropsValues.DL_FILE_ENTRY_THUMBNAIL_ENABLED) {
120                            return false;
121                    }
122    
123                    boolean hasImages = false;
124    
125                    try {
126                            hasImages = _instance._hasImages(fileVersion);
127    
128                            if (!hasImages && _instance.isSupported(fileVersion)) {
129                                    _instance._queueGeneration(fileVersion);
130                            }
131                    }
132                    catch (Exception e) {
133                            _log.error(e, e);
134                    }
135    
136                    return hasImages;
137            }
138    
139            public static boolean hasThumbnailImage(FileVersion fileVersion) {
140                    return _instance._hasThumbnailImage(fileVersion);
141            }
142    
143            public static void storeThumbnail(
144                            long companyId, long groupId, long fileEntryId, long fileVersionId,
145                            long custom1ImageId, long custom2ImageId,
146                            InputStream is, String type)
147                    throws Exception {
148    
149                    _instance._storeThumbnail(
150                            companyId, groupId, fileEntryId, fileVersionId, custom1ImageId,
151                            custom2ImageId, is, type);
152            }
153    
154            public boolean isSupported(String mimeType) {
155                    return _imageMimeTypes.contains(mimeType);
156            }
157    
158            public void trigger(FileVersion fileVersion) {
159                    _instance._queueGeneration(fileVersion);
160            }
161    
162            private void _generateImages(FileVersion fileVersion) {
163                    try {
164                            if (!PropsValues.DL_FILE_ENTRY_THUMBNAIL_ENABLED) {
165                                    return;
166                            }
167    
168                            InputStream inputStream = fileVersion.getContentStream(false);
169    
170                            byte[] bytes = FileUtil.getBytes(inputStream);
171    
172                            ImageBag imageBag = ImageProcessorUtil.read(bytes);
173    
174                            RenderedImage renderedImage = imageBag.getRenderedImage();
175    
176                            if (renderedImage == null) {
177                                    return;
178                            }
179    
180                            String type = _instance._getType(fileVersion);
181    
182                            _saveThumbnailImage(
183                                    fileVersion, renderedImage,
184                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_MAX_HEIGHT,
185                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_MAX_WIDTH,
186                                    getThumbnailFilePath(fileVersion, type));
187    
188                            if ((PrefsPropsUtil.getInteger(
189                                            PropsKeys.
190                                                    DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_HEIGHT) > 0) ||
191                                    (PrefsPropsUtil.getInteger(
192                                            PropsKeys.
193                                                    DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_WIDTH) > 0)) {
194    
195                                    _saveThumbnailImage(
196                                            fileVersion, renderedImage,
197                                            PropsKeys.DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_HEIGHT,
198                                            PropsKeys.DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_WIDTH,
199                                            _getCustom1FilePath(fileVersion, type));
200                            }
201    
202                            if ((PrefsPropsUtil.getInteger(
203                                            PropsKeys.
204                                                    DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_HEIGHT) > 0) ||
205                                    (PrefsPropsUtil.getInteger(
206                                            PropsKeys.
207                                                    DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_WIDTH) > 0)) {
208    
209                                    _saveThumbnailImage(
210                                            fileVersion, renderedImage,
211                                            PropsKeys.DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_HEIGHT,
212                                            PropsKeys.DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_WIDTH,
213                                            _getCustom2FilePath(fileVersion, type));
214                            }
215                    }
216                    catch (NoSuchFileEntryException nsfee) {
217                    }
218                    catch (Exception e) {
219                            _log.error(e, e);
220                    }
221                    finally {
222                            _fileVersionIds.remove(fileVersion.getFileVersionId());
223                    }
224            }
225    
226            private String _getCustom1FilePath(
227                    FileVersion fileVersion, String type) {
228    
229                    return _getCustomFilePath(fileVersion, type, 1);
230            }
231    
232            private String _getCustom2FilePath(
233                    FileVersion fileVersion, String type) {
234    
235                    return _getCustomFilePath(fileVersion, type, 2);
236            }
237    
238            private InputStream _getCustomAsStream(
239                            FileVersion fileVersion, String type, int index)
240                    throws Exception {
241    
242                    return DLStoreUtil.getFileAsStream(
243                            fileVersion.getCompanyId(), CompanyConstants.SYSTEM,
244                            _getCustomFilePath(fileVersion, type, index));
245            }
246    
247            private String _getCustomFilePath(
248                    FileVersion fileVersion, String type, int index) {
249    
250                    StringBundler sb = new StringBundler(5);
251    
252                    sb.append(getPathSegment(fileVersion, false));
253                    sb.append(StringPool.DASH);
254                    sb.append(index);
255                    sb.append(StringPool.PERIOD);
256                    sb.append(type);
257    
258                    return sb.toString();
259            }
260    
261            private long _getCustomFileSize(
262                            FileVersion fileVersion, String type, int index)
263                    throws Exception {
264    
265                    return DLStoreUtil.getFileSize(
266                            fileVersion.getCompanyId(), CompanyConstants.SYSTEM,
267                            _getCustomFilePath(fileVersion, type, index));
268            }
269    
270            private String _getType(FileVersion fileVersion) {
271                    String type = fileVersion.getExtension();
272    
273                    if (type.equals("jpeg")) {
274                            type = "jpg";
275                    }
276    
277                    return type;
278            }
279    
280            private boolean _hasCustomImage(FileVersion fileVersion, int index) {
281                    try {
282                            String type = _getType(fileVersion);
283    
284                            return DLStoreUtil.hasFile(
285                                    fileVersion.getCompanyId(), REPOSITORY_ID,
286                                    _getCustomFilePath(fileVersion, type, index));
287                    }
288                    catch (Exception e) {
289                            _log.error(e, e);
290                    }
291    
292                    return false;
293            }
294    
295            private boolean _hasImages(FileVersion fileVersion) {
296                    if (!_hasThumbnailImage(fileVersion)) {
297                            return false;
298                    }
299    
300                    try {
301                            if ((PrefsPropsUtil.getInteger(
302                                            PropsKeys.
303                                                    DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_HEIGHT) > 0) ||
304                                    (PrefsPropsUtil.getInteger(
305                                            PropsKeys.
306                                                    DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_WIDTH) > 0)) {
307    
308                                    if (!_hasCustomImage(fileVersion, 1)) {
309                                            return false;
310                                    }
311                            }
312    
313                            if ((PrefsPropsUtil.getInteger(
314                                                    PropsKeys.
315                                                            DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_HEIGHT) > 0) ||
316                                            (PrefsPropsUtil.getInteger(
317                                                    PropsKeys.
318                                                            DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_WIDTH) > 0)) {
319    
320                                    if (!_hasCustomImage(fileVersion, 2)) {
321                                            return false;
322                                    }
323                            }
324                    }
325                    catch (Exception e) {
326                            _log.error(e, e);
327                    }
328    
329                    return true;
330            }
331    
332            private boolean _hasThumbnailImage(FileVersion fileVersion) {
333                    try {
334                            String imageType = _getType(fileVersion);
335    
336                            return DLStoreUtil.hasFile(
337                                    fileVersion.getCompanyId(), REPOSITORY_ID,
338                                    getThumbnailFilePath(fileVersion, imageType));
339                    }
340                    catch (Exception e) {
341                            _log.error(e, e);
342                    }
343    
344                    return false;
345            }
346    
347            private void _queueGeneration(FileVersion fileVersion) {
348                    if (!_fileVersionIds.contains(fileVersion.getFileVersionId()) &&
349                            isSupported(fileVersion) && !_hasImages(fileVersion)) {
350                            _fileVersionIds.add(fileVersion.getFileVersionId());
351    
352                            MessageBusUtil.sendMessage(
353                                    DestinationNames.DOCUMENT_LIBRARY_IMAGE_PROCESSOR,
354                                    fileVersion);
355                    }
356            }
357    
358            private void _saveThumbnailImage(
359                            FileVersion fileVersion, RenderedImage renderedImage,
360                            String maxHeightPropsKey, String maxWidthPropsKey, String filePath)
361                    throws Exception {
362    
363                    File file = _scaleImage(
364                            renderedImage, fileVersion.getMimeType(),
365                            PrefsPropsUtil.getInteger(maxHeightPropsKey),
366                            PrefsPropsUtil.getInteger(maxWidthPropsKey));
367    
368                    try {
369                            addFileToStore(
370                                    fileVersion.getCompanyId(), THUMBNAIL_PATH, filePath, file);
371                    }
372                    finally {
373                            FileUtil.delete(file);
374                    }
375            }
376    
377            private File _scaleImage(
378                            RenderedImage renderedImage, String contentType, int height,
379                            int width)
380                    throws IOException {
381    
382                    RenderedImage thumbnailRenderedImage = ImageProcessorUtil.scale(
383                            renderedImage, height, width);
384    
385                    byte[] bytes = ImageProcessorUtil.getBytes(
386                            thumbnailRenderedImage, contentType);
387    
388                    return FileUtil.createTempFile(bytes);
389            }
390    
391            private void _storeThumbnail(
392                            long companyId, long groupId, long fileEntryId, long fileVersionId,
393                            long custom1ImageId, long custom2ImageId, InputStream is,
394                            String type)
395                    throws Exception {
396    
397                    StringBundler sb = new StringBundler(5);
398    
399                    sb.append(getPathSegment(groupId, fileEntryId, fileVersionId, false));
400    
401                    if (custom1ImageId != 0) {
402                            sb.append(StringPool.DASH);
403                            sb.append(1);
404                    }
405                    else if (custom2ImageId != 0) {
406                            sb.append(StringPool.DASH);
407                            sb.append(2);
408                    }
409    
410                    sb.append(StringPool.PERIOD);
411                    sb.append(type);
412    
413                    String filePath = sb.toString();
414    
415                    File file = null;
416    
417                    try {
418                            file = FileUtil.createTempFile(is);
419    
420                            addFileToStore(companyId, THUMBNAIL_PATH, filePath, file);
421                    }
422                    finally {
423                            FileUtil.delete(file);
424                    }
425            }
426    
427            private static Log _log = LogFactoryUtil.getLog(ImageProcessor.class);
428    
429            private static ImageProcessor _instance = new ImageProcessor();
430    
431            private static List<Long> _fileVersionIds = new Vector<Long>();
432            private static Set<String> _imageMimeTypes = SetUtil.fromArray(
433                    PropsValues.DL_FILE_ENTRY_PREVIEW_IMAGE_MIME_TYPES);
434    
435    }