001/* 002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl-2.1.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * <a href="mailto:tdelprat@nuxeo.com">Tiry</a> 016 */ 017package org.nuxeo.ecm.platform.rendition.extension; 018 019import java.util.ArrayList; 020import java.util.List; 021 022import org.apache.commons.io.FilenameUtils; 023import org.apache.commons.lang.StringUtils; 024import org.apache.commons.logging.Log; 025import org.apache.commons.logging.LogFactory; 026import org.nuxeo.ecm.automation.AutomationService; 027import org.nuxeo.ecm.automation.OperationContext; 028import org.nuxeo.ecm.automation.core.Constants; 029import org.nuxeo.ecm.core.api.Blob; 030import org.nuxeo.ecm.core.api.CoreSession; 031import org.nuxeo.ecm.core.api.DocumentModel; 032import org.nuxeo.ecm.core.api.NuxeoException; 033import org.nuxeo.ecm.core.api.blobholder.BlobHolder; 034import org.nuxeo.ecm.platform.mimetype.interfaces.MimetypeRegistry; 035import org.nuxeo.ecm.platform.rendition.service.RenditionDefinition; 036import org.nuxeo.ecm.platform.mimetype.interfaces.MimetypeEntry; 037import org.nuxeo.runtime.api.Framework; 038 039/** 040 * Class introduced to share code between sync and lazy automation based renditions 041 * 042 * @author <a href="mailto:tdelprat@nuxeo.com">Tiry</a> 043 * @since 7.2 044 */ 045public class AutomationRenderer { 046 047 protected static final Log log = LogFactory.getLog(AutomationRenderer.class); 048 049 /** 050 * Test if the Rendition is available on the given DocumentModel 051 * 052 * @param doc the target {@link DocumentModel} 053 * @param def the {@link RenditionDefinition} to use 054 * @return The test result 055 */ 056 public static boolean isRenditionAvailable(DocumentModel doc, RenditionDefinition def) { 057 String chain = def.getOperationChain(); 058 if (chain == null) { 059 log.error("Can not run Automation rendition if chain is not defined"); 060 return false; 061 } 062 AutomationService as = Framework.getLocalService(AutomationService.class); 063 064 try { 065 if (as.getOperation(chain) == null) { 066 log.error("Chain " + chain + " is not defined : rendition can not be used"); 067 return false; 068 } 069 } catch (Exception e) { 070 log.error("Unable to test Rendition availability", e); 071 return false; 072 } 073 074 if (!def.isEmptyBlobAllowed()) { 075 BlobHolder bh = doc.getAdapter(BlobHolder.class); 076 if (bh == null) { 077 return false; 078 } 079 try { 080 Blob blob = bh.getBlob(); 081 if (blob == null) { 082 return false; 083 } 084 } catch (Exception e) { 085 log.error("Unable to get Blob to test Rendition availability", e); 086 return false; 087 } 088 } 089 return true; 090 } 091 092 /** 093 * Generate the rendition Blobs for a given {@link RenditionDefinition}. Return is a List of Blob for bigger 094 * flexibility (typically HTML rendition with resources) 095 * 096 * @param doc the target {@link DocumentModel} 097 * @param definition the {@link RenditionDefinition} to use 098 * @param session the {@link CoreSession} to use 099 * @return The list of Blobs 100 */ 101 public static List<Blob> render(DocumentModel doc, RenditionDefinition definition, CoreSession session) { 102 103 String chain = definition.getOperationChain(); 104 if (chain == null) { 105 throw new NuxeoException("no operation defined"); 106 } 107 108 if (session == null) { 109 session = doc.getCoreSession(); 110 } 111 AutomationService as = Framework.getLocalService(AutomationService.class); 112 OperationContext oc = new OperationContext(session); 113 oc.push(Constants.O_DOCUMENT, doc); 114 115 try { 116 BlobHolder bh = doc.getAdapter(BlobHolder.class); 117 if (bh != null) { 118 try { 119 Blob blob = bh.getBlob(); 120 if (blob != null) { 121 oc.push(Constants.O_BLOB, blob); 122 } 123 } catch (Exception e) { 124 if (!definition.isEmptyBlobAllowed()) { 125 throw new NuxeoException("No Blob available", e); 126 } 127 } 128 } else { 129 if (!definition.isEmptyBlobAllowed()) { 130 throw new NuxeoException("No Blob available"); 131 } 132 } 133 134 Blob blob = (Blob) as.run(oc, definition.getOperationChain()); 135 if (blob != null && StringUtils.isBlank(blob.getFilename())) { 136 String filename = getFilenameWithExtension(doc.getTitle(), blob.getMimeType(), "bin"); 137 blob.setFilename(filename); 138 } 139 List<Blob> blobs = new ArrayList<Blob>(); 140 blobs.add(blob); 141 return blobs; 142 143 } catch (Exception e) { 144 throw new NuxeoException("Exception while running the operation chain: " 145 + definition.getOperationChain(), e); 146 } 147 } 148 149 /** 150 * Generate a revised filename whose extension is either based on the supplied mimeType if applicable or the 151 * supplied default extension. 152 * 153 * @param filename the filename to use 154 * @param mimeType the mimeType from which the assigned extension is derived 155 * @param defaultExtension the default extension to be assigned if the mimeType has no corresponding extension 156 * @return the filename with the revised extension 157 * @since 7.4 158 */ 159 public static String getFilenameWithExtension(String filename, String mimeType, String defaultExtension) { 160 String baseName = FilenameUtils.getBaseName(filename); 161 MimetypeRegistry mimetypeRegistry = Framework.getLocalService(MimetypeRegistry.class); 162 MimetypeEntry mimeTypeEntry = mimetypeRegistry.getMimetypeEntryByMimeType(mimeType); 163 List<String> extensions = mimeTypeEntry.getExtensions(); 164 String extension; 165 if (!extensions.isEmpty()) { 166 extension = extensions.get(0); 167 } else { 168 extension = defaultExtension; 169 } 170 return (extension == null) ? filename : baseName + "." + extension; 171 } 172 173}