001/*
002 * (C) Copyright 2015-2018 Nuxeo (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     <a href="mailto:tdelprat@nuxeo.com">Tiry</a>
018 */
019package org.nuxeo.ecm.platform.rendition.extension;
020
021import java.util.ArrayList;
022import java.util.List;
023
024import org.apache.commons.io.FilenameUtils;
025import org.apache.commons.lang3.StringUtils;
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.MimetypeEntry;
035import org.nuxeo.ecm.platform.mimetype.interfaces.MimetypeRegistry;
036import org.nuxeo.ecm.platform.rendition.service.RenditionDefinition;
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    /**
048     * Generate the rendition Blobs for a given {@link RenditionDefinition}. Return is a List of Blob for bigger
049     * flexibility (typically HTML rendition with resources)
050     *
051     * @param doc the target {@link DocumentModel}
052     * @param definition the {@link RenditionDefinition} to use
053     * @param session the {@link CoreSession} to use
054     * @return The list of Blobs
055     */
056    public static List<Blob> render(DocumentModel doc, RenditionDefinition definition, CoreSession session) {
057
058        String chain = definition.getOperationChain();
059        if (chain == null) {
060            throw new NuxeoException("no operation defined");
061        }
062
063        if (session == null) {
064            session = doc.getCoreSession();
065        }
066        AutomationService as = Framework.getService(AutomationService.class);
067        try (OperationContext oc = new OperationContext(session)) {
068            oc.push(Constants.O_DOCUMENT, doc);
069
070            BlobHolder bh = doc.getAdapter(BlobHolder.class);
071            if (bh != null) {
072                try {
073                    Blob blob = bh.getBlob();
074                    if (blob != null) {
075                        oc.push(Constants.O_BLOB, blob);
076                    }
077                } catch (Exception e) {
078                    if (!definition.isEmptyBlobAllowed()) {
079                        throw new NuxeoException("No Blob available", e);
080                    }
081                }
082            } else {
083                if (!definition.isEmptyBlobAllowed()) {
084                    throw new NuxeoException("No Blob available");
085                }
086            }
087
088            List<Blob> blobs = new ArrayList<>();
089            Blob blob = (Blob) as.run(oc, definition.getOperationChain());
090            if (blob != null) {
091                if (StringUtils.isBlank(blob.getFilename())) {
092                    String filename = getFilenameWithExtension(doc.getTitle(), blob.getMimeType(), "bin");
093                    blob.setFilename(filename);
094                }
095                blobs.add(blob);
096            }
097            return blobs;
098
099        } catch (Exception e) {
100            throw new NuxeoException("Exception while running the operation chain: " + definition.getOperationChain(),
101                    e);
102        }
103    }
104
105    /**
106     * Generate a revised filename whose extension is either based on the supplied mimeType if applicable or the
107     * supplied default extension.
108     *
109     * @param filename the filename to use
110     * @param mimeType the mimeType from which the assigned extension is derived
111     * @param defaultExtension the default extension to be assigned if the mimeType has no corresponding extension
112     * @return the filename with the revised extension
113     * @since 7.4
114     */
115    public static String getFilenameWithExtension(String filename, String mimeType, String defaultExtension) {
116        String baseName = FilenameUtils.getBaseName(filename);
117        MimetypeRegistry mimetypeRegistry = Framework.getService(MimetypeRegistry.class);
118        MimetypeEntry mimeTypeEntry = mimetypeRegistry.getMimetypeEntryByMimeType(mimeType);
119        List<String> extensions = mimeTypeEntry.getExtensions();
120        String extension;
121        if (!extensions.isEmpty()) {
122            extension = extensions.get(0);
123        } else {
124            extension = defaultExtension;
125        }
126        return (extension == null) ? filename : baseName + "." + extension;
127    }
128
129}