All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.mklinger.qetcher.liferay.client.impl.PDFProcessorImpl Maven / Gradle / Ivy

/*
 * Copyright 2013-present mklinger GmbH - http://www.mklinger.de
 *
 * All rights reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of mklinger GmbH and its suppliers, if any.
 * The intellectual and technical concepts contained herein are
 * proprietary to mklinger GmbH and its suppliers and are protected
 * by trade secret or copyright law. Dissemination of this
 * information or reproduction of this material is strictly forbidden
 * unless prior written permission is obtained from mklinger GmbH.
 */
package de.mklinger.qetcher.liferay.client.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.lar.PortletDataContext;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.messaging.DestinationNames;
import com.liferay.portal.kernel.repository.model.FileEntry;
import com.liferay.portal.kernel.repository.model.FileVersion;
import com.liferay.portal.kernel.util.ContentTypes;
import com.liferay.portal.kernel.util.FileUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.MimeTypesUtil;
import com.liferay.portal.kernel.util.StreamUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.xml.Element;
import com.liferay.portal.repository.liferayrepository.model.LiferayFileVersion;
import com.liferay.portal.util.PropsValues;
import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
import com.liferay.portlet.documentlibrary.util.DLPreviewableProcessor;
import com.liferay.portlet.documentlibrary.util.DLUtil;
import com.liferay.portlet.documentlibrary.util.DocumentConversionUtil;
import com.liferay.portlet.documentlibrary.util.PDFProcessor;

import de.mklinger.qetcher.liferay.abstraction.LiferayException;
import de.mklinger.qetcher.liferay.client.impl.abstraction.LiferayAbstractionFactorySupplier;


/**
 * @author Marc Klinger - mklinger[at]mklinger[dot]de
 */
public class PDFProcessorImpl extends DLPreviewableProcessor implements PDFProcessor {
	private static final Logger LOG = LoggerFactory.getLogger(PDFProcessorImpl.class);

	@Override
	public void afterPropertiesSet() throws Exception {
		FileUtil.mkdirs(PREVIEW_TMP_PATH);
		FileUtil.mkdirs(THUMBNAIL_TMP_PATH);
	}

	@Override
	public void generateImages(final FileVersion sourceFileVersion, final FileVersion destinationFileVersion) throws Exception {
		_generateImages(sourceFileVersion, destinationFileVersion);
	}

	@Override
	public InputStream getPreviewAsStream(final FileVersion fileVersion, final int index) throws Exception {
		return doGetPreviewAsStream(fileVersion, index, PREVIEW_TYPE);
	}

	@Override
	public int getPreviewFileCount(final FileVersion fileVersion) {
		try {
			return doGetPreviewFileCount(fileVersion);
		} catch (final Exception e) {
			_log.error(e, e);
		}
		return 0;
	}

	@Override
	public long getPreviewFileSize(final FileVersion fileVersion, final int index) throws Exception {
		return doGetPreviewFileSize(fileVersion, index);
	}

	@Override
	public InputStream getThumbnailAsStream(final FileVersion fileVersion, final int index) throws Exception {
		return doGetThumbnailAsStream(fileVersion, index);
	}

	@Override
	public long getThumbnailFileSize(final FileVersion fileVersion, final int index) throws Exception {
		return doGetThumbnailFileSize(fileVersion, index);
	}

	@Override
	public boolean hasImages(final FileVersion fileVersion) {
		boolean hasImages = false;

		try {
			hasImages = _hasImages(fileVersion);
			if (!hasImages && isSupported(fileVersion)) {
				_queueGeneration(null, fileVersion);
			}
		} catch (final Exception e) {
			_log.error(e, e);
		}

		return hasImages;
	}

	@Override
	public boolean isDocumentSupported(final FileVersion fileVersion) {
		return isSupported(fileVersion);
	}

	@Override
	public boolean isDocumentSupported(final String mimeType) {
		return isSupported(mimeType);
	}

