001
014
015 package com.liferay.portlet.documentlibrary.util;
016
017 import com.liferay.portal.kernel.exception.PortalException;
018 import com.liferay.portal.kernel.exception.SystemException;
019 import com.liferay.portal.kernel.image.ImageBag;
020 import com.liferay.portal.kernel.image.ImageTool;
021 import com.liferay.portal.kernel.image.ImageToolUtil;
022 import com.liferay.portal.kernel.lar.PortletDataContext;
023 import com.liferay.portal.kernel.log.Log;
024 import com.liferay.portal.kernel.log.LogFactoryUtil;
025 import com.liferay.portal.kernel.messaging.DestinationNames;
026 import com.liferay.portal.kernel.repository.model.FileEntry;
027 import com.liferay.portal.kernel.repository.model.FileVersion;
028 import com.liferay.portal.kernel.util.ContentTypes;
029 import com.liferay.portal.kernel.util.FileUtil;
030 import com.liferay.portal.kernel.util.SetUtil;
031 import com.liferay.portal.kernel.util.StreamUtil;
032 import com.liferay.portal.kernel.util.StringBundler;
033 import com.liferay.portal.kernel.util.StringPool;
034 import com.liferay.portal.kernel.util.Validator;
035 import com.liferay.portal.kernel.xml.Element;
036 import com.liferay.portal.util.PropsValues;
037 import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
038 import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
039
040 import java.awt.image.ColorModel;
041 import java.awt.image.RenderedImage;
042
043 import java.io.File;
044 import java.io.FileOutputStream;
045 import java.io.InputStream;
046
047 import java.util.List;
048 import java.util.Set;
049 import java.util.Vector;
050 import java.util.concurrent.Future;
051
052
057 public class ImageProcessorImpl
058 extends DLPreviewableProcessor implements ImageProcessor {
059
060 @Override
061 public void afterPropertiesSet() {
062 }
063
064 @Override
065 public void cleanUp(FileEntry fileEntry) {
066 deleteFiles(fileEntry, null);
067 }
068
069 @Override
070 public void cleanUp(FileVersion fileVersion) {
071 String type = getThumbnailType(fileVersion);
072
073 deleteFiles(fileVersion, type);
074 }
075
076 @Override
077 public void generateImages(
078 FileVersion sourceFileVersion, FileVersion destinationFileVersion)
079 throws Exception {
080
081 _generateImages(sourceFileVersion, destinationFileVersion);
082 }
083
084 @Override
085 public Set<String> getImageMimeTypes() {
086 return _imageMimeTypes;
087 }
088
089 @Override
090 public InputStream getPreviewAsStream(FileVersion fileVersion)
091 throws Exception {
092
093 if (_previewGenerationRequired(fileVersion)) {
094 String type = getPreviewType(fileVersion);
095
096 return doGetPreviewAsStream(fileVersion, type);
097 }
098
099 return fileVersion.getContentStream(false);
100 }
101
102 @Override
103 public long getPreviewFileSize(FileVersion fileVersion) throws Exception {
104 if (_previewGenerationRequired(fileVersion)) {
105 String type = getPreviewType(fileVersion);
106
107 return doGetPreviewFileSize(fileVersion, type);
108 }
109
110 return fileVersion.getSize();
111 }
112
113 @Override
114 public String getPreviewType(FileVersion fileVersion) {
115 return _getType(fileVersion);
116 }
117
118 @Override
119 public InputStream getThumbnailAsStream(FileVersion fileVersion, int index)
120 throws Exception {
121
122 return doGetThumbnailAsStream(fileVersion, index);
123 }
124
125 @Override
126 public long getThumbnailFileSize(FileVersion fileVersion, int index)
127 throws Exception {
128
129 return doGetThumbnailFileSize(fileVersion, index);
130 }
131
132 @Override
133 public String getThumbnailType(FileVersion fileVersion) {
134 return _getType(fileVersion);
135 }
136
137 @Override
138 public boolean hasImages(FileVersion fileVersion) {
139 if (!PropsValues.DL_FILE_ENTRY_PREVIEW_ENABLED &&
140 !PropsValues.DL_FILE_ENTRY_THUMBNAIL_ENABLED) {
141
142 return false;
143 }
144
145 boolean hasImages = false;
146
147 try {
148 if (_hasPreview(fileVersion) && hasThumbnails(fileVersion)) {
149 hasImages = true;
150 }
151
152 if (!hasImages && isSupported(fileVersion)) {
153 _queueGeneration(null, fileVersion);
154 }
155 }
156 catch (Exception e) {
157 _log.error(e, e);
158 }
159
160 return hasImages;
161 }
162
163 @Override
164 public boolean isImageSupported(FileVersion fileVersion) {
165 return isSupported(fileVersion);
166 }
167
168 @Override
169 public boolean isImageSupported(String mimeType) {
170 return isSupported(mimeType);
171 }
172
173 @Override
174 public boolean isSupported(String mimeType) {
175 if (Validator.isNull(mimeType)) {
176 return false;
177 }
178
179 return _imageMimeTypes.contains(mimeType);
180 }
181
182 @Override
183 public void storeThumbnail(
184 long companyId, long groupId, long fileEntryId, long fileVersionId,
185 long custom1ImageId, long custom2ImageId, InputStream is,
186 String type)
187 throws Exception {
188
189 _storeThumbnail(
190 companyId, groupId, fileEntryId, fileVersionId, custom1ImageId,
191 custom2ImageId, is, type);
192 }
193
194 @Override
195 public void trigger(
196 FileVersion sourceFileVersion, FileVersion destinationFileVersion) {
197
198 super.trigger(sourceFileVersion, destinationFileVersion);
199
200 _queueGeneration(sourceFileVersion, destinationFileVersion);
201 }
202
203 @Override
204 protected void doExportGeneratedFiles(
205 PortletDataContext portletDataContext, FileEntry fileEntry,
206 Element fileEntryElement)
207 throws Exception {
208
209 exportThumbnails(
210 portletDataContext, fileEntry, fileEntryElement, "image");
211
212 exportPreview(portletDataContext, fileEntry, fileEntryElement);
213 }
214
215 @Override
216 protected void doImportGeneratedFiles(
217 PortletDataContext portletDataContext, FileEntry fileEntry,
218 FileEntry importedFileEntry, Element fileEntryElement)
219 throws Exception {
220
221 importThumbnails(
222 portletDataContext, fileEntry, importedFileEntry, fileEntryElement,
223 "image");
224
225 FileVersion importedFileVersion = importedFileEntry.getFileVersion();
226
227 if (!_previewGenerationRequired(importedFileVersion)) {
228 return;
229 }
230
231 importPreview(
232 portletDataContext, fileEntry, importedFileEntry, fileEntryElement,
233 "image", getPreviewType(importedFileVersion));
234 }
235
236 protected void exportPreview(
237 PortletDataContext portletDataContext, FileEntry fileEntry,
238 Element fileEntryElement)
239 throws Exception {
240
241 FileVersion fileVersion = fileEntry.getFileVersion();
242
243 if (!isSupported(fileVersion) ||
244 !_previewGenerationRequired(fileVersion) ||
245 !_hasPreview(fileVersion)) {
246
247 return;
248 }
249
250 exportPreview(
251 portletDataContext, fileEntry, fileEntryElement, "image",
252 getPreviewType(fileVersion));
253 }
254
255 @Override
256 protected List<Long> getFileVersionIds() {
257 return _fileVersionIds;
258 }
259
260 private void _generateImages(
261 FileVersion sourceFileVersion, FileVersion destinationFileVersion)
262 throws Exception {
263
264 InputStream inputStream = null;
265
266 try {
267 if (sourceFileVersion != null) {
268 copy(sourceFileVersion, destinationFileVersion);
269
270 return;
271 }
272
273 if (!PropsValues.DL_FILE_ENTRY_THUMBNAIL_ENABLED &&
274 !PropsValues.DL_FILE_ENTRY_PREVIEW_ENABLED) {
275
276 return;
277 }
278
279 inputStream = destinationFileVersion.getContentStream(false);
280
281 byte[] bytes = FileUtil.getBytes(inputStream);
282
283 ImageBag imageBag = ImageToolUtil.read(bytes);
284
285 RenderedImage renderedImage = imageBag.getRenderedImage();
286
287 if (renderedImage == null) {
288 return;
289 }
290
291 ColorModel colorModel = renderedImage.getColorModel();
292
293 if (colorModel.getNumColorComponents() == 4) {
294 Future<RenderedImage> future = ImageToolUtil.convertCMYKtoRGB(
295 bytes, imageBag.getType());
296
297 if (future == null) {
298 return;
299 }
300
301 String processIdentity = String.valueOf(
302 destinationFileVersion.getFileVersionId());
303
304 futures.put(processIdentity, future);
305
306 RenderedImage convertedRenderedImage = future.get();
307
308 if (convertedRenderedImage != null) {
309 renderedImage = convertedRenderedImage;
310 }
311 }
312
313 if (!_hasPreview(destinationFileVersion)) {
314 _storePreviewImage(destinationFileVersion, renderedImage);
315 }
316
317 if (!hasThumbnails(destinationFileVersion)) {
318 storeThumbnailImages(destinationFileVersion, renderedImage);
319 }
320 }
321 catch (NoSuchFileEntryException nsfee) {
322 }
323 finally {
324 StreamUtil.cleanUp(inputStream);
325
326 _fileVersionIds.remove(destinationFileVersion.getFileVersionId());
327 }
328 }
329
330 private String _getType(FileVersion fileVersion) {
331 String type = "png";
332
333 if (fileVersion == null) {
334 return type;
335 }
336
337 String mimeType = fileVersion.getMimeType();
338
339 if (mimeType.equals(ContentTypes.IMAGE_BMP)) {
340 type = ImageTool.TYPE_BMP;
341 }
342 else if (mimeType.equals(ContentTypes.IMAGE_GIF)) {
343 type = ImageTool.TYPE_GIF;
344 }
345 else if (mimeType.equals(ContentTypes.IMAGE_JPEG)) {
346 type = ImageTool.TYPE_JPEG;
347 }
348 else if (mimeType.equals(ContentTypes.IMAGE_PNG)) {
349 type = ImageTool.TYPE_PNG;
350 }
351 else if (!_previewGenerationRequired(fileVersion)) {
352 type = fileVersion.getExtension();
353 }
354
355 return type;
356 }
357
358 private boolean _hasPreview(FileVersion fileVersion)
359 throws PortalException, SystemException {
360
361 if (PropsValues.DL_FILE_ENTRY_PREVIEW_ENABLED &&
362 _previewGenerationRequired(fileVersion)) {
363
364 String type = getPreviewType(fileVersion);
365
366 String previewFilePath = getPreviewFilePath(fileVersion, type);
367
368 if (!DLStoreUtil.hasFile(
369 fileVersion.getCompanyId(), REPOSITORY_ID,
370 previewFilePath)) {
371
372 return false;
373 }
374 }
375
376 return true;
377 }
378
379 private boolean _previewGenerationRequired(FileVersion fileVersion) {
380 String mimeType = fileVersion.getMimeType();
381
382 if (mimeType.contains("tiff") || mimeType.contains("tif")) {
383 return true;
384 }
385 else {
386 return false;
387 }
388 }
389
390 private void _queueGeneration(
391 FileVersion sourceFileVersion, FileVersion destinationFileVersion) {
392
393 if (_fileVersionIds.contains(
394 destinationFileVersion.getFileVersionId()) ||
395 !isSupported(destinationFileVersion)) {
396
397 return;
398 }
399
400 _fileVersionIds.add(destinationFileVersion.getFileVersionId());
401
402 sendGenerationMessage(
403 DestinationNames.DOCUMENT_LIBRARY_IMAGE_PROCESSOR,
404 sourceFileVersion, destinationFileVersion);
405 }
406
407 private void _storePreviewImage(
408 FileVersion fileVersion, RenderedImage renderedImage)
409 throws Exception {
410
411 String type = getPreviewType(fileVersion);
412
413 File file = null;
414
415 try {
416 file = FileUtil.createTempFile(type);
417
418 FileOutputStream fos = new FileOutputStream(file);
419
420 try {
421 ImageToolUtil.write(renderedImage, type, fos);
422 }
423 finally {
424 fos.close();
425 }
426
427 addFileToStore(
428 fileVersion.getCompanyId(), PREVIEW_PATH,
429 getPreviewFilePath(fileVersion, type), file);
430 }
431 finally {
432 FileUtil.delete(file);
433 }
434 }
435
436 private void _storeThumbnail(
437 long companyId, long groupId, long fileEntryId, long fileVersionId,
438 long custom1ImageId, long custom2ImageId, InputStream is,
439 String type)
440 throws Exception {
441
442 StringBundler sb = new StringBundler(5);
443
444 sb.append(getPathSegment(groupId, fileEntryId, fileVersionId, false));
445
446 if (custom1ImageId != 0) {
447 sb.append(StringPool.DASH);
448 sb.append(1);
449 }
450 else if (custom2ImageId != 0) {
451 sb.append(StringPool.DASH);
452 sb.append(2);
453 }
454
455 if (Validator.isNotNull(type)) {
456 sb.append(StringPool.PERIOD);
457 sb.append(type);
458 }
459
460 String filePath = sb.toString();
461
462 File file = null;
463
464 try {
465 file = FileUtil.createTempFile(is);
466
467 addFileToStore(companyId, THUMBNAIL_PATH, filePath, file);
468 }
469 finally {
470 FileUtil.delete(file);
471 }
472 }
473
474 private static Log _log = LogFactoryUtil.getLog(ImageProcessorImpl.class);
475
476 private List<Long> _fileVersionIds = new Vector<Long>();
477 private Set<String> _imageMimeTypes = SetUtil.fromArray(
478 PropsValues.DL_FILE_ENTRY_PREVIEW_IMAGE_MIME_TYPES);
479
480 }