/*
* (C) Copyright 2006-2016 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* Nuxeo - initial API and implementation
* Florent Bonnet <florent.bonnet@nuxeo.com>
* Estelle Giuly <egiuly@nuxeo.com>
*
* $Id: JOOoConvertPluginImpl.java 18651 2007-05-13 20:28:53Z sfermigier $
*/
package org.nuxeo.ecm.webapp.action;
import static org.nuxeo.ecm.platform.mimetype.interfaces.MimetypeRegistry.PDF_MIMETYPE;
import static org.nuxeo.ecm.platform.mimetype.interfaces.MimetypeRegistry.PDF_EXTENSION;
import java.io.IOException;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.remoting.WebRemote;
import org.jboss.seam.annotations.web.RequestParameter;
import org.nuxeo.ecm.core.api.Blob;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.IdRef;
import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
import org.nuxeo.ecm.core.api.blobholder.DocumentBlobHolder;
import org.nuxeo.ecm.core.blob.BlobManager;
import org.nuxeo.ecm.core.blob.BlobManager.UsageHint;
import org.nuxeo.ecm.core.convert.api.ConversionService;
import org.nuxeo.ecm.core.convert.api.ConverterCheckResult;
import org.nuxeo.ecm.core.convert.api.ConverterNotRegistered;
import org.nuxeo.ecm.platform.mimetype.interfaces.MimetypeRegistry;
import org.nuxeo.ecm.platform.ui.web.api.NavigationContext;
import org.nuxeo.ecm.platform.ui.web.cache.ThreadSafeCacheHolder;
import org.nuxeo.ecm.platform.ui.web.util.ComponentUtils;
import org.nuxeo.runtime.api.Framework;
@Name("conversionActions")
@Scope(ScopeType.EVENT)
public class ConversionActionBean implements ConversionAction {
private static final Log log = LogFactory.getLog(ConversionActionBean.class);
protected Map<String, ConverterCheckResult> pdfConverterForTypes;
@In(create = true, required = false)
CoreSession documentManager;
@In(create = true)
NavigationContext navigationContext;
@RequestParameter
private String docRef;
@RequestParameter
private String fileFieldFullName;
@RequestParameter
private String filename;
protected String pdfConverterName;
protected static final ThreadSafeCacheHolder<Boolean> exportableToPDFCache = new ThreadSafeCacheHolder<>(20);
public String display() {
return "view_file";
}
private DocumentModel getDocument() {
if (docRef == null) {
return navigationContext.getCurrentDocument();
} else {
return documentManager.getDocument(new IdRef(docRef));
}
}
private String getMimetypeFromDocument(String propertyName) {
Blob blob = (Blob) getDocument().getPropertyValue(propertyName);
return blob.getMimeType();
}
@Override
public void reCheckConverterAvailability() {
pdfConverterForTypes.clear();
}
public boolean isExportableToPDF(BlobHolder bh) {
if (bh == null) {
return false;
}
Blob blob = bh.getBlob();
return blob != null && isExportableToPDF(blob);
}
@Override
public boolean isExportableToPDF(Blob blob) {
if (blob == null) {
return false;
}
// check if there's a conversion available
if (getPDFConversionURL(blob) != null) {
return true;
}
String mimeType = blob.getMimeType();
return isMimeTypeExportableToPDF(mimeType);
}
protected String getPDFConversionURL(Blob blob) {
BlobManager blobManager = Framework.getService(BlobManager.class);
try {
URI uri = blobManager.getAvailableConversions(blob, UsageHint.DOWNLOAD).get(PDF_MIMETYPE);
if (uri != null) {
return uri.toString();
}
} catch (IOException e) {
log.error("Failed to retrieve available conversions", e);
}
return null;
}
protected boolean isMimeTypeExportableToPDF(String mimeType) {
// Don't bother searching for NO MIME type.
if (mimeType == null) {
return false;
}
// Initialize the converter check result map.
if (pdfConverterForTypes == null) {
pdfConverterForTypes = new HashMap<>();
}
// Check if there is any saved ConverterCheckResult for the desired
// MIME type.
if (pdfConverterForTypes.containsKey(mimeType)) {
return pdfConverterForTypes.get(mimeType).isAvailable();
}
try {
ConverterCheckResult pdfConverterAvailability;
ConversionService conversionService = Framework.getLocalService(ConversionService.class);
Iterator<String> converterNames = conversionService.getConverterNames(mimeType, PDF_MIMETYPE).iterator();
while (converterNames.hasNext()) {
pdfConverterName = converterNames.next();
pdfConverterAvailability = conversionService.isConverterAvailable(pdfConverterName, true);
// Save the converter availability for all the mime-types the
// converter
// supports.
for (String supMimeType : pdfConverterAvailability.getSupportedInputMimeTypes()) {
pdfConverterForTypes.put(supMimeType, pdfConverterAvailability);
}
if (pdfConverterAvailability.isAvailable()) {
return true;
}
}
} catch (ConverterNotRegistered e) {
log.error("Error while testing PDF converter availability", e);
}
return false;
}
@Override
@WebRemote
public boolean isFileExportableToPDF(String fieldName) {
DocumentModel doc = getDocument();
Boolean cacheResult = exportableToPDFCache.getFromCache(doc, fieldName);
boolean isSupported;
if (cacheResult == null) {
String mimetype = getMimetypeFromDocument(fieldName);
isSupported = isMimeTypeExportableToPDF(mimetype);
exportableToPDFCache.addToCache(doc, fieldName, isSupported);
} else {
isSupported = cacheResult;
}
return isSupported;
}
public String generatePdfFileFromBlobHolder(DocumentModel doc, BlobHolder bh) throws IOException {
// redirect to the conversion URL when available
Blob blob = bh.getBlob();
String url = getPDFConversionURL(blob);
if (url != null) {
try {
FacesContext.getCurrentInstance().getExternalContext().redirect(url);
return null;
} catch (IOException e) {
//
}
}
if (pdfConverterName == null) {
log.error("No PDF converter was found.");
return "pdf_generation_error";
}
Blob result = Framework.getService(ConversionService.class)
.convertToMimeType(MimetypeRegistry.PDF_MIMETYPE, bh, Collections.emptyMap())
.getBlob();
if (result == null) {
log.error("Transform service didn't return any resulting documents which is not normal.");
return "pdf_generation_error";
}
String xpath;
if (bh instanceof DocumentBlobHolder) {
xpath = ((DocumentBlobHolder) bh).getXpath();
} else {
xpath = null;
}
ComponentUtils.download(doc, xpath, result, result.getFilename(), "pdfConversion");
return null;
}
@Override
@WebRemote
public String generatePdfFile() throws IOException {
DocumentModel doc = getDocument();
BlobHolder bh = new DocumentBlobHolder(doc, fileFieldFullName);
return generatePdfFileFromBlobHolder(doc, bh);
}
/**
* @since 7.3
*/
public boolean isPDF(BlobHolder bh) {
if (bh == null) {
return false;
}
Blob blob = bh.getBlob();
return blob != null && isPDF(blob);
}
/**
* @since 7.3
*/
public boolean isPDF(Blob blob) {
if (blob == null) {
return false;
}
String mimeType = blob.getMimeType();
if (StringUtils.isNotBlank(mimeType) && PDF_MIMETYPE.equals(mimeType)) {
return true;
} else {
String filename = blob.getFilename();
if (StringUtils.isNotBlank(filename) && filename.endsWith(PDF_EXTENSION)) {
// assume it's a pdf file
return true;
}
}
return false;
}
public void initialize() {
// NOP
}
}