	@Override
	public boolean isSupported(final String mimeType) {
		if (Validator.isNull(mimeType)) {
			return false;
		}

		if (mimeType.equals(ContentTypes.APPLICATION_PDF) || mimeType.equals(ContentTypes.APPLICATION_X_PDF)) {
			return true;
		}

		if (DocumentConversionUtil.isEnabled()) {
			final Set extensions = MimeTypesUtil.getExtensions(mimeType);
			for (String extension : extensions) {
				extension = extension.substring(1);
				final String[] targetExtensions = DocumentConversionUtil.getConversions(extension);
				for (final String targetExtension : targetExtensions) {
					if ("pdf".equals(targetExtension)) {
						return true;
					}
				}
			}
		}

		return false;
	}

	@Override
	public void trigger(final FileVersion sourceFileVersion, final FileVersion destinationFileVersion) {
		super.trigger(sourceFileVersion, destinationFileVersion);
		_queueGeneration(sourceFileVersion, destinationFileVersion);
	}

	@Override
	protected void copyPreviews(
			final FileVersion sourceFileVersion, final FileVersion destinationFileVersion) {

		if (!PropsValues.DL_FILE_ENTRY_PREVIEW_ENABLED) {
			return;
		}

		try {
			if (hasPreview(sourceFileVersion) &&
					!hasPreview(destinationFileVersion)) {

				final int count = getPreviewFileCount(sourceFileVersion);

				for (int i = 0; i < count; i++) {
					final String previewFilePath = getPreviewFilePath(
							destinationFileVersion, i + 1);

					final InputStream is = doGetPreviewAsStream(
							sourceFileVersion, i + 1, PREVIEW_TYPE);

					addFileToStore(
							destinationFileVersion.getCompanyId(), PREVIEW_PATH,
							previewFilePath, is);
				}
			}
		}
		catch (final Exception e) {
			_log.error(e, e);
		}
	}

	@Override
	protected void doExportGeneratedFiles(final PortletDataContext portletDataContext, final FileEntry fileEntry, final Element fileEntryElement) throws Exception {
		exportThumbnails(portletDataContext, fileEntry, fileEntryElement, "pdf");
		exportPreviews(portletDataContext, fileEntry, fileEntryElement);
	}

	@Override
	protected void doImportGeneratedFiles(final PortletDataContext portletDataContext, final FileEntry fileEntry, final FileEntry importedFileEntry, final Element fileEntryElement) throws Exception {
		importThumbnails(
				portletDataContext, fileEntry, importedFileEntry, fileEntryElement,
				"pdf");

		importPreviews(
				portletDataContext, fileEntry, importedFileEntry, fileEntryElement);
	}

	protected void exportPreviews(final PortletDataContext portletDataContext, final FileEntry fileEntry, final Element fileEntryElement) throws Exception {
		final FileVersion fileVersion = fileEntry.getFileVersion();
		if (!isSupported(fileVersion) || !_hasImages(fileVersion)) {
			return;
		}

		if (!portletDataContext.isPerformDirectBinaryImport()) {
			final int previewFileCount = getPreviewFileCount(fileVersion);
			fileEntryElement.addAttribute("bin-path-pdf-preview-count", String.valueOf(previewFileCount));
			for (int i = 0; i < previewFileCount; i++) {
				exportPreview(
						portletDataContext, fileEntry, fileEntryElement, "pdf",
						PREVIEW_TYPE, i);
			}
		}
	}

	@Override
	protected List getFileVersionIds() {
		return _fileVersionIds;
	}

	@Override
	protected String getPreviewType(final FileVersion fileVersion) {
		return PREVIEW_TYPE;
	}

	@Override
	protected String getThumbnailType(final FileVersion fileVersion) {
		return THUMBNAIL_TYPE;
	}

	protected boolean hasPreview(final FileVersion fileVersion) throws Exception {
		return hasPreview(fileVersion, null);
	}

	@Override
	protected boolean hasPreview(final FileVersion fileVersion, final String type)
			throws Exception {

		final String previewFilePath = getPreviewFilePath(fileVersion, 1);

		return DLStoreUtil.hasFile(
				fileVersion.getCompanyId(), REPOSITORY_ID, previewFilePath);
	}

	protected void importPreviews(
			final PortletDataContext portletDataContext, final FileEntry fileEntry,
			final FileEntry importedFileEntry, final Element fileEntryElement)
					throws Exception {

		final int previewFileCount = GetterUtil.getInteger(
				fileEntryElement.attributeValue("bin-path-pdf-preview-count"));

		for (int i = 0; i < previewFileCount; i++) {
			importPreview(
					portletDataContext, fileEntry, importedFileEntry,
					fileEntryElement, "pdf", PREVIEW_TYPE, i);
		}
	}

