001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.documentlibrary.util;
016    
017    import com.liferay.portal.kernel.image.ImageBag;
018    import com.liferay.portal.kernel.image.ImageToolUtil;
019    import com.liferay.portal.kernel.io.FileFilter;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.repository.model.FileEntry;
023    import com.liferay.portal.kernel.repository.model.FileVersion;
024    import com.liferay.portal.kernel.util.FileUtil;
025    import com.liferay.portal.kernel.util.MimeTypesUtil;
026    import com.liferay.portal.kernel.util.PrefsPropsUtil;
027    import com.liferay.portal.kernel.util.PropsKeys;
028    import com.liferay.portal.kernel.util.StringBundler;
029    import com.liferay.portal.kernel.util.StringPool;
030    import com.liferay.portal.kernel.util.SystemProperties;
031    import com.liferay.portal.model.CompanyConstants;
032    import com.liferay.portal.util.PortalUtil;
033    import com.liferay.portlet.documentlibrary.DuplicateDirectoryException;
034    import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
035    
036    import java.awt.image.RenderedImage;
037    
038    import java.io.File;
039    import java.io.InputStream;
040    
041    /**
042     * @author Alexander Chow
043     */
044    public abstract class DLPreviewableProcessor implements DLProcessor {
045    
046            public static final String PREVIEW_PATH = "document_preview/";
047    
048            public static final String PREVIEW_TMP_PATH =
049                    SystemProperties.get(SystemProperties.TMP_DIR) +
050                            "/liferay/" + PREVIEW_PATH;
051    
052            public static final long REPOSITORY_ID = CompanyConstants.SYSTEM;
053    
054            public static int THUMBNAIL_INDEX_CUSTOM_1 = 1;
055    
056            public static int THUMBNAIL_INDEX_CUSTOM_2 = 2;
057    
058            public static int THUMBNAIL_INDEX_DEFAULT = 0;
059    
060            public static final String THUMBNAIL_PATH = "document_thumbnail/";
061    
062            public static final String THUMBNAIL_TMP_PATH =
063                    SystemProperties.get(SystemProperties.TMP_DIR) +
064                            "/liferay/" + THUMBNAIL_PATH;
065    
066            public static void deleteFiles() {
067                    long[] companyIds = PortalUtil.getCompanyIds();
068    
069                    for (long companyId : companyIds) {
070                            try {
071                                    DLStoreUtil.deleteDirectory(
072                                            companyId, REPOSITORY_ID, PREVIEW_PATH);
073                            }
074                            catch (Exception e) {
075                            }
076    
077                            try {
078                                    DLStoreUtil.deleteDirectory(
079                                            companyId, REPOSITORY_ID, THUMBNAIL_PATH);
080                            }
081                            catch (Exception e) {
082                            }
083                    }
084            }
085    
086            public static void deleteFiles(FileEntry fileEntry, String thumbnailType) {
087                    deleteFiles(
088                            fileEntry.getCompanyId(), fileEntry.getRepositoryId(),
089                            fileEntry.getFileEntryId(), -1, thumbnailType);
090            }
091    
092            public static void deleteFiles(
093                    FileVersion fileVersion, String thumbnailType) {
094    
095                    deleteFiles(
096                            fileVersion.getCompanyId(), fileVersion.getRepositoryId(),
097                            fileVersion.getFileEntryId(), fileVersion.getFileVersionId(),
098                            thumbnailType);
099            }
100    
101            protected static void deleteFiles(
102                    long companyId, long groupId, long fileEntryId, long fileVersionId,
103                    String thumbnailType) {
104    
105                    try {
106                            DLStoreUtil.deleteDirectory(
107                                    companyId, REPOSITORY_ID,
108                                    getPathSegment(groupId, fileEntryId, fileVersionId, true));
109                    }
110                    catch (Exception e) {
111                    }
112    
113                    try {
114                            String dirName = getPathSegment(
115                                    groupId, fileEntryId, fileVersionId, false);
116    
117                            if (fileVersionId > 0) {
118                                    dirName = dirName.concat(StringPool.PERIOD);
119                                    dirName = dirName.concat(thumbnailType);
120                            }
121    
122                            DLStoreUtil.deleteDirectory(companyId, REPOSITORY_ID, dirName);
123                    }
124                    catch (Exception e) {
125                    }
126            }
127    
128            protected static String getPathSegment(
129                    FileVersion fileVersion, boolean preview) {
130    
131                    return getPathSegment(
132                            fileVersion.getGroupId(), fileVersion.getFileEntryId(),
133                            fileVersion.getFileVersionId(), preview);
134            }
135    
136            protected static String getPathSegment(
137                    long groupId, long fileEntryId, long fileVersionId, boolean preview) {
138    
139                    StringBundler sb = null;
140    
141                    if (fileVersionId > 0) {
142                            sb = new StringBundler(5);
143                    }
144                    else {
145                            sb = new StringBundler(3);
146                    }
147    
148                    if (preview) {
149                            sb.append(PREVIEW_PATH);
150                    }
151                    else {
152                            sb.append(THUMBNAIL_PATH);
153                    }
154    
155                    sb.append(groupId);
156                    sb.append(DLUtil.getDividedPath(fileEntryId));
157    
158                    if (fileVersionId > 0) {
159                            sb.append(StringPool.SLASH);
160                            sb.append(fileVersionId);
161                    }
162    
163                    return sb.toString();
164            }
165    
166            public boolean isSupported(FileVersion fileVersion) {
167                    if (fileVersion == null) {
168                            return false;
169                    }
170    
171                    return isSupported(fileVersion.getMimeType());
172            }
173    
174            protected void addFileToStore(
175                            long companyId, String dirName, String filePath, File srcFile)
176                    throws Exception {
177    
178                    try {
179                            DLStoreUtil.addDirectory(companyId, REPOSITORY_ID, dirName);
180                    }
181                    catch (DuplicateDirectoryException dde) {
182                    }
183    
184                    DLStoreUtil.addFile(companyId, REPOSITORY_ID, filePath, srcFile);
185            }
186    
187            protected InputStream doGetPreviewAsStream(
188                            FileVersion fileVersion, int index, String type)
189                    throws Exception {
190    
191                    return DLStoreUtil.getFileAsStream(
192                            fileVersion.getCompanyId(), CompanyConstants.SYSTEM,
193                            getPreviewFilePath(fileVersion, index, type));
194            }
195    
196            protected InputStream doGetPreviewAsStream(
197                            FileVersion fileVersion, String type)
198                    throws Exception {
199    
200                    return doGetPreviewAsStream(fileVersion, 0, type);
201            }
202    
203            protected int doGetPreviewFileCount(FileVersion fileVersion)
204                    throws Exception {
205    
206                    try {
207                            String[] fileNames = DLStoreUtil.getFileNames(
208                                    fileVersion.getCompanyId(), REPOSITORY_ID,
209                                    getPathSegment(fileVersion, true));
210    
211                            return fileNames.length;
212                    }
213                    catch (Exception e) {
214                    }
215    
216                    return 0;
217            }
218    
219            protected long doGetPreviewFileSize(
220                            FileVersion fileVersion, int index, String type)
221                    throws Exception {
222    
223                    return DLStoreUtil.getFileSize(
224                            fileVersion.getCompanyId(), CompanyConstants.SYSTEM,
225                            getPreviewFilePath(fileVersion, index, type));
226            }
227    
228            protected long doGetPreviewFileSize(FileVersion fileVersion, String type)
229                    throws Exception {
230    
231                    return doGetPreviewFileSize(fileVersion, 0, type);
232            }
233    
234            protected InputStream doGetThumbnailAsStream(
235                            FileVersion fileVersion, int thumbnailIndex)
236                    throws Exception {
237    
238                    String type = getThumbnailType(fileVersion);
239    
240                    return DLStoreUtil.getFileAsStream(
241                            fileVersion.getCompanyId(), CompanyConstants.SYSTEM,
242                            getThumbnailFilePath(fileVersion, type, thumbnailIndex));
243            }
244    
245            protected long doGetThumbnailFileSize(
246                            FileVersion fileVersion, int thumbnailIndex)
247                    throws Exception {
248    
249                    String type = getThumbnailType(fileVersion);
250    
251                    return DLStoreUtil.getFileSize(
252                            fileVersion.getCompanyId(), CompanyConstants.SYSTEM,
253                            getThumbnailFilePath(fileVersion, type, thumbnailIndex));
254            }
255    
256            protected String getPreviewFilePath(
257                    FileVersion fileVersion, int index, String type) {
258    
259                    StringBundler sb = null;
260    
261                    if (index > 0) {
262                            sb = new StringBundler(5);
263                    }
264                    else {
265                            sb = new StringBundler(3);
266                    }
267    
268                    sb.append(getPathSegment(fileVersion, true));
269    
270                    if (index > 0) {
271                            sb.append(StringPool.SLASH);
272                            sb.append(index - 1);
273                    }
274    
275                    sb.append(StringPool.PERIOD);
276                    sb.append(type);
277    
278                    return sb.toString();
279            }
280    
281            protected String getPreviewFilePath(FileVersion fileVersion, String type) {
282                    return getPreviewFilePath(fileVersion, 0, type);
283            }
284    
285            protected File getPreviewTempFile(String id, int index, String type) {
286                    String previewTempFilePath = getPreviewTempFilePath(id, index, type);
287    
288                    return new File(previewTempFilePath);
289            }
290    
291            protected File getPreviewTempFile(String id, String type) {
292                    return getPreviewTempFile(id, 0, type);
293            }
294    
295            protected int getPreviewTempFileCount(
296                    FileVersion fileVersion, String type) {
297    
298                    String tempFileId = DLUtil.getTempFileId(
299                            fileVersion.getFileEntryId(), fileVersion.getVersion());
300    
301                    StringBundler sb = new StringBundler(5);
302    
303                    sb.append(tempFileId);
304                    sb.append(StringPool.DASH);
305                    sb.append("(.*)");
306                    sb.append(StringPool.PERIOD);
307                    sb.append(type);
308    
309                    File dir = new File(PREVIEW_TMP_PATH);
310    
311                    File[] files = dir.listFiles(new FileFilter(sb.toString()));
312    
313                    if (_log.isDebugEnabled()) {
314                            for (File file : files) {
315                                    _log.debug("Preview page for " + tempFileId + " " + file);
316                            }
317                    }
318    
319                    return files.length;
320            }
321    
322            protected String getPreviewTempFilePath(String id, int index, String type) {
323                    StringBundler sb = null;
324    
325                    if (index > 0) {
326                            sb = new StringBundler(6);
327                    }
328                    else {
329                            sb = new StringBundler(4);
330                    }
331    
332                    sb.append(PREVIEW_TMP_PATH);
333                    sb.append(id);
334    
335                    if (index > 0) {
336                            sb.append(StringPool.DASH);
337                            sb.append(index - 1);
338                    }
339    
340                    sb.append(StringPool.PERIOD);
341                    sb.append(type);
342    
343                    return sb.toString();
344            }
345    
346            protected String getPreviewTempFilePath(String id, String type) {
347                    return getPreviewTempFilePath(id, 0, type);
348            }
349    
350            protected abstract String getPreviewType(FileVersion fileVersion);
351    
352            protected String getThumbnailFilePath(
353                    FileVersion fileVersion, String type, int index) {
354    
355                    StringBundler sb = new StringBundler(5);
356    
357                    sb.append(getPathSegment(fileVersion, false));
358    
359                    if (index != THUMBNAIL_INDEX_DEFAULT) {
360                            sb.append(StringPool.DASH);
361                            sb.append(index);
362                    }
363    
364                    sb.append(StringPool.PERIOD);
365                    sb.append(type);
366    
367                    return sb.toString();
368            }
369    
370            protected File getThumbnailTempFile(String id, String type) {
371                    String thumbnailTempFilePath = getThumbnailTempFilePath(id, type);
372    
373                    return new File(thumbnailTempFilePath);
374            }
375    
376            protected String getThumbnailTempFilePath(String id, String type) {
377                    StringBundler sb = new StringBundler(4);
378    
379                    sb.append(THUMBNAIL_TMP_PATH);
380                    sb.append(id);
381                    sb.append(StringPool.PERIOD);
382                    sb.append(type);
383    
384                    return sb.toString();
385            }
386    
387            protected abstract String getThumbnailType(FileVersion fileVersion);
388    
389            protected boolean hasThumbnail(
390                    FileVersion fileVersion, int thumbnailIndex) {
391    
392                    try {
393                            String imageType = getThumbnailType(fileVersion);
394    
395                            return DLStoreUtil.hasFile(
396                                    fileVersion.getCompanyId(), REPOSITORY_ID,
397                                    getThumbnailFilePath(fileVersion, imageType, thumbnailIndex));
398                    }
399                    catch (Exception e) {
400                            _log.error(e, e);
401                    }
402    
403                    return false;
404            }
405    
406            protected boolean isCustomThumbnailsEnabled(int thumbnailIndex)
407                    throws Exception {
408    
409                    if (thumbnailIndex == 1) {
410                            if ((PrefsPropsUtil.getInteger(
411                                            PropsKeys.
412                                                    DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_HEIGHT) > 0) ||
413                                    (PrefsPropsUtil.getInteger(
414                                            PropsKeys.
415                                                    DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_WIDTH) > 0)) {
416    
417                                    return true;
418                            }
419                    }
420                    else if (thumbnailIndex == 2) {
421                            if ((PrefsPropsUtil.getInteger(
422                                            PropsKeys.
423                                                    DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_HEIGHT) > 0) ||
424                                    (PrefsPropsUtil.getInteger(
425                                            PropsKeys.
426                                                    DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_WIDTH) > 0)) {
427    
428                                    return true;
429                            }
430                    }
431    
432                    return false;
433            }
434    
435            protected void storeThumbnailImages(FileVersion fileVersion, File file)
436                    throws Exception {
437    
438                    ImageBag imageBag = ImageToolUtil.read(file);
439    
440                    RenderedImage renderedImage = imageBag.getRenderedImage();
441    
442                    storeThumbnailImages(fileVersion, renderedImage);
443            }
444    
445            protected void storeThumbnailImages(
446                            FileVersion fileVersion, RenderedImage renderedImage)
447                    throws Exception {
448    
449                    storeThumbnailmage(fileVersion, renderedImage, THUMBNAIL_INDEX_DEFAULT);
450                    storeThumbnailmage(
451                            fileVersion, renderedImage, THUMBNAIL_INDEX_CUSTOM_1);
452                    storeThumbnailmage(
453                            fileVersion, renderedImage, THUMBNAIL_INDEX_CUSTOM_2);
454            }
455    
456            protected void storeThumbnailmage(
457                            FileVersion fileVersion, RenderedImage renderedImage,
458                            int thumbnailIndex)
459                    throws Exception {
460    
461                    if ((thumbnailIndex > 0) &&
462                            !isCustomThumbnailsEnabled(thumbnailIndex)) {
463    
464                            return;
465                    }
466    
467                    String type = getThumbnailType(fileVersion);
468    
469                    String maxHeightPropsKey = PropsKeys.DL_FILE_ENTRY_THUMBNAIL_MAX_HEIGHT;
470    
471                    if (thumbnailIndex == THUMBNAIL_INDEX_CUSTOM_1) {
472                            maxHeightPropsKey =
473                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_HEIGHT;
474                    }
475                    else if (thumbnailIndex == THUMBNAIL_INDEX_CUSTOM_2) {
476                            maxHeightPropsKey =
477                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_HEIGHT;
478                    }
479    
480                    String maxWidthPropsKey = PropsKeys.DL_FILE_ENTRY_THUMBNAIL_MAX_WIDTH;
481    
482                    if (thumbnailIndex == THUMBNAIL_INDEX_CUSTOM_1) {
483                            maxWidthPropsKey =
484                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_CUSTOM_1_MAX_WIDTH;
485                    }
486                    else if (thumbnailIndex == THUMBNAIL_INDEX_CUSTOM_2) {
487                            maxWidthPropsKey =
488                                    PropsKeys.DL_FILE_ENTRY_THUMBNAIL_CUSTOM_2_MAX_WIDTH;
489                    }
490    
491                    RenderedImage thumbnailRenderedImage = ImageToolUtil.scale(
492                            renderedImage, PrefsPropsUtil.getInteger(maxHeightPropsKey),
493                            PrefsPropsUtil.getInteger(maxWidthPropsKey));
494    
495                    byte[] bytes = ImageToolUtil.getBytes(
496                            thumbnailRenderedImage, MimeTypesUtil.getContentType("A." + type));
497    
498                    File file = FileUtil.createTempFile(bytes);
499    
500                    try {
501                            addFileToStore(
502                                    fileVersion.getCompanyId(), THUMBNAIL_PATH,
503                                    getThumbnailFilePath(fileVersion, type, thumbnailIndex), file);
504                    }
505                    finally {
506                            FileUtil.delete(file);
507                    }
508            }
509    
510            private static Log _log = LogFactoryUtil.getLog(
511                    DLPreviewableProcessor.class);
512    
513    }