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