	private void _generateImages(final FileVersion sourceFileVersion, final FileVersion destinationFileVersion) throws Exception {
		InputStream inputStream = null;

		try {
			if (sourceFileVersion != null) {
				copy(sourceFileVersion, destinationFileVersion);
				return;
			}

			if (_hasImages(destinationFileVersion)) {
				return;
			}

			final String extension = destinationFileVersion.getExtension();

			if (extension.equals("pdf")) {
				if (destinationFileVersion instanceof LiferayFileVersion) {
					try {
						final LiferayFileVersion liferayFileVersion = (LiferayFileVersion)destinationFileVersion;
						final File file = liferayFileVersion.getFile(false);
						_generateImages(destinationFileVersion, file);
						return;
					}
					catch (final UnsupportedOperationException uoe) {
					}
				}

				inputStream = destinationFileVersion.getContentStream(false);

				_generateImages(destinationFileVersion, inputStream);
			}
			else if (DocumentConversionUtil.isEnabled()) {
				inputStream = destinationFileVersion.getContentStream(false);

				final String tempFileId = DLUtil.getTempFileId(destinationFileVersion.getFileEntryId(), destinationFileVersion.getVersion());

				final File file = DocumentConversionUtil.convert(tempFileId, inputStream, extension, "pdf");

				// Qetcher: store pdf as preview
				if (LiferayClientConfiguration.getInstance().isStorePdfAsPreview()) {
					LOG.info("Adding preview PDF to store");
					addFileToStore(
							destinationFileVersion.getCompanyId(), PREVIEW_PATH,
							getPreviewFilePath(destinationFileVersion, "pdf"), file);
				}
				// Qetcher: store pdf as preview - end

				_generateImages(destinationFileVersion, file);
			}
		}
		catch (final NoSuchFileEntryException nsfee) {
		}
		finally {
			StreamUtil.cleanUp(inputStream);

			_fileVersionIds.remove(destinationFileVersion.getFileVersionId());
		}
	}

	@Override
	protected void addFileToStore(final long companyId, final String dirName, final String filePath, final File srcFile) throws PortalException, SystemException {
		// delete file in case the path already exists
		try {
			DLStoreUtil.deleteFile(companyId, REPOSITORY_ID, filePath);
		} catch (final PortalException e) {
			// ignore.
		}
		super.addFileToStore(companyId, dirName, filePath, srcFile);
	}

	@Override
	protected void addFileToStore(final long companyId, final String dirName, final String filePath, final InputStream is) throws PortalException, SystemException {
		// delete file in case the path already exists
		try {
			DLStoreUtil.deleteFile(companyId, REPOSITORY_ID, filePath);
		} catch (final PortalException e) {
			// ignore.
		}
		super.addFileToStore(companyId, dirName, filePath, is);
	}

	private void _generateImages(final FileVersion fileVersion, final File file) throws Exception {
		_generateImages(fileVersion, new FileInputStream(file));
	}

	private void _generateImages(final FileVersion fileVersion, final InputStream inputStream) throws Exception {
		final boolean storePreview = _isGeneratePreview(fileVersion);
		final boolean storeThumbnail = _isGenerateThumbnail(fileVersion);
		final Map targetParameters = new HashMap<>();
		// ignoring dl.file.entry.preview.document.depth / PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_DEPTH
		targetParameters.put("resolution", String.valueOf(PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_DPI));
		if (PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_HEIGHT != 0) {
			targetParameters.put("width", String.valueOf(PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_WIDTH));
			targetParameters.put("height", String.valueOf(PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_HEIGHT));
		} else {
			targetParameters.put("width", String.valueOf(PropsValues.DL_FILE_ENTRY_PREVIEW_DOCUMENT_MAX_WIDTH));
		}
		if (storeThumbnail && !storePreview) {
			targetParameters.put("pages", "1");
		}
		final de.mklinger.qetcher.liferay.abstraction.FileVersion wrappedLiferayFileVersion = LiferayAbstractionFactorySupplier.getInstance().getDLTool().wrapLiferayFileVersion(fileVersion);
		final PreviewOutputStreamProvider outputStreamProvider = new PreviewOutputStreamProvider(
				wrappedLiferayFileVersion, storeThumbnail, storePreview, new PreviewProcessorBridgeImpl());
		QetcherLiferayServiceUtil.convert(inputStream, outputStreamProvider, "pdf", PREVIEW_TYPE, targetParameters, getReferer(fileVersion));
	}

