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.image.ImageBag;
018    import com.liferay.portal.kernel.image.ImageToolUtil;
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.MessageBusException;
023    import com.liferay.portal.kernel.messaging.MessageBusUtil;
024    import com.liferay.portal.kernel.repository.model.FileEntry;
025    import com.liferay.portal.kernel.repository.model.FileVersion;
026    import com.liferay.portal.kernel.util.FileUtil;
027    import com.liferay.portal.kernel.util.InstancePool;
028    import com.liferay.portal.kernel.util.SetUtil;
029    import com.liferay.portal.kernel.util.StringBundler;
030    import com.liferay.portal.kernel.util.StringPool;
031    import com.liferay.portal.kernel.util.Validator;
032    import com.liferay.portal.util.PropsValues;
033    import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
034    
035    import java.awt.image.RenderedImage;
036    
037    import java.io.File;
038    import java.io.InputStream;
039    
040    import java.util.List;
041    import java.util.Set;
042    import java.util.Vector;
043    
044    /**
045     * @author Sergio González
046     * @author Alexander Chow
047     */
048    public class ImageProcessorImpl
049            extends DLPreviewableProcessor implements ImageProcessor {
050    
051            public static ImageProcessorImpl getInstance() {
052                    return _instance;
053            }
054    
055            public void cleanUp(FileEntry fileEntry) {
056                    deleteFiles(fileEntry, null);
057            }
058    
059            public void cleanUp(FileVersion fileVersion) {
060                    String type = _instance.getThumbnailType(fileVersion);
061    
062                    deleteFiles(fileVersion, type);
063            }
064    
065            public void generateImages(FileVersion fileVersion) {
066                    _instance._generateImages(fileVersion);
067            }
068    
069            public Set<String> getImageMimeTypes() {
070                    return _instance._imageMimeTypes;
071            }
072    
073            public InputStream getThumbnailAsStream(
074                            FileVersion fileVersion, int thumbnailIndex)
075                    throws Exception {
076    
077                    return _instance.doGetThumbnailAsStream(fileVersion, thumbnailIndex);
078            }
079    
080            public long getThumbnailFileSize(
081                            FileVersion fileVersion, int thumbnailIndex)
082                    throws Exception {
083    
084                    return _instance.doGetThumbnailFileSize(fileVersion, thumbnailIndex);
085            }
086    
087            public boolean hasImages(FileVersion fileVersion) {
088                    if (!PropsValues.DL_FILE_ENTRY_THUMBNAIL_ENABLED) {
089                            return false;
090                    }
091    
092                    boolean hasImages = false;
093    
094                    try {
095                            hasImages = _instance._hasImages(fileVersion);
096    
097                            if (!hasImages && _instance.isSupported(fileVersion)) {
098                                    _instance._queueGeneration(fileVersion);
099                            }
100                    }
101                    catch (Exception e) {
102                            _log.error(e, e);
103                    }
104    
105                    return hasImages;
106            }
107    
108            public boolean isImageSupported(FileVersion fileVersion) {
109                    return _instance.isSupported(fileVersion);
110            }
111    
112            public boolean isImageSupported(String mimeType) {
113                    return _instance.isSupported(mimeType);
114            }
115    
116            public boolean isSupported(String mimeType) {
117                    if (Validator.isNull(mimeType)) {
118                            return false;
119                    }
120    
121                    return _imageMimeTypes.contains(mimeType);
122            }
123    
124            public void storeThumbnail(
125                            long companyId, long groupId, long fileEntryId, long fileVersionId,
126                            long custom1ImageId, long custom2ImageId,
127                            InputStream is, String type)
128                    throws Exception {
129    
130                    _instance._storeThumbnail(
131                            companyId, groupId, fileEntryId, fileVersionId, custom1ImageId,
132                            custom2ImageId, is, type);
133            }
134    
135            public void trigger(FileVersion fileVersion) {
136                    _instance._queueGeneration(fileVersion);
137            }
138    
139            @Override
140            protected String getPreviewType(FileVersion fileVersion) {
141                    return null;
142            }
143    
144            @Override
145            protected String getThumbnailType(FileVersion fileVersion) {
146                    String type = fileVersion.getExtension();
147    
148                    if (type.equals("jpeg")) {
149                            type = "jpg";
150                    }
151    
152                    return type;
153            }
154    
155            private ImageProcessorImpl() {
156            }
157    
158            private void _generateImages(FileVersion fileVersion) {
159                    try {
160                            if (!PropsValues.DL_FILE_ENTRY_THUMBNAIL_ENABLED) {
161                                    return;
162                            }
163    
164                            InputStream inputStream = fileVersion.getContentStream(false);
165    
166                            byte[] bytes = FileUtil.getBytes(inputStream);
167    
168                            ImageBag imageBag = ImageToolUtil.read(bytes);
169    
170                            RenderedImage renderedImage = imageBag.getRenderedImage();
171    
172                            if (renderedImage == null) {
173                                    return;
174                            }
175    
176                            storeThumbnailImages(fileVersion, renderedImage);
177                    }
178                    catch (NoSuchFileEntryException nsfee) {
179                    }
180                    catch (Exception e) {
181                            _log.error(e, e);
182                    }
183                    finally {
184                            _fileVersionIds.remove(fileVersion.getFileVersionId());
185                    }
186            }
187    
188            private boolean _hasImages(FileVersion fileVersion) {
189                    if (PropsValues.DL_FILE_ENTRY_THUMBNAIL_ENABLED) {
190                            if (!hasThumbnail(fileVersion, THUMBNAIL_INDEX_DEFAULT)) {
191                                    return false;
192                            }
193                    }
194    
195                    try {
196                            if (isCustomThumbnailsEnabled(1)) {
197                                    if (!hasThumbnail(fileVersion, THUMBNAIL_INDEX_CUSTOM_1)) {
198                                            return false;
199                                    }
200                            }
201    
202                            if (isCustomThumbnailsEnabled(2)) {
203                                    if (!hasThumbnail(fileVersion, THUMBNAIL_INDEX_CUSTOM_2)) {
204                                            return false;
205                                    }
206                            }
207                    }
208                    catch (Exception e) {
209                            _log.error(e, e);
210                    }
211    
212                    return true;
213            }
214    
215            private void _queueGeneration(FileVersion fileVersion) {
216                    if (!_fileVersionIds.contains(fileVersion.getFileVersionId()) &&
217                            isSupported(fileVersion) && !_hasImages(fileVersion)) {
218                            _fileVersionIds.add(fileVersion.getFileVersionId());
219    
220                            if (PropsValues.DL_FILE_ENTRY_PROCESSORS_TRIGGER_SYNCHRONOUSLY) {
221                                    try {
222                                            MessageBusUtil.sendSynchronousMessage(
223                                                    DestinationNames.DOCUMENT_LIBRARY_IMAGE_PROCESSOR,
224                                                    fileVersion);
225                                    }
226                                    catch (MessageBusException mbe) {
227                                            if (_log.isWarnEnabled()) {
228                                                    _log.warn(mbe, mbe);
229                                            }
230                                    }
231                            }
232                            else {
233                                    MessageBusUtil.sendMessage(
234                                            DestinationNames.DOCUMENT_LIBRARY_IMAGE_PROCESSOR,
235                                            fileVersion);
236                            }
237                    }
238            }
239    
240            private void _storeThumbnail(
241                            long companyId, long groupId, long fileEntryId, long fileVersionId,
242                            long custom1ImageId, long custom2ImageId, InputStream is,
243                            String type)
244                    throws Exception {
245    
246                    StringBundler sb = new StringBundler(5);
247    
248                    sb.append(getPathSegment(groupId, fileEntryId, fileVersionId, false));
249    
250                    if (custom1ImageId != 0) {
251                            sb.append(StringPool.DASH);
252                            sb.append(1);
253                    }
254                    else if (custom2ImageId != 0) {
255                            sb.append(StringPool.DASH);
256                            sb.append(2);
257                    }
258    
259                    sb.append(StringPool.PERIOD);
260                    sb.append(type);
261    
262                    String filePath = sb.toString();
263    
264                    File file = null;
265    
266                    try {
267                            file = FileUtil.createTempFile(is);
268    
269                            addFileToStore(companyId, THUMBNAIL_PATH, filePath, file);
270                    }
271                    finally {
272                            FileUtil.delete(file);
273                    }
274            }
275    
276            private static Log _log = LogFactoryUtil.getLog(ImageProcessorImpl.class);
277    
278            private static ImageProcessorImpl _instance = new ImageProcessorImpl();
279    
280            static {
281                    InstancePool.put(ImageProcessorImpl.class.getName(), _instance);
282            }
283    
284            private List<Long> _fileVersionIds = new Vector<Long>();
285            private Set<String> _imageMimeTypes = SetUtil.fromArray(
286                    PropsValues.DL_FILE_ENTRY_PREVIEW_IMAGE_MIME_TYPES);
287    
288    }