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