001/* 002 * (C) Copyright 2002-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 * Nuxeo - initial API and implementation 016 * 017 */ 018 019package org.nuxeo.ecm.platform.convert.plugins; 020 021import java.io.Closeable; 022import java.io.IOException; 023import java.io.Serializable; 024import java.util.ArrayList; 025import java.util.HashMap; 026import java.util.List; 027import java.util.Map; 028 029import org.apache.commons.io.FilenameUtils; 030import org.apache.commons.io.IOUtils; 031import org.nuxeo.ecm.core.api.Blob; 032import org.nuxeo.ecm.core.api.CloseableFile; 033import org.nuxeo.ecm.core.api.blobholder.BlobHolder; 034import org.nuxeo.ecm.core.convert.api.ConversionException; 035import org.nuxeo.ecm.core.convert.api.ConverterCheckResult; 036import org.nuxeo.ecm.core.convert.extension.Converter; 037import org.nuxeo.ecm.core.convert.extension.ConverterDescriptor; 038import org.nuxeo.ecm.core.convert.extension.ExternalConverter; 039import org.nuxeo.ecm.platform.commandline.executor.api.CmdParameters; 040import org.nuxeo.ecm.platform.commandline.executor.api.CommandAvailability; 041import org.nuxeo.ecm.platform.commandline.executor.api.CommandException; 042import org.nuxeo.ecm.platform.commandline.executor.api.CommandLineExecutorService; 043import org.nuxeo.ecm.platform.commandline.executor.api.CommandNotAvailable; 044import org.nuxeo.ecm.platform.commandline.executor.api.ExecResult; 045import org.nuxeo.runtime.api.Framework; 046 047/** 048 * Base class to implement {@link Converter} based on {@link CommandLineExecutorService}. 049 * 050 * @author tiry 051 */ 052public abstract class CommandLineBasedConverter implements ExternalConverter { 053 054 protected static final String CMD_NAME_PARAMETER = "CommandLineName"; 055 056 protected static final String TMP_PATH_PARAMETER = "TmpDirectory"; 057 058 protected Map<String, String> initParameters; 059 060 /** 061 * @deprecated Since 7.4. Useless. 062 */ 063 @Deprecated 064 protected CommandLineExecutorService getCommandLineService() { 065 return Framework.getService(CommandLineExecutorService.class); 066 } 067 068 public String getTmpDirectory(Map<String, Serializable> parameters) { 069 String tmp = initParameters.get(TMP_PATH_PARAMETER); 070 if (parameters != null && parameters.containsKey(TMP_PATH_PARAMETER)) { 071 tmp = (String) parameters.get(TMP_PATH_PARAMETER); 072 } 073 if (tmp == null) { 074 tmp = System.getProperty("java.io.tmpdir"); 075 } 076 return tmp; 077 } 078 079 @Override 080 public BlobHolder convert(BlobHolder blobHolder, Map<String, Serializable> parameters) throws ConversionException { 081 String commandName = getCommandName(blobHolder, parameters); 082 if (commandName == null) { 083 throw new ConversionException("Unable to determine target CommandLine name"); 084 } 085 086 Map<String, Blob> blobParams = getCmdBlobParameters(blobHolder, parameters); 087 Map<String, String> strParams = getCmdStringParameters(blobHolder, parameters); 088 089 CmdReturn result = execOnBlob(commandName, blobParams, strParams); 090 return buildResult(result.output, result.params); 091 } 092 093 protected String getCommandName(BlobHolder blobHolder, Map<String, Serializable> parameters) { 094 String commandName = initParameters.get(CMD_NAME_PARAMETER); 095 if (parameters != null && parameters.containsKey(CMD_NAME_PARAMETER)) { 096 commandName = (String) parameters.get(CMD_NAME_PARAMETER); 097 } 098 return commandName; 099 } 100 101 /** 102 * Extracts BlobParameters. 103 */ 104 protected abstract Map<String, Blob> getCmdBlobParameters(BlobHolder blobHolder, 105 Map<String, Serializable> parameters) throws ConversionException; 106 107 /** 108 * Extracts String parameters. 109 */ 110 protected abstract Map<String, String> getCmdStringParameters(BlobHolder blobHolder, 111 Map<String, Serializable> parameters) throws ConversionException; 112 113 /** 114 * Builds result from commandLine output buffer. 115 */ 116 protected abstract BlobHolder buildResult(List<String> cmdOutput, CmdParameters cmdParams) 117 throws ConversionException; 118 119 protected class CmdReturn { 120 protected final CmdParameters params; 121 122 protected final List<String> output; 123 124 protected CmdReturn(CmdParameters params, List<String> output) { 125 this.params = params; 126 this.output = output; 127 } 128 } 129 130 protected CmdReturn execOnBlob(String commandName, Map<String, Blob> blobParameters, Map<String, String> parameters) 131 throws ConversionException { 132 CommandLineExecutorService cles = Framework.getService(CommandLineExecutorService.class); 133 CmdParameters params = cles.getDefaultCmdParameters(); 134 List<Closeable> toClose = new ArrayList<>(); 135 try { 136 if (blobParameters != null) { 137 for (String blobParamName : blobParameters.keySet()) { 138 Blob blob = blobParameters.get(blobParamName); 139 // closed in finally block 140 CloseableFile closeable = blob.getCloseableFile("." 141 + FilenameUtils.getExtension(blob.getFilename())); 142 params.addNamedParameter(blobParamName, closeable.getFile()); 143 toClose.add(closeable); 144 } 145 } 146 147 if (parameters != null) { 148 for (String paramName : parameters.keySet()) { 149 params.addNamedParameter(paramName, parameters.get(paramName)); 150 } 151 } 152 153 ExecResult result = Framework.getService(CommandLineExecutorService.class).execCommand(commandName, params); 154 if (!result.isSuccessful()) { 155 throw result.getError(); 156 } 157 return new CmdReturn(params, result.getOutput()); 158 } catch (CommandNotAvailable e) { 159 // XXX bubble installation instructions 160 throw new ConversionException("Unable to find targetCommand", e); 161 } catch (IOException | CommandException e) { 162 throw new ConversionException("Error while converting via CommandLineService", e); 163 } finally { 164 for (Closeable closeable : toClose) { 165 IOUtils.closeQuietly(closeable); 166 } 167 } 168 } 169 170 @Override 171 public void init(ConverterDescriptor descriptor) { 172 initParameters = descriptor.getParameters(); 173 if (initParameters == null) { 174 initParameters = new HashMap<>(); 175 } 176 } 177 178 @Override 179 public ConverterCheckResult isConverterAvailable() { 180 String commandName = getCommandName(null, null); 181 if (commandName == null) { 182 // can not check 183 return new ConverterCheckResult(); 184 } 185 186 CommandAvailability ca = Framework.getService(CommandLineExecutorService.class).getCommandAvailability( 187 commandName); 188 189 if (ca.isAvailable()) { 190 return new ConverterCheckResult(); 191 } else { 192 return new ConverterCheckResult(ca.getInstallMessage(), ca.getErrorMessage()); 193 } 194 } 195 196}