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