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