mirror of
https://github.com/Alfresco/alfresco-transform-core.git
synced 2025-08-14 17:58:27 +00:00
Save point: [skip ci]
* Extract TransformHandler from TransformController
This commit is contained in:
@@ -27,19 +27,16 @@
|
|||||||
package org.alfresco.transform.coreaio;
|
package org.alfresco.transform.coreaio;
|
||||||
|
|
||||||
import org.alfresco.transform.base.TransformEngine;
|
import org.alfresco.transform.base.TransformEngine;
|
||||||
import org.alfresco.transform.base.TransformRegistryImpl;
|
|
||||||
import org.alfresco.transform.base.probes.ProbeTestTransform;
|
import org.alfresco.transform.base.probes.ProbeTestTransform;
|
||||||
import org.alfresco.transform.config.TransformConfig;
|
import org.alfresco.transform.config.TransformConfig;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.alfresco.transform.base.logging.StandardMessages.COMMUNITY_LICENCE;
|
import static org.alfresco.transform.base.logging.StandardMessages.COMMUNITY_LICENCE;
|
||||||
import static org.alfresco.transform.common.Mimetype.MIMETYPE_HTML;
|
|
||||||
import static org.alfresco.transform.common.Mimetype.MIMETYPE_PDF;
|
import static org.alfresco.transform.common.Mimetype.MIMETYPE_PDF;
|
||||||
import static org.alfresco.transform.common.Mimetype.MIMETYPE_TEXT_PLAIN;
|
import static org.alfresco.transform.common.Mimetype.MIMETYPE_TEXT_PLAIN;
|
||||||
|
|
||||||
|
@@ -26,20 +26,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.transform.base;
|
package org.alfresco.transform.base;
|
||||||
|
|
||||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
import org.alfresco.transform.base.messaging.TransformMessageConverter;
|
||||||
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
|
import org.alfresco.transform.base.messaging.TransformReplySender;
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.Message;
|
|
||||||
|
|
||||||
import org.alfresco.transform.client.model.TransformReply;
|
import org.alfresco.transform.client.model.TransformReply;
|
||||||
import org.alfresco.transform.client.model.TransformRequest;
|
import org.alfresco.transform.client.model.TransformRequest;
|
||||||
import org.alfresco.transform.common.TransformException;
|
import org.alfresco.transform.common.TransformException;
|
||||||
import org.alfresco.transform.base.messaging.TransformMessageConverter;
|
|
||||||
import org.alfresco.transform.base.messaging.TransformReplySender;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -49,6 +40,14 @@ import org.springframework.jms.annotation.JmsListener;
|
|||||||
import org.springframework.jms.support.converter.MessageConversionException;
|
import org.springframework.jms.support.converter.MessageConversionException;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.jms.Destination;
|
||||||
|
import javax.jms.JMSException;
|
||||||
|
import javax.jms.Message;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||||
|
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queue Transformer service.
|
* Queue Transformer service.
|
||||||
* This service reads all the requests for the particular engine, forwards them to the worker
|
* This service reads all the requests for the particular engine, forwards them to the worker
|
||||||
@@ -64,14 +63,10 @@ public class QueueTransformService
|
|||||||
{
|
{
|
||||||
private static final Logger logger = LoggerFactory.getLogger(QueueTransformService.class);
|
private static final Logger logger = LoggerFactory.getLogger(QueueTransformService.class);
|
||||||
|
|
||||||
// TODO: I know this is not smart but all the the transformation logic is in the Controller.
|
|
||||||
// The controller also manages the probes. There's tons of refactoring needed there, hence this. Sorry.
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TransformController transformController;
|
private TransformHandler transformHandler;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TransformMessageConverter transformMessageConverter;
|
private TransformMessageConverter transformMessageConverter;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TransformReplySender transformReplySender;
|
private TransformReplySender transformReplySender;
|
||||||
|
|
||||||
@@ -129,9 +124,7 @@ public class QueueTransformService
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransformReply reply = transformController.transform(transformRequest.get(), null)
|
TransformReply reply = transformHandler.handleMessageRequest(transformRequest.get(), null).getBody();
|
||||||
.getBody();
|
|
||||||
|
|
||||||
transformReplySender.send(replyToDestinationQueue, reply);
|
transformReplySender.send(replyToDestinationQueue, reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,19 +26,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.transform.base;
|
package org.alfresco.transform.base;
|
||||||
|
|
||||||
import org.alfresco.transform.base.clients.AlfrescoSharedFileStoreClient;
|
|
||||||
import org.alfresco.transform.base.fs.FileManager;
|
|
||||||
import org.alfresco.transform.base.logging.LogEntry;
|
import org.alfresco.transform.base.logging.LogEntry;
|
||||||
import org.alfresco.transform.base.model.FileRefResponse;
|
|
||||||
import org.alfresco.transform.base.probes.ProbeTestTransform;
|
import org.alfresco.transform.base.probes.ProbeTestTransform;
|
||||||
import org.alfresco.transform.base.util.OutputStreamLengthRecorder;
|
|
||||||
import org.alfresco.transform.client.model.InternalContext;
|
|
||||||
import org.alfresco.transform.client.model.TransformReply;
|
import org.alfresco.transform.client.model.TransformReply;
|
||||||
import org.alfresco.transform.client.model.TransformRequest;
|
import org.alfresco.transform.client.model.TransformRequest;
|
||||||
import org.alfresco.transform.common.TransformException;
|
import org.alfresco.transform.common.TransformException;
|
||||||
import org.alfresco.transform.common.TransformerDebug;
|
|
||||||
import org.alfresco.transform.config.TransformConfig;
|
import org.alfresco.transform.config.TransformConfig;
|
||||||
import org.alfresco.transform.messages.TransformRequestValidator;
|
|
||||||
import org.alfresco.transform.registry.TransformServiceRegistry;
|
import org.alfresco.transform.registry.TransformServiceRegistry;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -47,24 +40,16 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||||
import org.springframework.context.event.EventListener;
|
import org.springframework.context.event.EventListener;
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.validation.DirectFieldBindingResult;
|
|
||||||
import org.springframework.validation.Errors;
|
|
||||||
import org.springframework.web.bind.MissingServletRequestParameterException;
|
import org.springframework.web.bind.MissingServletRequestParameterException;
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import org.springframework.web.client.HttpClientErrorException;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||||
@@ -72,50 +57,29 @@ import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBo
|
|||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import static java.text.MessageFormat.format;
|
import static java.text.MessageFormat.format;
|
||||||
import static java.util.stream.Collectors.joining;
|
|
||||||
import static org.alfresco.transform.base.fs.FileManager.TempFileProvider.createTempFile;
|
|
||||||
import static org.alfresco.transform.base.fs.FileManager.createTargetFile;
|
|
||||||
import static org.alfresco.transform.base.fs.FileManager.deleteFile;
|
|
||||||
import static org.alfresco.transform.base.fs.FileManager.getDirectAccessUrlInputStream;
|
|
||||||
import static org.alfresco.transform.base.fs.FileManager.getFilenameFromContentDisposition;
|
|
||||||
import static org.alfresco.transform.base.fs.FileManager.save;
|
|
||||||
import static org.alfresco.transform.common.RequestParamMap.CONFIG_VERSION;
|
import static org.alfresco.transform.common.RequestParamMap.CONFIG_VERSION;
|
||||||
import static org.alfresco.transform.common.RequestParamMap.CONFIG_VERSION_DEFAULT;
|
import static org.alfresco.transform.common.RequestParamMap.CONFIG_VERSION_DEFAULT;
|
||||||
import static org.alfresco.transform.common.RequestParamMap.DIRECT_ACCESS_URL;
|
|
||||||
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_ERROR;
|
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_ERROR;
|
||||||
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_LOG;
|
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_LOG;
|
||||||
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_ROOT;
|
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_ROOT;
|
||||||
|
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TEST;
|
||||||
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM;
|
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM;
|
||||||
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM_CONFIG;
|
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM_CONFIG;
|
||||||
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TEST;
|
|
||||||
import static org.alfresco.transform.common.RequestParamMap.FILE;
|
import static org.alfresco.transform.common.RequestParamMap.FILE;
|
||||||
import static org.alfresco.transform.common.RequestParamMap.SOURCE_ENCODING;
|
|
||||||
import static org.alfresco.transform.common.RequestParamMap.SOURCE_EXTENSION;
|
|
||||||
import static org.alfresco.transform.common.RequestParamMap.SOURCE_MIMETYPE;
|
import static org.alfresco.transform.common.RequestParamMap.SOURCE_MIMETYPE;
|
||||||
import static org.alfresco.transform.common.RequestParamMap.TARGET_ENCODING;
|
|
||||||
import static org.alfresco.transform.common.RequestParamMap.TARGET_MIMETYPE;
|
import static org.alfresco.transform.common.RequestParamMap.TARGET_MIMETYPE;
|
||||||
import static org.alfresco.transform.config.CoreVersionDecorator.setOrClearCoreVersion;
|
import static org.alfresco.transform.config.CoreVersionDecorator.setOrClearCoreVersion;
|
||||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||||
import static org.springframework.http.HttpStatus.CREATED;
|
|
||||||
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
|
|
||||||
import static org.springframework.http.HttpStatus.OK;
|
import static org.springframework.http.HttpStatus.OK;
|
||||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
|
||||||
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
|
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
|
||||||
import static org.springframework.util.StringUtils.getFilenameExtension;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the main endpoints into the t-engine.
|
* Provides the main endpoints into the t-engine.
|
||||||
@@ -124,82 +88,26 @@ import static org.springframework.util.StringUtils.getFilenameExtension;
|
|||||||
public class TransformController
|
public class TransformController
|
||||||
{
|
{
|
||||||
private static final Logger logger = LoggerFactory.getLogger(TransformController.class);
|
private static final Logger logger = LoggerFactory.getLogger(TransformController.class);
|
||||||
private static final List<String> NON_TRANSFORM_OPTION_REQUEST_PARAMETERS = Arrays.asList(SOURCE_EXTENSION,
|
|
||||||
TARGET_MIMETYPE, SOURCE_MIMETYPE, DIRECT_ACCESS_URL);
|
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
private List<TransformEngine> transformEngines;
|
private List<TransformEngine> transformEngines;
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
private List<CustomTransformer> customTransformers;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private AlfrescoSharedFileStoreClient alfrescoSharedFileStoreClient;
|
|
||||||
@Autowired
|
|
||||||
private TransformRequestValidator transformRequestValidator;
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TransformServiceRegistry transformRegistry;
|
private TransformServiceRegistry transformRegistry;
|
||||||
@Autowired
|
@Autowired
|
||||||
private TransformerDebug transformerDebug;
|
private TransformHandler transformHandler;
|
||||||
@Value("${transform.core.version}")
|
@Value("${transform.core.version}")
|
||||||
private String coreVersion;
|
private String coreVersion;
|
||||||
|
|
||||||
private TransformEngine transformEngine;
|
private TransformEngine transformEngine;
|
||||||
ProbeTestTransform probeTestTransform;
|
ProbeTestTransform probeTestTransform;
|
||||||
private Map<String, CustomTransformer> customTransformersByName = new HashMap<>();
|
|
||||||
private AtomicInteger httpRequestCount = new AtomicInteger(1);
|
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init()
|
private void init()
|
||||||
{
|
{
|
||||||
initTransformEngine();
|
transformEngine = transformHandler.getTransformEngine();
|
||||||
initProbeTestTransform();
|
probeTestTransform = transformHandler.getProbeTestTransform();
|
||||||
initCustomTransformersByName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initTransformEngine()
|
|
||||||
{
|
|
||||||
if (transformEngines != null)
|
|
||||||
{
|
|
||||||
// Normally there is just one TransformEngine per t-engine, but we also want to be able to amalgamate the
|
|
||||||
// CustomTransform code from many t-engines into a single t-engine. In this case, there should be a wrapper
|
|
||||||
// TransformEngine (it has no TransformConfig of its own).
|
|
||||||
transformEngine = transformEngines.stream()
|
|
||||||
.filter(transformEngine -> transformEngine.getTransformConfig() == null)
|
|
||||||
.findFirst()
|
|
||||||
.orElse(transformEngines.get(0));
|
|
||||||
|
|
||||||
logger.info("TransformEngine: " + transformEngine.getTransformEngineName());
|
|
||||||
transformEngines.stream()
|
|
||||||
.filter(te -> te != transformEngine)
|
|
||||||
.sorted(Comparator.comparing(TransformEngine::getTransformEngineName))
|
|
||||||
.map(transformEngine -> " "+transformEngine.getTransformEngineName()).forEach(logger::info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initProbeTestTransform()
|
|
||||||
{
|
|
||||||
if (transformEngine != null)
|
|
||||||
{
|
|
||||||
probeTestTransform = transformEngine.getLivenessAndReadinessProbeTestTransform();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initCustomTransformersByName()
|
|
||||||
{
|
|
||||||
if (customTransformers != null)
|
|
||||||
{
|
|
||||||
customTransformers.forEach(customTransformer ->
|
|
||||||
customTransformersByName.put(customTransformer.getTransformerName(), customTransformer));
|
|
||||||
|
|
||||||
logger.info("Transformers:");
|
|
||||||
customTransformers.stream()
|
|
||||||
.sorted(Comparator.comparing(CustomTransformer::getTransformerName))
|
|
||||||
.map(customTransformer -> " "+customTransformer.getTransformerName()).forEach(logger::info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@EventListener(ApplicationReadyEvent.class)
|
@EventListener(ApplicationReadyEvent.class)
|
||||||
public void startup()
|
public void startup()
|
||||||
{
|
{
|
||||||
@@ -288,13 +196,26 @@ public class TransformController
|
|||||||
return new ResponseEntity<>(transformConfig, OK);
|
return new ResponseEntity<>(transformConfig, OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = ENDPOINT_TRANSFORM, consumes = MULTIPART_FORM_DATA_VALUE)
|
||||||
|
public StreamingResponseBody transform(HttpServletRequest request,
|
||||||
|
@RequestParam(value = FILE, required = false) MultipartFile sourceMultipartFile,
|
||||||
|
@RequestParam(value = SOURCE_MIMETYPE, required = false) String sourceMimetype,
|
||||||
|
@RequestParam(value = TARGET_MIMETYPE, required = false) String targetMimetype,
|
||||||
|
@RequestParam Map<String, String> requestParameters)
|
||||||
|
{
|
||||||
|
return transformHandler.handleHttpRequest(request, sourceMultipartFile, sourceMimetype,
|
||||||
|
targetMimetype, requestParameters);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping(value = ENDPOINT_TEST, consumes = MULTIPART_FORM_DATA_VALUE)
|
@PostMapping(value = ENDPOINT_TEST, consumes = MULTIPART_FORM_DATA_VALUE)
|
||||||
public StreamingResponseBody test(HttpServletRequest request,
|
public StreamingResponseBody testTransform(HttpServletRequest request,
|
||||||
@RequestParam(value = FILE, required = false) MultipartFile sourceMultipartFile,
|
@RequestParam(value = FILE, required = false) MultipartFile sourceMultipartFile,
|
||||||
@RequestParam(value = SOURCE_MIMETYPE, required = false) String sourceMimetype,
|
@RequestParam(value = SOURCE_MIMETYPE, required = false) String sourceMimetype,
|
||||||
@RequestParam(value = TARGET_MIMETYPE, required = false) String targetMimetype,
|
@RequestParam(value = TARGET_MIMETYPE, required = false) String targetMimetype,
|
||||||
@RequestParam Map<String, String> origRequestParameters)
|
@RequestParam Map<String, String> origRequestParameters)
|
||||||
{
|
{
|
||||||
|
// Remaps request parameters from test.html and hands them off to the normal transform endpoint.
|
||||||
|
// There are name<i> and value<i> parameters which allow dynamic names and values to be used.
|
||||||
Map<String, String> requestParameters = new HashMap<>();
|
Map<String, String> requestParameters = new HashMap<>();
|
||||||
sourceMimetype = overrideMimetypeFromExtension(origRequestParameters, SOURCE_MIMETYPE, sourceMimetype);
|
sourceMimetype = overrideMimetypeFromExtension(origRequestParameters, SOURCE_MIMETYPE, sourceMimetype);
|
||||||
targetMimetype = overrideMimetypeFromExtension(origRequestParameters, TARGET_MIMETYPE, targetMimetype);
|
targetMimetype = overrideMimetypeFromExtension(origRequestParameters, TARGET_MIMETYPE, targetMimetype);
|
||||||
@@ -328,420 +249,6 @@ public class TransformController
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = ENDPOINT_TRANSFORM, consumes = MULTIPART_FORM_DATA_VALUE)
|
|
||||||
public StreamingResponseBody transform(HttpServletRequest request,
|
|
||||||
@RequestParam(value = FILE, required = false) MultipartFile sourceMultipartFile,
|
|
||||||
@RequestParam(value = SOURCE_MIMETYPE, required = false) String sourceMimetype,
|
|
||||||
@RequestParam(value = TARGET_MIMETYPE, required = false) String targetMimetype,
|
|
||||||
@RequestParam Map<String, String> requestParameters)
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
logger.debug("Processing request via HTTP endpoint. Params: sourceMimetype: '{}', targetMimetype: '{}', "
|
|
||||||
+ "requestParameters: {}", sourceMimetype, targetMimetype, requestParameters);
|
|
||||||
}
|
|
||||||
probeTestTransform.incrementTransformerCount();
|
|
||||||
|
|
||||||
// Obtain the source
|
|
||||||
final String directUrl = requestParameters.getOrDefault(DIRECT_ACCESS_URL, "");
|
|
||||||
InputStream inputStream = directUrl.isBlank()
|
|
||||||
? FileManager.getMultipartFileInputStream(sourceMultipartFile)
|
|
||||||
: getDirectAccessUrlInputStream(directUrl);
|
|
||||||
long sourceSizeInBytes = -1L; // TODO pass in t-options or just ignore for http request as the repo will have checked.
|
|
||||||
Map<String, String> transformOptions = getTransformOptions(requestParameters);
|
|
||||||
String transformName = getTransformerName(sourceSizeInBytes, sourceMimetype, targetMimetype, transformOptions);
|
|
||||||
CustomTransformer customTransformer = getCustomTransformer(transformName);
|
|
||||||
String sourceEncoding = transformOptions.get(SOURCE_ENCODING);
|
|
||||||
String targetEncoding = transformOptions.get(TARGET_ENCODING); // TODO not normally set
|
|
||||||
String reference = "e"+httpRequestCount.getAndIncrement();
|
|
||||||
transformerDebug.pushTransform(reference, sourceMimetype, targetMimetype, sourceSizeInBytes, transformName);
|
|
||||||
transformerDebug.logOptions(reference, requestParameters);
|
|
||||||
|
|
||||||
return os -> {
|
|
||||||
OutputStreamLengthRecorder outputStream = new OutputStreamLengthRecorder(os);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
TransformManagerImpl transformManager = TransformManagerImpl.builder()
|
|
||||||
.withRequest(request)
|
|
||||||
.withSourceMimetype(sourceMimetype)
|
|
||||||
.withTargetMimetype(targetMimetype)
|
|
||||||
.withInputStream(inputStream)
|
|
||||||
.withOutputStream(outputStream)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
customTransformer.transform(sourceMimetype, inputStream,
|
|
||||||
targetMimetype, outputStream, transformOptions, transformManager);
|
|
||||||
|
|
||||||
transformManager.ifUsedCopyTargetFileToOutputStream();
|
|
||||||
|
|
||||||
LogEntry.setTargetSize(outputStream.getLength());
|
|
||||||
long time = LogEntry.setStatusCodeAndMessage(OK.value(), "Success");
|
|
||||||
|
|
||||||
transformManager.deleteSourceFileIfExists();
|
|
||||||
transformManager.deleteTargetFileIfExists();
|
|
||||||
|
|
||||||
probeTestTransform.recordTransformTime(time);
|
|
||||||
transformerDebug.popTransform(reference, time);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
transformerDebug.logFailure(reference, e.getMessage());
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* '/transform' endpoint which consumes and produces 'application/json'
|
|
||||||
*
|
|
||||||
* This is the way to tell Spring to redirect the request to this endpoint
|
|
||||||
* instead of the one which produces 'html'
|
|
||||||
*
|
|
||||||
* @param request The transformation request
|
|
||||||
* @param timeout Transformation timeout
|
|
||||||
* @return A transformation reply
|
|
||||||
*/
|
|
||||||
public ResponseEntity<TransformReply> transform(@RequestBody TransformRequest request,
|
|
||||||
@RequestParam(value = "timeout", required = false) Long timeout)
|
|
||||||
{
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
logger.trace("Received {}, timeout {} ms", request, timeout);
|
|
||||||
probeTestTransform.incrementTransformerCount();
|
|
||||||
TransformReply reply = createBasicTransformReply(request);
|
|
||||||
|
|
||||||
if (isTransformRequestValid(request, reply) == false)
|
|
||||||
{
|
|
||||||
return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus()));
|
|
||||||
}
|
|
||||||
|
|
||||||
InputStream inputStream = getInputStream(request, reply);
|
|
||||||
if (inputStream == null)
|
|
||||||
{
|
|
||||||
return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus()));
|
|
||||||
}
|
|
||||||
|
|
||||||
String targetMimetype = request.getTargetMediaType();
|
|
||||||
String sourceMimetype = request.getSourceMediaType();
|
|
||||||
File targetFile = createTargetFile(null, sourceMimetype, targetMimetype);
|
|
||||||
transformerDebug.pushTransform(request);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
OutputStreamLengthRecorder outputStream =
|
|
||||||
new OutputStreamLengthRecorder(new BufferedOutputStream(new FileOutputStream(targetFile)));
|
|
||||||
|
|
||||||
long sourceSizeInBytes = request.getSourceSize();
|
|
||||||
Map<String, String> transformOptions = getTransformOptions(request.getTransformRequestOptions());
|
|
||||||
String sourceEncoding = transformOptions.get(SOURCE_ENCODING);
|
|
||||||
String targetEncoding = transformOptions.get(TARGET_ENCODING); // TODO not normally set
|
|
||||||
transformerDebug.logOptions(request);
|
|
||||||
String transformName = getTransformerName(sourceSizeInBytes, sourceMimetype, targetMimetype, transformOptions);
|
|
||||||
CustomTransformer customTransformer = getCustomTransformer(transformName);
|
|
||||||
|
|
||||||
TransformManagerImpl transformManager = TransformManagerImpl.builder()
|
|
||||||
.withSourceMimetype(sourceMimetype)
|
|
||||||
.withTargetMimetype(targetMimetype)
|
|
||||||
.withInputStream(inputStream)
|
|
||||||
.withOutputStream(outputStream)
|
|
||||||
.withTargetFile(targetFile)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
customTransformer.transform(sourceMimetype, inputStream,
|
|
||||||
targetMimetype, outputStream, transformOptions, transformManager);
|
|
||||||
|
|
||||||
transformManager.ifUsedCopyTargetFileToOutputStream();
|
|
||||||
|
|
||||||
reply.getInternalContext().setCurrentSourceSize(outputStream.getLength());
|
|
||||||
|
|
||||||
if (saveTargetFileInSharedFileStore(targetFile, reply) == false)
|
|
||||||
{
|
|
||||||
return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus()));
|
|
||||||
}
|
|
||||||
|
|
||||||
transformManager.deleteSourceFileIfExists();
|
|
||||||
transformManager.deleteTargetFileIfExists();
|
|
||||||
|
|
||||||
probeTestTransform.recordTransformTime(System.currentTimeMillis()-start);
|
|
||||||
transformerDebug.popTransform(reply);
|
|
||||||
|
|
||||||
logger.trace("Sending successful {}, timeout {} ms", reply, timeout);
|
|
||||||
return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus()));
|
|
||||||
}
|
|
||||||
catch (TransformException e)
|
|
||||||
{
|
|
||||||
reply.setStatus(e.getStatusCode());
|
|
||||||
reply.setErrorDetails(messageWithCause("Failed at processing transformation", e));
|
|
||||||
|
|
||||||
transformerDebug.logFailure(reply);
|
|
||||||
logger.trace("Failed to perform transform (TransformException), sending " + reply, e);
|
|
||||||
return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus()));
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
reply.setStatus(INTERNAL_SERVER_ERROR.value());
|
|
||||||
reply.setErrorDetails(messageWithCause("Failed at processing transformation", e));
|
|
||||||
|
|
||||||
transformerDebug.logFailure(reply);
|
|
||||||
logger.trace("Failed to perform transform (Exception), sending " + reply, e);
|
|
||||||
return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isTransformRequestValid(TransformRequest request, TransformReply reply)
|
|
||||||
{
|
|
||||||
final Errors errors = validateTransformRequest(request);
|
|
||||||
validateInternalContext(request, errors);
|
|
||||||
reply.setInternalContext(request.getInternalContext());
|
|
||||||
if (!errors.getAllErrors().isEmpty())
|
|
||||||
{
|
|
||||||
reply.setStatus(BAD_REQUEST.value());
|
|
||||||
reply.setErrorDetails(errors
|
|
||||||
.getAllErrors()
|
|
||||||
.stream()
|
|
||||||
.map(Object::toString)
|
|
||||||
.collect(joining(", ")));
|
|
||||||
|
|
||||||
transformerDebug.logFailure(reply);
|
|
||||||
logger.trace("Invalid request, sending {}", reply);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private TransformReply createBasicTransformReply(TransformRequest request)
|
|
||||||
{
|
|
||||||
TransformReply reply = new TransformReply();
|
|
||||||
reply.setRequestId(request.getRequestId());
|
|
||||||
reply.setSourceReference(request.getSourceReference());
|
|
||||||
reply.setSchema(request.getSchema());
|
|
||||||
reply.setClientData(request.getClientData());
|
|
||||||
reply.setInternalContext(request.getInternalContext());
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Errors validateTransformRequest(final TransformRequest transformRequest)
|
|
||||||
{
|
|
||||||
DirectFieldBindingResult errors = new DirectFieldBindingResult(transformRequest, "request");
|
|
||||||
transformRequestValidator.validate(transformRequest, errors);
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void validateInternalContext(TransformRequest request, Errors errors)
|
|
||||||
{
|
|
||||||
String errorMessage = InternalContext.checkForBasicErrors(request.getInternalContext(), "T-Request");
|
|
||||||
if (errorMessage != null)
|
|
||||||
{
|
|
||||||
errors.rejectValue("internalContext", null, errorMessage);
|
|
||||||
}
|
|
||||||
initialiseContext(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initialiseContext(TransformRequest request)
|
|
||||||
{
|
|
||||||
// If needed, initialise the context enough to allow logging to take place without NPE checks
|
|
||||||
request.setInternalContext(InternalContext.initialise(request.getInternalContext()));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Map<String, String> getTransformOptions(Map<String, String> requestParameters)
|
|
||||||
{
|
|
||||||
Map<String, String> transformOptions = new HashMap<>(requestParameters);
|
|
||||||
transformOptions.keySet().removeAll(NON_TRANSFORM_OPTION_REQUEST_PARAMETERS);
|
|
||||||
transformOptions.values().removeIf(v -> v.isEmpty());
|
|
||||||
return transformOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
private InputStream getSharedFileStoreInputStream(String sourceReference)
|
|
||||||
{
|
|
||||||
ResponseEntity<Resource> responseEntity = alfrescoSharedFileStoreClient.retrieveFile(sourceReference);
|
|
||||||
final Resource body = responseEntity.getBody();
|
|
||||||
if (body == null)
|
|
||||||
{
|
|
||||||
String message = "Source file with reference: " + sourceReference + " is null or empty.";
|
|
||||||
logger.warn(message);
|
|
||||||
throw new TransformException(BAD_REQUEST.value(), message);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return body.getInputStream();
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
String message = "Shared File Store reference is invalid.";
|
|
||||||
logger.warn(message);
|
|
||||||
throw new TransformException(BAD_REQUEST.value(), message, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private InputStream getInputStream(TransformRequest request, TransformReply reply)
|
|
||||||
{
|
|
||||||
final String directUrl = request.getTransformRequestOptions().getOrDefault(DIRECT_ACCESS_URL, "");
|
|
||||||
InputStream inputStream = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
inputStream = directUrl.isBlank()
|
|
||||||
? getSharedFileStoreInputStream(request.getSourceReference())
|
|
||||||
: getDirectAccessUrlInputStream(directUrl);
|
|
||||||
}
|
|
||||||
catch (TransformException e)
|
|
||||||
{
|
|
||||||
reply.setStatus(e.getStatusCode());
|
|
||||||
reply.setErrorDetails(messageWithCause("Failed at reading the source file", e));
|
|
||||||
|
|
||||||
transformerDebug.logFailure(reply);
|
|
||||||
logger.trace("Failed to load source file (TransformException), sending " + reply);
|
|
||||||
}
|
|
||||||
catch (HttpClientErrorException e)
|
|
||||||
{
|
|
||||||
reply.setStatus(e.getStatusCode().value());
|
|
||||||
reply.setErrorDetails(messageWithCause("Failed at reading the source file", e));
|
|
||||||
|
|
||||||
transformerDebug.logFailure(reply);
|
|
||||||
logger.trace("Failed to load source file (HttpClientErrorException), sending " + reply, e);
|
|
||||||
}
|
|
||||||
return inputStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean saveTargetFileInSharedFileStore(File targetFile, TransformReply reply)
|
|
||||||
{
|
|
||||||
FileRefResponse targetRef;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
targetRef = alfrescoSharedFileStoreClient.saveFile(targetFile);
|
|
||||||
}
|
|
||||||
catch (TransformException e)
|
|
||||||
{
|
|
||||||
reply.setStatus(e.getStatusCode());
|
|
||||||
reply.setErrorDetails(messageWithCause("Failed at writing the transformed file", e));
|
|
||||||
|
|
||||||
transformerDebug.logFailure(reply);
|
|
||||||
logger.trace("Failed to save target file (TransformException), sending " + reply, e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (HttpClientErrorException e)
|
|
||||||
{
|
|
||||||
reply.setStatus(e.getStatusCode().value());
|
|
||||||
reply.setErrorDetails(messageWithCause("Failed at writing the transformed file. ", e));
|
|
||||||
|
|
||||||
transformerDebug.logFailure(reply);
|
|
||||||
logger.trace("Failed to save target file (HttpClientErrorException), sending " + reply, e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
reply.setStatus(INTERNAL_SERVER_ERROR.value());
|
|
||||||
reply.setErrorDetails(messageWithCause("Failed at writing the transformed file. ", e));
|
|
||||||
|
|
||||||
transformerDebug.logFailure(reply);
|
|
||||||
logger.trace("Failed to save target file (Exception), sending " + reply, e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
deleteFile(targetFile);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
logger.error("Failed to delete local temp target file. Error will be ignored ", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
reply.setTargetReference(targetRef.getEntry().getFileRef());
|
|
||||||
reply.setStatus(CREATED.value());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the file with the specified sourceReference from Alfresco Shared File Store
|
|
||||||
*
|
|
||||||
* @param sourceReference reference to the file in Alfresco Shared File Store
|
|
||||||
* @param sourceExtension default extension if the file in Alfresco Shared File Store has none
|
|
||||||
* @return the file containing the source content for the transformation
|
|
||||||
*/
|
|
||||||
private File loadSourceFile(final String sourceReference, final String sourceExtension)
|
|
||||||
{
|
|
||||||
ResponseEntity<Resource> responseEntity = alfrescoSharedFileStoreClient.retrieveFile(sourceReference);
|
|
||||||
|
|
||||||
HttpHeaders headers = responseEntity.getHeaders();
|
|
||||||
String filename = getFilenameFromContentDisposition(headers);
|
|
||||||
|
|
||||||
String extension = getFilenameExtension(filename) != null ? getFilenameExtension(filename) : sourceExtension;
|
|
||||||
MediaType contentType = headers.getContentType();
|
|
||||||
long size = headers.getContentLength();
|
|
||||||
|
|
||||||
final Resource body = responseEntity.getBody();
|
|
||||||
if (body == null)
|
|
||||||
{
|
|
||||||
String message = "Source file with reference: " + sourceReference + " is null or empty. "
|
|
||||||
+ "Transformation will fail and stop now as there is no content to be transformed.";
|
|
||||||
logger.warn(message);
|
|
||||||
throw new TransformException(BAD_REQUEST.value(), message);
|
|
||||||
}
|
|
||||||
final File file = createTempFile("source_", "." + extension);
|
|
||||||
|
|
||||||
logger.debug("Read source content {} length={} contentType={}",
|
|
||||||
sourceReference, size, contentType);
|
|
||||||
|
|
||||||
save(body, file);
|
|
||||||
LogEntry.setSource(filename, size);
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String messageWithCause(final String prefix, Throwable e)
|
|
||||||
{
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append(prefix).append(" - ")
|
|
||||||
.append(e.getClass().getSimpleName()).append(": ")
|
|
||||||
.append(e.getMessage());
|
|
||||||
|
|
||||||
while (e.getCause() != null)
|
|
||||||
{
|
|
||||||
e = e.getCause();
|
|
||||||
sb.append(", cause ")
|
|
||||||
.append(e.getClass().getSimpleName()).append(": ")
|
|
||||||
.append(e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTransformerName(long sourceSizeInBytes, final String sourceMimetype,
|
|
||||||
final String targetMimetype, final Map<String, String> transformOptions)
|
|
||||||
{
|
|
||||||
// The transformOptions always contains sourceEncoding when sent to a T-Engine, even though it should not be
|
|
||||||
// used to select a transformer. Similar to source and target mimetypes and extensions, but these are not
|
|
||||||
// passed in transformOptions.
|
|
||||||
String sourceEncoding = transformOptions.remove(SOURCE_ENCODING);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
final String transformerName = transformRegistry.findTransformerName(sourceMimetype,
|
|
||||||
sourceSizeInBytes, targetMimetype, transformOptions, null);
|
|
||||||
if (transformerName == null)
|
|
||||||
{
|
|
||||||
throw new TransformException(BAD_REQUEST.value(), "No transforms were able to handle the request");
|
|
||||||
}
|
|
||||||
return transformerName;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (sourceEncoding != null)
|
|
||||||
{
|
|
||||||
transformOptions.put(SOURCE_ENCODING, sourceEncoding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private CustomTransformer getCustomTransformer(String transformName)
|
|
||||||
{
|
|
||||||
CustomTransformer customTransformer = customTransformersByName.get(transformName);
|
|
||||||
if (customTransformer == null)
|
|
||||||
{
|
|
||||||
throw new TransformException(BAD_REQUEST.value(), "Custom Transformer "+customTransformer+" not found");
|
|
||||||
}
|
|
||||||
return customTransformer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(TypeMismatchException.class)
|
@ExceptionHandler(TypeMismatchException.class)
|
||||||
public void handleParamsTypeMismatch(HttpServletResponse response, MissingServletRequestParameterException e) throws IOException
|
public void handleParamsTypeMismatch(HttpServletResponse response, MissingServletRequestParameterException e) throws IOException
|
||||||
{
|
{
|
||||||
|
@@ -26,9 +26,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.transform.base;
|
package org.alfresco.transform.base;
|
||||||
|
|
||||||
|
import org.alfresco.transform.base.probes.ProbeTestTransform;
|
||||||
import org.alfresco.transform.common.TransformConfigResourceReader;
|
import org.alfresco.transform.common.TransformConfigResourceReader;
|
||||||
import org.alfresco.transform.config.TransformConfig;
|
import org.alfresco.transform.config.TransformConfig;
|
||||||
import org.alfresco.transform.base.probes.ProbeTestTransform;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface to be implemented by transform specific code. Provides information about the t-engine as a whole.
|
* Interface to be implemented by transform specific code. Provides information about the t-engine as a whole.
|
||||||
|
@@ -0,0 +1,577 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Transform Core
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* -
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
* -
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
* -
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
* -
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.transform.base;
|
||||||
|
|
||||||
|
import org.alfresco.transform.base.clients.AlfrescoSharedFileStoreClient;
|
||||||
|
import org.alfresco.transform.base.fs.FileManager;
|
||||||
|
import org.alfresco.transform.base.logging.LogEntry;
|
||||||
|
import org.alfresco.transform.base.model.FileRefResponse;
|
||||||
|
import org.alfresco.transform.base.probes.ProbeTestTransform;
|
||||||
|
import org.alfresco.transform.base.util.OutputStreamLengthRecorder;
|
||||||
|
import org.alfresco.transform.client.model.InternalContext;
|
||||||
|
import org.alfresco.transform.client.model.TransformReply;
|
||||||
|
import org.alfresco.transform.client.model.TransformRequest;
|
||||||
|
import org.alfresco.transform.common.TransformException;
|
||||||
|
import org.alfresco.transform.common.TransformerDebug;
|
||||||
|
import org.alfresco.transform.messages.TransformRequestValidator;
|
||||||
|
import org.alfresco.transform.registry.TransformServiceRegistry;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.validation.DirectFieldBindingResult;
|
||||||
|
import org.springframework.validation.Errors;
|
||||||
|
import org.springframework.web.client.HttpClientErrorException;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import static java.util.stream.Collectors.joining;
|
||||||
|
import static org.alfresco.transform.base.fs.FileManager.TempFileProvider.createTempFile;
|
||||||
|
import static org.alfresco.transform.base.fs.FileManager.createTargetFile;
|
||||||
|
import static org.alfresco.transform.base.fs.FileManager.deleteFile;
|
||||||
|
import static org.alfresco.transform.base.fs.FileManager.getDirectAccessUrlInputStream;
|
||||||
|
import static org.alfresco.transform.base.fs.FileManager.getFilenameFromContentDisposition;
|
||||||
|
import static org.alfresco.transform.base.fs.FileManager.save;
|
||||||
|
import static org.alfresco.transform.common.RequestParamMap.DIRECT_ACCESS_URL;
|
||||||
|
import static org.alfresco.transform.common.RequestParamMap.SOURCE_ENCODING;
|
||||||
|
import static org.alfresco.transform.common.RequestParamMap.SOURCE_EXTENSION;
|
||||||
|
import static org.alfresco.transform.common.RequestParamMap.SOURCE_MIMETYPE;
|
||||||
|
import static org.alfresco.transform.common.RequestParamMap.TARGET_ENCODING;
|
||||||
|
import static org.alfresco.transform.common.RequestParamMap.TARGET_MIMETYPE;
|
||||||
|
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||||
|
import static org.springframework.http.HttpStatus.CREATED;
|
||||||
|
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
|
||||||
|
import static org.springframework.http.HttpStatus.OK;
|
||||||
|
import static org.springframework.util.StringUtils.getFilenameExtension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the transform requests from either http or a message.
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class TransformHandler
|
||||||
|
{
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(TransformHandler.class);
|
||||||
|
private static final List<String> NON_TRANSFORM_OPTION_REQUEST_PARAMETERS = Arrays.asList(SOURCE_EXTENSION,
|
||||||
|
TARGET_MIMETYPE, SOURCE_MIMETYPE, DIRECT_ACCESS_URL);
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private List<TransformEngine> transformEngines;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private List<CustomTransformer> customTransformers;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AlfrescoSharedFileStoreClient alfrescoSharedFileStoreClient;
|
||||||
|
@Autowired
|
||||||
|
private TransformRequestValidator transformRequestValidator;
|
||||||
|
@Autowired
|
||||||
|
private TransformServiceRegistry transformRegistry;
|
||||||
|
@Autowired
|
||||||
|
private TransformerDebug transformerDebug;
|
||||||
|
@Autowired
|
||||||
|
private TransformEngine transformEngine;
|
||||||
|
private AtomicInteger httpRequestCount = new AtomicInteger(1);
|
||||||
|
private ProbeTestTransform probeTestTransform;
|
||||||
|
private Map<String, CustomTransformer> customTransformersByName = new HashMap<>();
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
initTransformEngine();
|
||||||
|
initProbeTestTransform();
|
||||||
|
initCustomTransformersByName();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initTransformEngine()
|
||||||
|
{
|
||||||
|
if (transformEngines != null)
|
||||||
|
{
|
||||||
|
// Normally there is just one TransformEngine per t-engine, but we also want to be able to amalgamate the
|
||||||
|
// CustomTransform code from many t-engines into a single t-engine. In this case, there should be a wrapper
|
||||||
|
// TransformEngine (it has no TransformConfig of its own).
|
||||||
|
transformEngine = transformEngines.stream()
|
||||||
|
.filter(transformEngine -> transformEngine.getTransformConfig() == null)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(transformEngines.get(0));
|
||||||
|
|
||||||
|
logger.info("TransformEngine: " + transformEngine.getTransformEngineName());
|
||||||
|
transformEngines.stream()
|
||||||
|
.filter(te -> te != transformEngine)
|
||||||
|
.sorted(Comparator.comparing(TransformEngine::getTransformEngineName))
|
||||||
|
.map(transformEngine -> " "+transformEngine.getTransformEngineName()).forEach(logger::info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initProbeTestTransform()
|
||||||
|
{
|
||||||
|
if (transformEngine != null)
|
||||||
|
{
|
||||||
|
probeTestTransform = transformEngine.getLivenessAndReadinessProbeTestTransform();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initCustomTransformersByName()
|
||||||
|
{
|
||||||
|
if (customTransformers != null)
|
||||||
|
{
|
||||||
|
customTransformers.forEach(customTransformer ->
|
||||||
|
customTransformersByName.put(customTransformer.getTransformerName(), customTransformer));
|
||||||
|
|
||||||
|
logger.info("Transformers:");
|
||||||
|
customTransformers.stream()
|
||||||
|
.sorted(Comparator.comparing(CustomTransformer::getTransformerName))
|
||||||
|
.map(customTransformer -> " "+customTransformer.getTransformerName()).forEach(logger::info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransformEngine getTransformEngine()
|
||||||
|
{
|
||||||
|
return transformEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProbeTestTransform getProbeTestTransform()
|
||||||
|
{
|
||||||
|
return probeTestTransform;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamingResponseBody handleHttpRequest(HttpServletRequest request, MultipartFile sourceMultipartFile,
|
||||||
|
String sourceMimetype, String targetMimetype, Map<String, String> requestParameters)
|
||||||
|
{
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Processing request via HTTP endpoint. Params: sourceMimetype: '{}', targetMimetype: '{}', "
|
||||||
|
+ "requestParameters: {}", sourceMimetype, targetMimetype, requestParameters);
|
||||||
|
}
|
||||||
|
probeTestTransform.incrementTransformerCount();
|
||||||
|
|
||||||
|
// Obtain the source
|
||||||
|
final String directUrl = requestParameters.getOrDefault(DIRECT_ACCESS_URL, "");
|
||||||
|
InputStream inputStream = directUrl.isBlank()
|
||||||
|
? FileManager.getMultipartFileInputStream(sourceMultipartFile)
|
||||||
|
: getDirectAccessUrlInputStream(directUrl);
|
||||||
|
long sourceSizeInBytes = -1L; // TODO pass in t-options or just ignore for http request as the repo will have checked.
|
||||||
|
Map<String, String> transformOptions = getTransformOptions(requestParameters);
|
||||||
|
String transformName = getTransformerName(sourceSizeInBytes, sourceMimetype, targetMimetype, transformOptions);
|
||||||
|
CustomTransformer customTransformer = getCustomTransformer(transformName);
|
||||||
|
String sourceEncoding = transformOptions.get(SOURCE_ENCODING);
|
||||||
|
String targetEncoding = transformOptions.get(TARGET_ENCODING); // TODO not normally set
|
||||||
|
String reference = "e"+httpRequestCount.getAndIncrement();
|
||||||
|
transformerDebug.pushTransform(reference, sourceMimetype, targetMimetype, sourceSizeInBytes, transformName);
|
||||||
|
transformerDebug.logOptions(reference, requestParameters);
|
||||||
|
|
||||||
|
return os -> {
|
||||||
|
OutputStreamLengthRecorder outputStream = new OutputStreamLengthRecorder(os);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TransformManagerImpl transformManager = TransformManagerImpl.builder()
|
||||||
|
.withRequest(request)
|
||||||
|
.withSourceMimetype(sourceMimetype)
|
||||||
|
.withTargetMimetype(targetMimetype)
|
||||||
|
.withInputStream(inputStream)
|
||||||
|
.withOutputStream(outputStream)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
customTransformer.transform(sourceMimetype, inputStream,
|
||||||
|
targetMimetype, outputStream, transformOptions, transformManager);
|
||||||
|
|
||||||
|
transformManager.ifUsedCopyTargetFileToOutputStream();
|
||||||
|
|
||||||
|
LogEntry.setTargetSize(outputStream.getLength());
|
||||||
|
long time = LogEntry.setStatusCodeAndMessage(OK.value(), "Success");
|
||||||
|
|
||||||
|
transformManager.deleteSourceFileIfExists();
|
||||||
|
transformManager.deleteTargetFileIfExists();
|
||||||
|
|
||||||
|
probeTestTransform.recordTransformTime(time);
|
||||||
|
transformerDebug.popTransform(reference, time);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
transformerDebug.logFailure(reference, e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResponseEntity<TransformReply> handleMessageRequest(TransformRequest request, Long timeout)
|
||||||
|
{
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
logger.trace("Received {}, timeout {} ms", request, timeout);
|
||||||
|
probeTestTransform.incrementTransformerCount();
|
||||||
|
TransformReply reply = createBasicTransformReply(request);
|
||||||
|
|
||||||
|
if (isTransformRequestValid(request, reply) == false)
|
||||||
|
{
|
||||||
|
return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus()));
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream inputStream = getInputStream(request, reply);
|
||||||
|
if (inputStream == null)
|
||||||
|
{
|
||||||
|
return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus()));
|
||||||
|
}
|
||||||
|
|
||||||
|
String targetMimetype = request.getTargetMediaType();
|
||||||
|
String sourceMimetype = request.getSourceMediaType();
|
||||||
|
File targetFile = createTargetFile(null, sourceMimetype, targetMimetype);
|
||||||
|
transformerDebug.pushTransform(request);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
OutputStreamLengthRecorder outputStream =
|
||||||
|
new OutputStreamLengthRecorder(new BufferedOutputStream(new FileOutputStream(targetFile)));
|
||||||
|
|
||||||
|
long sourceSizeInBytes = request.getSourceSize();
|
||||||
|
Map<String, String> transformOptions = getTransformOptions(request.getTransformRequestOptions());
|
||||||
|
String sourceEncoding = transformOptions.get(SOURCE_ENCODING);
|
||||||
|
String targetEncoding = transformOptions.get(TARGET_ENCODING); // TODO not normally set
|
||||||
|
transformerDebug.logOptions(request);
|
||||||
|
String transformName = getTransformerName(sourceSizeInBytes, sourceMimetype, targetMimetype, transformOptions);
|
||||||
|
CustomTransformer customTransformer = getCustomTransformer(transformName);
|
||||||
|
|
||||||
|
TransformManagerImpl transformManager = TransformManagerImpl.builder()
|
||||||
|
.withSourceMimetype(sourceMimetype)
|
||||||
|
.withTargetMimetype(targetMimetype)
|
||||||
|
.withInputStream(inputStream)
|
||||||
|
.withOutputStream(outputStream)
|
||||||
|
.withTargetFile(targetFile)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
customTransformer.transform(sourceMimetype, inputStream,
|
||||||
|
targetMimetype, outputStream, transformOptions, transformManager);
|
||||||
|
|
||||||
|
transformManager.ifUsedCopyTargetFileToOutputStream();
|
||||||
|
|
||||||
|
reply.getInternalContext().setCurrentSourceSize(outputStream.getLength());
|
||||||
|
|
||||||
|
if (saveTargetFileInSharedFileStore(targetFile, reply) == false)
|
||||||
|
{
|
||||||
|
return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus()));
|
||||||
|
}
|
||||||
|
|
||||||
|
transformManager.deleteSourceFileIfExists();
|
||||||
|
transformManager.deleteTargetFileIfExists();
|
||||||
|
|
||||||
|
probeTestTransform.recordTransformTime(System.currentTimeMillis()-start);
|
||||||
|
transformerDebug.popTransform(reply);
|
||||||
|
|
||||||
|
logger.trace("Sending successful {}, timeout {} ms", reply, timeout);
|
||||||
|
return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus()));
|
||||||
|
}
|
||||||
|
catch (TransformException e)
|
||||||
|
{
|
||||||
|
reply.setStatus(e.getStatusCode());
|
||||||
|
reply.setErrorDetails(messageWithCause("Failed at processing transformation", e));
|
||||||
|
|
||||||
|
transformerDebug.logFailure(reply);
|
||||||
|
logger.trace("Failed to perform transform (TransformException), sending " + reply, e);
|
||||||
|
return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus()));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
reply.setStatus(INTERNAL_SERVER_ERROR.value());
|
||||||
|
reply.setErrorDetails(messageWithCause("Failed at processing transformation", e));
|
||||||
|
|
||||||
|
transformerDebug.logFailure(reply);
|
||||||
|
logger.trace("Failed to perform transform (Exception), sending " + reply, e);
|
||||||
|
return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private boolean isTransformRequestValid(TransformRequest request, TransformReply reply)
|
||||||
|
{
|
||||||
|
final Errors errors = validateTransformRequest(request);
|
||||||
|
validateInternalContext(request, errors);
|
||||||
|
reply.setInternalContext(request.getInternalContext());
|
||||||
|
if (!errors.getAllErrors().isEmpty())
|
||||||
|
{
|
||||||
|
reply.setStatus(BAD_REQUEST.value());
|
||||||
|
reply.setErrorDetails(errors
|
||||||
|
.getAllErrors()
|
||||||
|
.stream()
|
||||||
|
.map(Object::toString)
|
||||||
|
.collect(joining(", ")));
|
||||||
|
|
||||||
|
transformerDebug.logFailure(reply);
|
||||||
|
logger.trace("Invalid request, sending {}", reply);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TransformReply createBasicTransformReply(TransformRequest request)
|
||||||
|
{
|
||||||
|
TransformReply reply = new TransformReply();
|
||||||
|
reply.setRequestId(request.getRequestId());
|
||||||
|
reply.setSourceReference(request.getSourceReference());
|
||||||
|
reply.setSchema(request.getSchema());
|
||||||
|
reply.setClientData(request.getClientData());
|
||||||
|
reply.setInternalContext(request.getInternalContext());
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Errors validateTransformRequest(final TransformRequest transformRequest)
|
||||||
|
{
|
||||||
|
DirectFieldBindingResult errors = new DirectFieldBindingResult(transformRequest, "request");
|
||||||
|
transformRequestValidator.validate(transformRequest, errors);
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateInternalContext(TransformRequest request, Errors errors)
|
||||||
|
{
|
||||||
|
String errorMessage = InternalContext.checkForBasicErrors(request.getInternalContext(), "T-Request");
|
||||||
|
if (errorMessage != null)
|
||||||
|
{
|
||||||
|
errors.rejectValue("internalContext", null, errorMessage);
|
||||||
|
}
|
||||||
|
initialiseContext(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialiseContext(TransformRequest request)
|
||||||
|
{
|
||||||
|
// If needed, initialise the context enough to allow logging to take place without NPE checks
|
||||||
|
request.setInternalContext(InternalContext.initialise(request.getInternalContext()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> getTransformOptions(Map<String, String> requestParameters)
|
||||||
|
{
|
||||||
|
Map<String, String> transformOptions = new HashMap<>(requestParameters);
|
||||||
|
transformOptions.keySet().removeAll(NON_TRANSFORM_OPTION_REQUEST_PARAMETERS);
|
||||||
|
transformOptions.values().removeIf(v -> v.isEmpty());
|
||||||
|
return transformOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private InputStream getSharedFileStoreInputStream(String sourceReference)
|
||||||
|
{
|
||||||
|
ResponseEntity<Resource> responseEntity = alfrescoSharedFileStoreClient.retrieveFile(sourceReference);
|
||||||
|
final Resource body = responseEntity.getBody();
|
||||||
|
if (body == null)
|
||||||
|
{
|
||||||
|
String message = "Source file with reference: " + sourceReference + " is null or empty.";
|
||||||
|
logger.warn(message);
|
||||||
|
throw new TransformException(BAD_REQUEST.value(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return body.getInputStream();
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
String message = "Shared File Store reference is invalid.";
|
||||||
|
logger.warn(message);
|
||||||
|
throw new TransformException(BAD_REQUEST.value(), message, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private InputStream getInputStream(TransformRequest request, TransformReply reply)
|
||||||
|
{
|
||||||
|
final String directUrl = request.getTransformRequestOptions().getOrDefault(DIRECT_ACCESS_URL, "");
|
||||||
|
InputStream inputStream = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
inputStream = directUrl.isBlank()
|
||||||
|
? getSharedFileStoreInputStream(request.getSourceReference())
|
||||||
|
: getDirectAccessUrlInputStream(directUrl);
|
||||||
|
}
|
||||||
|
catch (TransformException e)
|
||||||
|
{
|
||||||
|
reply.setStatus(e.getStatusCode());
|
||||||
|
reply.setErrorDetails(messageWithCause("Failed at reading the source file", e));
|
||||||
|
|
||||||
|
transformerDebug.logFailure(reply);
|
||||||
|
logger.trace("Failed to load source file (TransformException), sending " + reply);
|
||||||
|
}
|
||||||
|
catch (HttpClientErrorException e)
|
||||||
|
{
|
||||||
|
reply.setStatus(e.getStatusCode().value());
|
||||||
|
reply.setErrorDetails(messageWithCause("Failed at reading the source file", e));
|
||||||
|
|
||||||
|
transformerDebug.logFailure(reply);
|
||||||
|
logger.trace("Failed to load source file (HttpClientErrorException), sending " + reply, e);
|
||||||
|
}
|
||||||
|
return inputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean saveTargetFileInSharedFileStore(File targetFile, TransformReply reply)
|
||||||
|
{
|
||||||
|
FileRefResponse targetRef;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
targetRef = alfrescoSharedFileStoreClient.saveFile(targetFile);
|
||||||
|
}
|
||||||
|
catch (TransformException e)
|
||||||
|
{
|
||||||
|
reply.setStatus(e.getStatusCode());
|
||||||
|
reply.setErrorDetails(messageWithCause("Failed at writing the transformed file", e));
|
||||||
|
|
||||||
|
transformerDebug.logFailure(reply);
|
||||||
|
logger.trace("Failed to save target file (TransformException), sending " + reply, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (HttpClientErrorException e)
|
||||||
|
{
|
||||||
|
reply.setStatus(e.getStatusCode().value());
|
||||||
|
reply.setErrorDetails(messageWithCause("Failed at writing the transformed file. ", e));
|
||||||
|
|
||||||
|
transformerDebug.logFailure(reply);
|
||||||
|
logger.trace("Failed to save target file (HttpClientErrorException), sending " + reply, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
reply.setStatus(INTERNAL_SERVER_ERROR.value());
|
||||||
|
reply.setErrorDetails(messageWithCause("Failed at writing the transformed file. ", e));
|
||||||
|
|
||||||
|
transformerDebug.logFailure(reply);
|
||||||
|
logger.trace("Failed to save target file (Exception), sending " + reply, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
deleteFile(targetFile);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.error("Failed to delete local temp target file. Error will be ignored ", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
reply.setTargetReference(targetRef.getEntry().getFileRef());
|
||||||
|
reply.setStatus(CREATED.value());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the file with the specified sourceReference from Alfresco Shared File Store
|
||||||
|
*
|
||||||
|
* @param sourceReference reference to the file in Alfresco Shared File Store
|
||||||
|
* @param sourceExtension default extension if the file in Alfresco Shared File Store has none
|
||||||
|
* @return the file containing the source content for the transformation
|
||||||
|
*/
|
||||||
|
private File loadSourceFile(final String sourceReference, final String sourceExtension)
|
||||||
|
{
|
||||||
|
ResponseEntity<Resource> responseEntity = alfrescoSharedFileStoreClient.retrieveFile(sourceReference);
|
||||||
|
|
||||||
|
HttpHeaders headers = responseEntity.getHeaders();
|
||||||
|
String filename = getFilenameFromContentDisposition(headers);
|
||||||
|
|
||||||
|
String extension = getFilenameExtension(filename) != null ? getFilenameExtension(filename) : sourceExtension;
|
||||||
|
MediaType contentType = headers.getContentType();
|
||||||
|
long size = headers.getContentLength();
|
||||||
|
|
||||||
|
final Resource body = responseEntity.getBody();
|
||||||
|
if (body == null)
|
||||||
|
{
|
||||||
|
String message = "Source file with reference: " + sourceReference + " is null or empty. "
|
||||||
|
+ "Transformation will fail and stop now as there is no content to be transformed.";
|
||||||
|
logger.warn(message);
|
||||||
|
throw new TransformException(BAD_REQUEST.value(), message);
|
||||||
|
}
|
||||||
|
final File file = createTempFile("source_", "." + extension);
|
||||||
|
|
||||||
|
logger.debug("Read source content {} length={} contentType={}",
|
||||||
|
sourceReference, size, contentType);
|
||||||
|
|
||||||
|
save(body, file);
|
||||||
|
LogEntry.setSource(filename, size);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String messageWithCause(final String prefix, Throwable e)
|
||||||
|
{
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(prefix).append(" - ")
|
||||||
|
.append(e.getClass().getSimpleName()).append(": ")
|
||||||
|
.append(e.getMessage());
|
||||||
|
|
||||||
|
while (e.getCause() != null)
|
||||||
|
{
|
||||||
|
e = e.getCause();
|
||||||
|
sb.append(", cause ")
|
||||||
|
.append(e.getClass().getSimpleName()).append(": ")
|
||||||
|
.append(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getTransformerName(long sourceSizeInBytes, final String sourceMimetype,
|
||||||
|
final String targetMimetype, final Map<String, String> transformOptions)
|
||||||
|
{
|
||||||
|
// The transformOptions always contains sourceEncoding when sent to a T-Engine, even though it should not be
|
||||||
|
// used to select a transformer. Similar to source and target mimetypes and extensions, but these are not
|
||||||
|
// passed in transformOptions.
|
||||||
|
String sourceEncoding = transformOptions.remove(SOURCE_ENCODING);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final String transformerName = transformRegistry.findTransformerName(sourceMimetype,
|
||||||
|
sourceSizeInBytes, targetMimetype, transformOptions, null);
|
||||||
|
if (transformerName == null)
|
||||||
|
{
|
||||||
|
throw new TransformException(BAD_REQUEST.value(), "No transforms were able to handle the request");
|
||||||
|
}
|
||||||
|
return transformerName;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (sourceEncoding != null)
|
||||||
|
{
|
||||||
|
transformOptions.put(SOURCE_ENCODING, sourceEncoding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CustomTransformer getCustomTransformer(String transformName)
|
||||||
|
{
|
||||||
|
CustomTransformer customTransformer = customTransformersByName.get(transformName);
|
||||||
|
if (customTransformer == null)
|
||||||
|
{
|
||||||
|
throw new TransformException(BAD_REQUEST.value(), "Custom Transformer "+customTransformer+" not found");
|
||||||
|
}
|
||||||
|
return customTransformer;
|
||||||
|
}
|
||||||
|
}
|
@@ -32,11 +32,9 @@ import org.alfresco.transform.base.clients.AlfrescoSharedFileStoreClient;
|
|||||||
import org.alfresco.transform.common.TransformerDebug;
|
import org.alfresco.transform.common.TransformerDebug;
|
||||||
import org.alfresco.transform.messages.TransformRequestValidator;
|
import org.alfresco.transform.messages.TransformRequestValidator;
|
||||||
import org.alfresco.transform.registry.TransformServiceRegistry;
|
import org.alfresco.transform.registry.TransformServiceRegistry;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.env.Environment;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
@@ -79,8 +77,6 @@ public class WebApplicationConfig implements WebMvcConfigurer
|
|||||||
return new TransformRequestValidator();
|
return new TransformRequestValidator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Autowired Environment env;
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public TransformServiceRegistry transformRegistry()
|
public TransformServiceRegistry transformRegistry()
|
||||||
{
|
{
|
||||||
|
@@ -26,35 +26,28 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.transform.base.fs;
|
package org.alfresco.transform.base.fs;
|
||||||
|
|
||||||
|
import org.alfresco.transform.base.logging.LogEntry;
|
||||||
|
import org.alfresco.transform.common.ExtensionService;
|
||||||
|
import org.alfresco.transform.common.TransformException;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
|
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
|
||||||
import static org.alfresco.transform.common.ExtensionService.getExtensionForMimetype;
|
import static org.alfresco.transform.common.ExtensionService.getExtensionForMimetype;
|
||||||
import static org.springframework.http.HttpHeaders.CONTENT_DISPOSITION;
|
import static org.springframework.http.HttpHeaders.CONTENT_DISPOSITION;
|
||||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||||
import static org.springframework.http.HttpStatus.INSUFFICIENT_STORAGE;
|
import static org.springframework.http.HttpStatus.INSUFFICIENT_STORAGE;
|
||||||
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
|
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
|
||||||
import static org.springframework.util.StringUtils.getFilename;
|
|
||||||
import static org.springframework.util.StringUtils.getFilenameExtension;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import org.alfresco.transform.common.ExtensionService;
|
|
||||||
import org.alfresco.transform.common.TransformException;
|
|
||||||
import org.alfresco.transform.base.logging.LogEntry;
|
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
import org.springframework.core.io.UrlResource;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
import org.springframework.web.util.UriUtils;
|
|
||||||
|
|
||||||
public class FileManager
|
public class FileManager
|
||||||
{
|
{
|
||||||
@@ -101,13 +94,6 @@ public class FileManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File buildFile(String filename)
|
|
||||||
{
|
|
||||||
filename = checkFilename(false, filename);
|
|
||||||
LogEntry.setTarget(filename);
|
|
||||||
return TempFileProvider.createTempFile("target_", "_" + filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void deleteFile(final File file) throws Exception
|
public static void deleteFile(final File file) throws Exception
|
||||||
{
|
{
|
||||||
if (!file.delete())
|
if (!file.delete())
|
||||||
@@ -116,32 +102,6 @@ public class FileManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String checkFilename(boolean source, String filename)
|
|
||||||
{
|
|
||||||
filename = getFilename(filename);
|
|
||||||
if (filename == null || filename.isEmpty())
|
|
||||||
{
|
|
||||||
String sourceOrTarget = source ? "source" : "target";
|
|
||||||
int statusCode = source ? BAD_REQUEST.value() : INTERNAL_SERVER_ERROR.value();
|
|
||||||
throw new TransformException(statusCode,
|
|
||||||
"The " + sourceOrTarget + " filename was not supplied");
|
|
||||||
}
|
|
||||||
return filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void save(MultipartFile multipartFile, File file)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Files.copy(multipartFile.getInputStream(), file.toPath(), REPLACE_EXISTING);
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
throw new TransformException(INSUFFICIENT_STORAGE.value(),
|
|
||||||
"Failed to store the source file", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void save(Resource body, File file)
|
public static void save(Resource body, File file)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -155,28 +115,6 @@ public class FileManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Resource load(File file)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Resource resource = new UrlResource(file.toURI());
|
|
||||||
if (resource.exists() || resource.isReadable())
|
|
||||||
{
|
|
||||||
return resource;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new TransformException(INTERNAL_SERVER_ERROR.value(),
|
|
||||||
"Could not read the target file: " + file.getPath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (MalformedURLException e)
|
|
||||||
{
|
|
||||||
throw new TransformException(INTERNAL_SERVER_ERROR.value(),
|
|
||||||
"The target filename was malformed: " + file.getPath(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getFilenameFromContentDisposition(HttpHeaders headers)
|
public static String getFilenameFromContentDisposition(HttpHeaders headers)
|
||||||
{
|
{
|
||||||
String filename = "";
|
String filename = "";
|
||||||
@@ -193,24 +131,6 @@ public class FileManager
|
|||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String createTargetFileName(final String fileName, String sourceMimetype, String targetMimetype)
|
|
||||||
{
|
|
||||||
String targetExtension = ExtensionService.getExtensionForTargetMimetype(targetMimetype, sourceMimetype);
|
|
||||||
final String sourceFilename = getFilename(fileName);
|
|
||||||
|
|
||||||
if (sourceFilename == null || sourceFilename.isEmpty())
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String ext = getFilenameExtension(sourceFilename);
|
|
||||||
if (ext == null || ext.isEmpty())
|
|
||||||
{
|
|
||||||
return sourceFilename + '.' + targetExtension;
|
|
||||||
}
|
|
||||||
return sourceFilename.substring(0, sourceFilename.length() - ext.length() - 1) + '.' + targetExtension;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static InputStream getMultipartFileInputStream(MultipartFile sourceMultipartFile)
|
public static InputStream getMultipartFileInputStream(MultipartFile sourceMultipartFile)
|
||||||
{
|
{
|
||||||
InputStream inputStream;
|
InputStream inputStream;
|
||||||
@@ -267,15 +187,6 @@ public class FileManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ResponseEntity<Resource> createAttachment(String targetFilename, File
|
|
||||||
targetFile)
|
|
||||||
{
|
|
||||||
Resource targetResource = load(targetFile);
|
|
||||||
targetFilename = UriUtils.encodePath(getFilename(targetFilename), "UTF-8");
|
|
||||||
return ResponseEntity.ok().header(CONTENT_DISPOSITION,
|
|
||||||
"attachment; filename*= UTF-8''" + targetFilename).body(targetResource);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TempFileProvider - Duplicated and adapted from alfresco-core.
|
* TempFileProvider - Duplicated and adapted from alfresco-core.
|
||||||
*/
|
*/
|
||||||
|
@@ -80,7 +80,6 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
import org.springframework.boot.test.mock.mockito.SpyBean;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
@@ -27,23 +27,10 @@
|
|||||||
|
|
||||||
package org.alfresco.transform.base;
|
package org.alfresco.transform.base;
|
||||||
|
|
||||||
import static org.mockito.Mockito.doReturn;
|
|
||||||
import static org.mockito.Mockito.doThrow;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
|
||||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
|
||||||
import static org.springframework.http.HttpStatus.CREATED;
|
|
||||||
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
|
|
||||||
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.Message;
|
|
||||||
|
|
||||||
import org.alfresco.transform.client.model.TransformReply;
|
|
||||||
import org.alfresco.transform.client.model.TransformRequest;
|
|
||||||
import org.alfresco.transform.base.messaging.TransformMessageConverter;
|
import org.alfresco.transform.base.messaging.TransformMessageConverter;
|
||||||
import org.alfresco.transform.base.messaging.TransformReplySender;
|
import org.alfresco.transform.base.messaging.TransformReplySender;
|
||||||
|
import org.alfresco.transform.client.model.TransformReply;
|
||||||
|
import org.alfresco.transform.client.model.TransformRequest;
|
||||||
import org.apache.activemq.command.ActiveMQObjectMessage;
|
import org.apache.activemq.command.ActiveMQObjectMessage;
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
import org.apache.activemq.command.ActiveMQQueue;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
@@ -55,10 +42,23 @@ import org.springframework.http.HttpStatus;
|
|||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.jms.support.converter.MessageConversionException;
|
import org.springframework.jms.support.converter.MessageConversionException;
|
||||||
|
|
||||||
|
import javax.jms.Destination;
|
||||||
|
import javax.jms.JMSException;
|
||||||
|
import javax.jms.Message;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
import static org.mockito.Mockito.doThrow;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
|
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||||
|
import static org.springframework.http.HttpStatus.CREATED;
|
||||||
|
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
|
||||||
|
|
||||||
public class QueueTransformServiceTest
|
public class QueueTransformServiceTest
|
||||||
{
|
{
|
||||||
@Mock
|
@Mock
|
||||||
private TransformController transformController;
|
private TransformHandler transformHandler;
|
||||||
@Mock
|
@Mock
|
||||||
private TransformMessageConverter transformMessageConverter;
|
private TransformMessageConverter transformMessageConverter;
|
||||||
@Mock
|
@Mock
|
||||||
@@ -78,7 +78,7 @@ public class QueueTransformServiceTest
|
|||||||
{
|
{
|
||||||
queueTransformService.receive(null);
|
queueTransformService.receive(null);
|
||||||
|
|
||||||
verifyNoMoreInteractions(transformController);
|
verifyNoMoreInteractions(transformHandler);
|
||||||
verifyNoMoreInteractions(transformMessageConverter);
|
verifyNoMoreInteractions(transformMessageConverter);
|
||||||
verifyNoMoreInteractions(transformReplySender);
|
verifyNoMoreInteractions(transformReplySender);
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,7 @@ public class QueueTransformServiceTest
|
|||||||
{
|
{
|
||||||
queueTransformService.receive(new ActiveMQObjectMessage());
|
queueTransformService.receive(new ActiveMQObjectMessage());
|
||||||
|
|
||||||
verifyNoMoreInteractions(transformController);
|
verifyNoMoreInteractions(transformHandler);
|
||||||
verifyNoMoreInteractions(transformMessageConverter);
|
verifyNoMoreInteractions(transformMessageConverter);
|
||||||
verifyNoMoreInteractions(transformReplySender);
|
verifyNoMoreInteractions(transformReplySender);
|
||||||
}
|
}
|
||||||
@@ -116,7 +116,7 @@ public class QueueTransformServiceTest
|
|||||||
verify(transformMessageConverter).fromMessage(msg);
|
verify(transformMessageConverter).fromMessage(msg);
|
||||||
verify(transformReplySender).send(destination, reply, msg.getCorrelationId());
|
verify(transformReplySender).send(destination, reply, msg.getCorrelationId());
|
||||||
|
|
||||||
verifyNoMoreInteractions(transformController);
|
verifyNoMoreInteractions(transformHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -143,7 +143,7 @@ public class QueueTransformServiceTest
|
|||||||
verify(transformMessageConverter).fromMessage(msg);
|
verify(transformMessageConverter).fromMessage(msg);
|
||||||
verify(transformReplySender).send(destination, reply, msg.getCorrelationId());
|
verify(transformReplySender).send(destination, reply, msg.getCorrelationId());
|
||||||
|
|
||||||
verifyNoMoreInteractions(transformController);
|
verifyNoMoreInteractions(transformHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -170,7 +170,7 @@ public class QueueTransformServiceTest
|
|||||||
verify(transformMessageConverter).fromMessage(msg);
|
verify(transformMessageConverter).fromMessage(msg);
|
||||||
verify(transformReplySender).send(destination, reply, msg.getCorrelationId());
|
verify(transformReplySender).send(destination, reply, msg.getCorrelationId());
|
||||||
|
|
||||||
verifyNoMoreInteractions(transformController);
|
verifyNoMoreInteractions(transformHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -188,12 +188,12 @@ public class QueueTransformServiceTest
|
|||||||
|
|
||||||
doReturn(request).when(transformMessageConverter).fromMessage(msg);
|
doReturn(request).when(transformMessageConverter).fromMessage(msg);
|
||||||
doReturn(new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus())))
|
doReturn(new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus())))
|
||||||
.when(transformController).transform(request, null);
|
.when(transformHandler).handleMessageRequest(request, null);
|
||||||
|
|
||||||
queueTransformService.receive(msg);
|
queueTransformService.receive(msg);
|
||||||
|
|
||||||
verify(transformMessageConverter).fromMessage(msg);
|
verify(transformMessageConverter).fromMessage(msg);
|
||||||
verify(transformController).transform(request, null);
|
verify(transformHandler).handleMessageRequest(request, null);
|
||||||
verify(transformReplySender).send(destination, reply);
|
verify(transformReplySender).send(destination, reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +206,7 @@ public class QueueTransformServiceTest
|
|||||||
|
|
||||||
queueTransformService.receive(msg);
|
queueTransformService.receive(msg);
|
||||||
|
|
||||||
verifyNoMoreInteractions(transformController);
|
verifyNoMoreInteractions(transformHandler);
|
||||||
verifyNoMoreInteractions(transformMessageConverter);
|
verifyNoMoreInteractions(transformMessageConverter);
|
||||||
verifyNoMoreInteractions(transformReplySender);
|
verifyNoMoreInteractions(transformReplySender);
|
||||||
}
|
}
|
||||||
@@ -229,12 +229,12 @@ public class QueueTransformServiceTest
|
|||||||
|
|
||||||
doReturn(request).when(transformMessageConverter).fromMessage(msg);
|
doReturn(request).when(transformMessageConverter).fromMessage(msg);
|
||||||
doReturn(new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus())))
|
doReturn(new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus())))
|
||||||
.when(transformController).transform(request, null);
|
.when(transformHandler).handleMessageRequest(request, null);
|
||||||
|
|
||||||
queueTransformService.receive(msg);
|
queueTransformService.receive(msg);
|
||||||
|
|
||||||
verify(transformMessageConverter).fromMessage(msg);
|
verify(transformMessageConverter).fromMessage(msg);
|
||||||
verify(transformController).transform(request, null);
|
verify(transformHandler).handleMessageRequest(request, null);
|
||||||
verify(transformReplySender).send(destination, reply);
|
verify(transformReplySender).send(destination, reply);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -34,13 +34,10 @@ import org.alfresco.transform.config.TransformConfig;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.alfresco.transform.base.logging.StandardMessages.COMMUNITY_LICENCE;
|
import static org.alfresco.transform.base.logging.StandardMessages.COMMUNITY_LICENCE;
|
||||||
import static org.alfresco.transform.common.Mimetype.MIMETYPE_HTML;
|
import static org.alfresco.transform.common.Mimetype.MIMETYPE_HTML;
|
||||||
import static org.alfresco.transform.common.Mimetype.MIMETYPE_PDF;
|
|
||||||
import static org.alfresco.transform.common.Mimetype.MIMETYPE_TEXT_PLAIN;
|
import static org.alfresco.transform.common.Mimetype.MIMETYPE_TEXT_PLAIN;
|
||||||
import static org.alfresco.transform.common.RequestParamMap.SOURCE_ENCODING;
|
import static org.alfresco.transform.common.RequestParamMap.SOURCE_ENCODING;
|
||||||
|
|
||||||
|
@@ -38,7 +38,6 @@ import java.util.Collections;
|
|||||||
import static org.alfresco.transform.base.logging.StandardMessages.COMMUNITY_LICENCE;
|
import static org.alfresco.transform.base.logging.StandardMessages.COMMUNITY_LICENCE;
|
||||||
import static org.alfresco.transform.common.Mimetype.MIMETYPE_IMAGE_PNG;
|
import static org.alfresco.transform.common.Mimetype.MIMETYPE_IMAGE_PNG;
|
||||||
import static org.alfresco.transform.common.Mimetype.MIMETYPE_PDF;
|
import static org.alfresco.transform.common.Mimetype.MIMETYPE_PDF;
|
||||||
import static org.alfresco.transform.common.Mimetype.MIMETYPE_TEXT_PLAIN;
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class PdfRendererTransformEngine implements TransformEngine
|
public class PdfRendererTransformEngine implements TransformEngine
|
||||||
|
Reference in New Issue
Block a user