001/*
002 * (C) Copyright 2014-2016 Nuxeo SA (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 *     Thomas Roger
018 */
019
020package org.nuxeo.ecm.platform.convert.plugins;
021
022import java.io.File;
023import java.io.IOException;
024import java.io.Serializable;
025import java.nio.file.Files;
026import java.nio.file.Path;
027import java.nio.file.Paths;
028import java.util.ArrayList;
029import java.util.Arrays;
030import java.util.HashMap;
031import java.util.List;
032import java.util.Map;
033
034import org.nuxeo.ecm.core.api.Blob;
035import org.nuxeo.ecm.core.api.Blobs;
036import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
037import org.nuxeo.ecm.core.convert.api.ConversionException;
038import org.nuxeo.ecm.core.convert.cache.SimpleCachableBlobHolder;
039import org.nuxeo.ecm.platform.commandline.executor.api.CmdParameters;
040import org.nuxeo.runtime.api.Framework;
041
042/**
043 * Generic converter executing a contributed command line.
044 * <p>
045 * The command line to call is stored in the {@code CommandLineName} parameter.
046 * <p>
047 * The target file name is in the {@code targetFileName} parameter. If it's null, a temporary one will be created.
048 * <p>
049 * All the converter parameters are passed to the command line.
050 * <p>
051 * A sample contribution using this converter:
052 *
053 * <pre>
054 *     <converter name="pdf2image" class="org.nuxeo.ecm.platform.convert.plugins.CommandLineConverter">
055 *       <sourceMimeType>application/pdf</sourceMimeType>
056 *       <destinationMimeType>image/jpeg</destinationMimeType>
057 *       <destinationMimeType>image/png</destinationMimeType>
058 *       <destinationMimeType>image/gif</destinationMimeType>
059 *       <parameters>
060 *         <parameter name="CommandLineName">pdftoimage</parameter>
061 *       </parameters>
062 *     </converter>
063 * </pre>
064 *
065 * @since 7.1
066 */
067public class CommandLineConverter extends CommandLineBasedConverter {
068
069    public static final String SOURCE_FILE_PATH_KEY = "sourceFilePath";
070
071    public static final String OUT_DIR_PATH_KEY = "outDirPath";
072
073    public static final String TARGET_FILE_NAME_KEY = "targetFileName";
074
075    public static final String TARGET_FILE_PATH_KEY = "targetFilePath";
076
077    public static final List<String> RESERVED_PARAMETERS = Arrays.asList(SOURCE_FILE_PATH_KEY, OUT_DIR_PATH_KEY,
078            TARGET_FILE_PATH_KEY, CMD_NAME_PARAMETER);
079
080    @Override
081    protected Map<String, Blob> getCmdBlobParameters(BlobHolder blobHolder, Map<String, Serializable> parameters)
082            throws ConversionException {
083        Map<String, Blob> cmdBlobParams = new HashMap<>();
084        cmdBlobParams.put(SOURCE_FILE_PATH_KEY, blobHolder.getBlob());
085        return cmdBlobParams;
086    }
087
088    @Override
089    protected Map<String, String> getCmdStringParameters(BlobHolder blobHolder, Map<String, Serializable> parameters)
090            throws ConversionException {
091        String tmpDir = getTmpDirectory(parameters);
092        Path tmpDirPath = tmpDir != null ? Paths.get(tmpDir) : null;
093        try {
094            Path outDirPath = tmpDirPath != null ? Files.createTempDirectory(tmpDirPath, null)
095                    : Framework.createTempDirectory(null);
096
097            Map<String, String> cmdStringParams = new HashMap<>();
098            cmdStringParams.put(OUT_DIR_PATH_KEY, outDirPath.toString());
099
100            String targetFileName = (String) parameters.get(TARGET_FILE_NAME_KEY);
101            Path targetFilePath;
102            if (targetFileName == null) {
103                targetFilePath = Files.createTempFile(outDirPath, null, null);
104            } else {
105                targetFilePath = Paths.get(outDirPath.toString(), targetFileName);
106            }
107            cmdStringParams.put(TARGET_FILE_PATH_KEY, targetFilePath.toString());
108            if (targetFileName == null) {
109                // do not keep a temporary file, just created to get a path
110                Files.delete(targetFilePath);
111            }
112
113            // pass all converter parameters to the command line
114            for (Map.Entry<String, Serializable> entry : parameters.entrySet()) {
115                if (!RESERVED_PARAMETERS.contains(entry.getKey())) {
116                    cmdStringParams.put(entry.getKey(), (String) entry.getValue());
117                }
118            }
119            // pass all the converter descriptor parameters to the commandline
120            for (Map.Entry<String, String> entry : initParameters.entrySet()) {
121                if (!RESERVED_PARAMETERS.contains(entry.getKey())) {
122                    cmdStringParams.put(entry.getKey(), entry.getValue());
123                }
124            }
125
126            return cmdStringParams;
127        } catch (IOException e) {
128            throw new ConversionException(e.getMessage(), e);
129        }
130    }
131
132    @Override
133    protected BlobHolder buildResult(List<String> cmdOutput, CmdParameters cmdParams) throws ConversionException {
134        String outputPath = cmdParams.getParameter(OUT_DIR_PATH_KEY);
135        List<Blob> blobs = new ArrayList<>();
136        File outputDir = new File(outputPath);
137        if (outputDir.exists() && outputDir.isDirectory()) {
138            File[] files = outputDir.listFiles();
139            if (files != null) {
140                for (File file : files) {
141                    try {
142                        Blob blob = Blobs.createBlob(file);
143                        blob.setFilename(file.getName());
144                        blobs.add(blob);
145                    } catch (IOException e) {
146                        throw new ConversionException("Cannot create blob", e);
147                    }
148                }
149            }
150        }
151        return new SimpleCachableBlobHolder(blobs);
152    }
153
154}