	private String getReferer(final FileVersion fileVersion) {
		return "companyId=" + fileVersion.getCompanyId() + ",fileEntryId=" + fileVersion.getFileEntryId();
	}

	private class PreviewProcessorBridgeImpl implements PreviewProcessorBridge {
		@Override
		public File getPreviewTempFile(final String id, final int index) {
			return PDFProcessorImpl.this.getPreviewTempFile(id, index);
		}

		@Override
		public void storeThumbnailImages(final de.mklinger.qetcher.liferay.abstraction.FileVersion fileVersion, final File file) throws Exception {
			PDFProcessorImpl.this.storeThumbnailImages((FileVersion)fileVersion.unwrap(), file);
		}

		@Override
		public String getPreviewFilePath(final de.mklinger.qetcher.liferay.abstraction.FileVersion fileVersion, final int index) {
			return PDFProcessorImpl.this.getPreviewFilePath((FileVersion)fileVersion.unwrap(), index);
		}

		@Override
		public void addFileToStore(final long companyId, final String dirName, final String filePath, final File srcFile) throws LiferayException {
			try {
				PDFProcessorImpl.this.addFileToStore(companyId, dirName, filePath, srcFile);
			} catch (PortalException | SystemException e) {
				throw new LiferayException(e);
			}
		}
	}

	private boolean _hasImages(final FileVersion fileVersion) throws Exception {
		return !_isGeneratePreview(fileVersion) && hasThumbnails(fileVersion);
	}

	private boolean _isGeneratePreview(final FileVersion fileVersion) throws Exception {
		if (PropsValues.DL_FILE_ENTRY_PREVIEW_ENABLED) {
			if (!DLStoreUtil.hasFile(
					fileVersion.getCompanyId(), REPOSITORY_ID,
					getPreviewFilePath(fileVersion, 1))) {
				return true;
			}
			if (LiferayClientConfiguration.getInstance().isStorePdfAsPreview() &&
					!"pdf".equals(fileVersion.getExtension()) &&
					!DLStoreUtil.hasFile(
							fileVersion.getCompanyId(), REPOSITORY_ID,
							getPreviewFilePath(fileVersion, "pdf"))) {
				return true;
			}
		}
		return false;
	}

	private boolean _isGenerateThumbnail(final FileVersion fileVersion) throws Exception {
		final String thumbnailFilePath = getThumbnailFilePath(fileVersion, THUMBNAIL_INDEX_DEFAULT);
		return PropsValues.DL_FILE_ENTRY_THUMBNAIL_ENABLED &&
				!DLStoreUtil.hasFile(fileVersion.getCompanyId(), REPOSITORY_ID, thumbnailFilePath);
	}

	private void _queueGeneration(final FileVersion sourceFileVersion, final FileVersion destinationFileVersion) {
		if (_fileVersionIds.contains(destinationFileVersion.getFileVersionId())) {
			return;
		}

		boolean generateImages = false;

		final String extension = destinationFileVersion.getExtension();

		if (extension.equals("pdf")) {
			generateImages = true;
		} else if (DocumentConversionUtil.isEnabled()) {
			final String[] conversions = DocumentConversionUtil.getConversions(extension);
			for (final String conversion : conversions) {
				if ("pdf".equals(conversion)) {
					generateImages = true;
					break;
				}
			}
		}

		if (generateImages) {
			_fileVersionIds.add(destinationFileVersion.getFileVersionId());

			sendGenerationMessage(
					DestinationNames.DOCUMENT_LIBRARY_PDF_PROCESSOR,
					sourceFileVersion, destinationFileVersion);
		}
	}

	private static Log _log = LogFactoryUtil.getLog(PDFProcessorImpl.class);

	private final List _fileVersionIds = new Vector<>();
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy