feature/ATS-16

This commit is contained in:
Lucian Tuca
2018-08-17 09:32:25 +01:00
parent c4ca88d876
commit dda632c7a5
22 changed files with 983 additions and 145 deletions

View File

@@ -111,6 +111,65 @@ public class AlfrescoPdfRendererController extends AbstractTransformerController
}
~~~
* *TransformerName*Controller#processTransform(File sourceFile, File targetFile, Map<String, String> transformOptions, Long timeout)
### /transform (Consumes: `application/json`, Produces: `application/json`)
The new *consumes* and *produces* arguments have been specified in order to differentiate this endpoint from the previous one (which **consumes** `multipart/form-data`)
The endpoint should **always** receive a `TransformationRequest` and should **always** respond with a `TransformationReply`.
As specific transformers require specific arguments (e.g. `transform` for the **Tika transformer**) the request body should include this in the `transformRequestOptions` via the `Map<String,String> transformRequestOptions`.
**Example request body**
```javascript
var transformRequest = {
"requestId": "1",
"sourceReference": "2f9ed237-c734-4366-8c8b-6001819169a4",
"sourceMediaType": "pdf",
"sourceSize": 123456,
"sourceExtension": "pdf",
"targetMediaType": "txt",
"targetExtension": "txt",
"clientType": "ACS",
"clientData": "Yo No Soy Marinero, Soy Capitan, Soy Capitan!",
"schema": 1,
"transformRequestOptions": {
"targetMimetype": "text/plain",
"targetEncoding": "UTF-8",
"transform": "PdfBox"
}
}
```
**Example response body**
```javascript
var transformReply = {
"requestId": "1",
"status": 201,
"errorDetails": null,
"sourceReference": "2f9ed237-c734-4366-8c8b-6001819169a4",
"targetReference": "34d69ff0-7eaa-4741-8a9f-e1915e6995bf",
"clientType": "ACS",
"clientData": "Yo No Soy Marinero, Soy Capitan, Soy Capitan!",
"schema": 1
}
```
### processTransform method
```java
public abstract class AbstractTransformerController
{
void processTransform(File sourceFile, File targetFile, Map<String, String> transformOptions, Long timeout) { /* Perform the transformation*/ }
}
```
The **abstract** method is declared in the *AbstractTransformerController* and must be implemented by the specific controllers.
This method is called by the *AbstractTransformerController* directly in the **new** `/transform` endpoint which **consumes** `application/json` and **produces** `application/json`.
The method is responsible for performing the transformation. Upon a **successful** transformation it updates the `targetFile` parameter.
* Application.java - [Spring Boot](https://projects.spring.io/spring-boot/) expects to find an Application in
a project's source files. The following may be used:

View File

@@ -26,6 +26,10 @@
<groupId>org.alfresco</groupId>
<artifactId>alfresco-core</artifactId>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-transform-data-model</artifactId>
</dependency>
</dependencies>
<build>

View File

@@ -25,34 +25,52 @@
*/
package org.alfresco.transformer;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.StringJoiner;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.transform.client.model.TransformReply;
import org.alfresco.transform.client.model.TransformRequest;
import org.alfresco.transformer.model.FileRefResponse;
import org.alfresco.util.TempFileProvider;
import org.alfresco.util.exec.RuntimeExec;
import org.apache.commons.logging.Log;
import org.springframework.beans.TypeMismatchException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.UriUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.*;
/**
* <p>Abstract Controller, provides structure and helper methods to sub-class transformer controllers.</p>
*
@@ -85,6 +103,10 @@ public abstract class AbstractTransformerController
{
public static final String SOURCE_FILE = "sourceFile";
public static final String TARGET_FILE = "targetFile";
public static final String FILENAME = "filename=";
@Autowired
private AlfrescoSharedFileStoreClient alfrescoSharedFileStoreClient;
protected static Log logger;
@@ -115,6 +137,125 @@ public abstract class AbstractTransformerController
protected abstract String getTransformerName();
/**
* '/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 older one, which produces 'html'
*
* @param transformRequest The transformation request
* @param timeout Transformation timeout
* @return A transformation reply
*/
@PostMapping(value = "/transform", produces = APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<TransformReply> transform(@RequestBody TransformRequest transformRequest,
@RequestParam(value = "timeout", required = false) Long timeout)
{
TransformReply transformReply = new TransformReply();
transformReply.setRequestId(transformRequest.getRequestId());
transformReply.setSourceReference(transformRequest.getSourceReference());
transformReply.setSchema(transformRequest.getSchema());
transformReply.setClientData(transformRequest.getClientData());
// Load the source file
File sourceFile;
try
{
sourceFile = loadSourceFile(transformRequest.getSourceReference());
}
catch (TransformException te)
{
transformReply.setStatus(te.getStatusCode());
transformReply
.setErrorDetails("Failed at reading the source file. " + te.getMessage());
return new ResponseEntity<>(transformReply, HttpStatus.valueOf(transformReply.getStatus()));
}
catch (HttpClientErrorException hcee)
{
transformReply.setStatus(hcee.getStatusCode().value());
transformReply
.setErrorDetails("Failed at reading the source file. " + hcee.getMessage());
return new ResponseEntity<>(transformReply, HttpStatus.valueOf(transformReply.getStatus()));
}
catch (Exception e)
{
transformReply.setStatus(500);
transformReply.setErrorDetails("Failed at reading the source file. " + e.getMessage());
return new ResponseEntity<>(transformReply, HttpStatus.valueOf(transformReply.getStatus()));
}
// Create local temp target file in order to run the transformation
String targetFilename = createTargetFileName(sourceFile.getName(),
transformRequest.getTargetExtension());
File targetFile = buildFile(targetFilename);
// Run the transformation
try
{
processTransform(sourceFile, targetFile,
transformRequest.getTransformationRequestOptions(), timeout);
}
catch (TransformException te)
{
transformReply.setStatus(te.getStatusCode());
transformReply
.setErrorDetails("Failed at processing transformation. " + te.getMessage());
return new ResponseEntity<>(transformReply, HttpStatus.valueOf(transformReply.getStatus()));
}
catch (Exception e)
{
transformReply.setStatus(500);
transformReply
.setErrorDetails("Failed at processing transformation. " + e.getMessage());
return new ResponseEntity<>(transformReply, HttpStatus.valueOf(transformReply.getStatus()));
}
// Write the target file
FileRefResponse targetRef;
try
{
targetRef = alfrescoSharedFileStoreClient.saveFile(targetFile);
}
catch (TransformException te)
{
transformReply.setStatus(te.getStatusCode());
transformReply
.setErrorDetails("Failed at writing the transformed file. " + te.getMessage());
return new ResponseEntity<>(transformReply, HttpStatus.valueOf(transformReply.getStatus()));
}
catch (HttpClientErrorException hcee)
{
transformReply.setStatus(hcee.getStatusCode().value());
transformReply
.setErrorDetails("Failed at writing the transformed file. " + hcee.getMessage());
return new ResponseEntity<>(transformReply, HttpStatus.valueOf(transformReply.getStatus()));
}
catch (Exception e)
{
transformReply.setStatus(500);
transformReply
.setErrorDetails("Failed at writing the transformed file. " + e.getMessage());
return new ResponseEntity<>(transformReply, HttpStatus.valueOf(transformReply.getStatus()));
}
transformReply.setTargetReference(targetRef.getEntry().getFileRef());
transformReply.setStatus(HttpStatus.CREATED.value());
return new ResponseEntity<>(transformReply, HttpStatus.valueOf(transformReply.getStatus()));
}
protected abstract void processTransform(File sourceFile, File targetFile,
Map<String, String> transformOptions, Long timeout);
@RequestMapping("/version")
@ResponseBody
protected String version()
@@ -269,10 +410,71 @@ public abstract class AbstractTransformerController
// return errorAttributes;
// }
protected String createTargetFileName(MultipartFile sourceMultipartFile, String targetExtension)
/**
* Loads the file with the specified sourceReference from Alfresco Shared File Store
*
* @param sourceReference reference to the file in Alfresco Shared File Store
* @return the file containing the source content for the transformation
*/
protected File loadSourceFile(String sourceReference)
{
ResponseEntity<Resource> responseEntity = alfrescoSharedFileStoreClient
.retrieveFile(sourceReference);
getProbeTestTransformInternal().incrementTransformerCount();
HttpHeaders headers = responseEntity.getHeaders();
String filename = getFilenameFromContentDisposition(headers);
String extension = StringUtils.getFilenameExtension(filename);
MediaType contentType = headers.getContentType();
long size = headers.getContentLength();
Resource body = responseEntity.getBody();
File file = TempFileProvider.createTempFile("source_", "." + extension);
if (logger.isDebugEnabled())
{
logger.debug(
"Read source content " + sourceReference + " length="
+ size + " contentType=" + contentType);
}
save(body, file);
LogEntry.setSource(filename, size);
return file;
}
private String getFilenameFromContentDisposition(HttpHeaders headers)
{
String filename = "";
String contentDisposition = headers.getFirst(HttpHeaders.CONTENT_DISPOSITION);
if (contentDisposition != null)
{
String[] strings = contentDisposition.split("; *");
for (String string: strings)
{
if (string.startsWith(FILENAME))
{
filename = string.substring(FILENAME.length());
break;
}
}
}
return filename;
}
/**
* Returns the file name for the target file
*
* @param fileName Desired file name
* @param targetExtension File extension
* @return Target file name
*/
protected String createTargetFileName(String fileName, String targetExtension)
{
String targetFilename = null;
String sourceFilename = sourceMultipartFile.getOriginalFilename();
String sourceFilename = fileName;
sourceFilename = StringUtils.getFilename(sourceFilename);
if (sourceFilename != null && !sourceFilename.isEmpty())
{
@@ -317,13 +519,18 @@ public abstract class AbstractTransformerController
*/
protected File createTargetFile(HttpServletRequest request, String filename)
{
filename = checkFilename( false, filename);
LogEntry.setTarget(filename);
File file = TempFileProvider.createTempFile("target_", "_" + filename);
File file = buildFile(filename);
request.setAttribute(TARGET_FILE, file);
return file;
}
private File buildFile(String filename)
{
filename = checkFilename( false, filename);
LogEntry.setTarget(filename);
return TempFileProvider.createTempFile("target_", "_" + filename);
}
/**
* Checks the filename is okay to uses in a temporary file name.
*
@@ -355,6 +562,20 @@ public abstract class AbstractTransformerController
}
}
private void save(Resource body, File file)
{
try
{
InputStream inputStream = body == null ? null : body.getInputStream();
Files.copy(inputStream, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
catch (IOException e)
{
throw new TransformException(507, "Failed to store the source file", e);
}
}
private Resource load(File file)
{
try
@@ -491,4 +712,37 @@ public abstract class AbstractTransformerController
throw new TransformException(500, "Filename encoding error", e);
}
}
/**
* Safely converts a {@link String} to an {@link Integer}
*
* @param param String to be converted
* @return Null if param is null or converted value as {@link Integer}
*/
protected Integer stringToInteger(String param)
{
return param == null ? null : Integer.parseInt(param);
}
/**
* Safely converts a {@link String} to an {@link Integer}
*
* @param param String to be converted
* @return Null if param is null or converted value as {@link Boolean}
*/
protected Boolean stringToBoolean(String param)
{
return param == null? null : Boolean.parseBoolean(param);
}
public AlfrescoSharedFileStoreClient getAlfrescoSharedFileStoreClient()
{
return alfrescoSharedFileStoreClient;
}
public void setAlfrescoSharedFileStoreClient(
AlfrescoSharedFileStoreClient alfrescoSharedFileStoreClient)
{
this.alfrescoSharedFileStoreClient = alfrescoSharedFileStoreClient;
}
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright 2005-2018 Alfresco Software, Ltd. All rights reserved.
*
* License rights for this program may be obtained from Alfresco Software, Ltd.
* pursuant to a written agreement and any use of this program without such an
* agreement is prohibited.
*/
package org.alfresco.transformer;
import java.io.File;
import org.alfresco.transformer.model.FileRefResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
/**
* Simple Rest client that call Alfresco Shared File Store
*/
public class AlfrescoSharedFileStoreClient
{
@Value("${fileStoreUrl}")
private String fileStoreUrl;
@Autowired
private RestTemplate restTemplate;
/**
* Retrieves a file from Shared File Store using given file reference
*
* @param fileRef File reference
* @return ResponseEntity<Resource>
*/
public ResponseEntity<Resource> retrieveFile(String fileRef)
{
try
{
return restTemplate.getForEntity(fileStoreUrl + "/" + fileRef,
org.springframework.core.io.Resource.class);
}
catch (HttpClientErrorException e)
{
throw new TransformException(e.getStatusCode().value(), e.getMessage(), e);
}
}
/**
* Stores given file in Shared File Store
*
* @param file File to be stored
* @return A FileRefResponse containing detail about file's reference
*/
public FileRefResponse saveFile(File file)
{
try
{
FileSystemResource value = new FileSystemResource(file.getAbsolutePath());
LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("file", value);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map,
headers);
ResponseEntity<FileRefResponse> responseEntity = restTemplate
.exchange(fileStoreUrl, HttpMethod.POST, requestEntity, FileRefResponse.class);
return responseEntity.getBody();
}
catch (HttpClientErrorException e)
{
throw new TransformException(e.getStatusCode().value(), e.getMessage(), e);
}
}
}

View File

@@ -35,4 +35,5 @@ public class Application
{
SpringApplication.run(Application.class, args);
}
}

View File

@@ -27,6 +27,7 @@ package org.alfresco.transformer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@@ -42,4 +43,16 @@ public class WebApplicationConfig extends WebMvcConfigurerAdapter {
public TransformInterceptor transformInterceptor() {
return new TransformInterceptor();
}
@Bean
public RestTemplate restTemplate()
{
return new RestTemplate();
}
@Bean
public AlfrescoSharedFileStoreClient alfrescoSharedFileStoreClient(){
return new AlfrescoSharedFileStoreClient();
}
}

View File

@@ -0,0 +1,57 @@
package org.alfresco.transformer.model;
import java.util.Objects;
/**
* TODO: Copied from org.alfresco.store.entity (alfresco-shared-file-store). To be discussed
*
* POJO that represents content reference ({@link java.util.UUID})
*/
public class FileRefEntity
{
private String fileRef;
public FileRefEntity()
{
}
public FileRefEntity(String fileRef)
{
this.fileRef = fileRef;
}
public void setFileRef(String fileRef){
this.fileRef = fileRef;
}
public String getFileRef()
{
return fileRef;
}
@Override
public String toString()
{
return fileRef;
}
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
FileRefEntity fileRef = (FileRefEntity) o;
return Objects.equals(this.fileRef, fileRef.fileRef);
}
@Override
public int hashCode()
{
return Objects.hash(fileRef);
}
}

View File

@@ -0,0 +1,30 @@
package org.alfresco.transformer.model;
/**
* TODO: Copied from org.alfresco.store.entity (alfresco-shared-file-store). To be discussed
*
* POJO that describes the ContentRefEntry response, contains {@link FileRefEntity} according to API spec
*/
public class FileRefResponse
{
private FileRefEntity entry;
public FileRefResponse()
{
}
public FileRefResponse(FileRefEntity entry)
{
this.entry = entry;
}
public FileRefEntity getEntry()
{
return entry;
}
public void setEntry(FileRefEntity entry)
{
this.entry = entry;
}
}

View File

@@ -1,10 +0,0 @@
spring.http.multipart.max-file-size=8192MB
spring.http.multipart.max-request-size=8192MB
server.port = 8090
#logging.level.org.alfresco.util.exec.RuntimeExec=debug
logging.level.org.alfresco.transformer.LibreOfficeController=debug
logging.level.org.alfresco.transformer.JodConverterSharedInstance=debug
logging.level.org.alfresco.transformer.AlfrescoPdfRendererController=debug
logging.level.org.alfresco.transformer.ImageMagickController=debug
logging.level.org.alfresco.transformer.TikaController=debug

View File

@@ -0,0 +1,19 @@
spring:
http:
multipart:
max-file-size: 8192MB
max-request-size: 8192MB
server:
port: 8090
logging:
level:
#org.alfresco.util.exec.RuntimeExec: debug
org.alfresco.transformer.LibreOfficeController: debug
org.alfresco.transformer.JodConverterSharedInstance: debug
org.alfresco.transformer.AlfrescoPdfRendererController: debug
org.alfresco.transformer.ImageMagickController: debug
org.alfresco.transformer.TikaController: debug
fileStoreUrl: ${FILE_STORE_URL:http://localhost:8099/alfresco/api/-default-/private/sfs/versions/1/file}

View File

@@ -25,30 +25,54 @@
*/
package org.alfresco.transformer;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.alfresco.transform.client.model.TransformReply;
import org.alfresco.transform.client.model.TransformRequest;
import org.alfresco.transformer.model.FileRefEntity;
import org.alfresco.transformer.model.FileRefResponse;
import org.alfresco.util.exec.RuntimeExec;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
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.mock.web.MockMultipartFile;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.util.StringUtils;
import java.io.*;
import java.net.URL;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Map;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.*;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Super class for testing controllers without a server. Includes tests for the AbstractTransformerController itself.
@@ -58,12 +82,18 @@ public abstract class AbstractTransformerControllerTest
@Autowired
protected MockMvc mockMvc;
@Autowired
protected ObjectMapper objectMapper;
@Mock
private RuntimeExec mockTransformCommand;
@Mock
private RuntimeExec mockCheckCommand;
@Mock
protected AlfrescoSharedFileStoreClient alfrescoSharedFileStoreClient;
@Mock
private RuntimeExec.ExecutionResult mockExecutionResult;
@@ -80,6 +110,11 @@ public abstract class AbstractTransformerControllerTest
protected AbstractTransformerController controller;
@Before
public void before() throws Exception
{
}
// Called by sub class
public void mockTransformCommand(AbstractTransformerController controller, String sourceExtension,
String targetExtension, String sourceMimetype,
@@ -109,6 +144,7 @@ public abstract class AbstractTransformerControllerTest
String actualOptions = actualProperties.get("options");
String actualSource = actualProperties.get("source");
String actualTarget = actualProperties.get("target");
String actualTargetExtension = StringUtils.getFilenameExtension(actualTarget);
assertNotNull(actualSource);
assertNotNull(actualTarget);
@@ -137,13 +173,9 @@ public abstract class AbstractTransformerControllerTest
{
String testFilename = actualTarget.substring(i+1);
File testFile = getTestFile(testFilename, false);
if (testFile != null)
{
File targetFile = new File(actualTarget);
FileChannel source = new FileInputStream(testFile).getChannel();
FileChannel target = new FileOutputStream(targetFile).getChannel();
target.transferFrom(source, 0, source.size());
}
File targetFile = new File(actualTarget);
generateTargetFileFromResourceFile(actualTargetExtension, testFile,
targetFile);
}
// Check the supplied source file has not been changed.
@@ -159,6 +191,37 @@ public abstract class AbstractTransformerControllerTest
when(mockExecutionResult.getStdOut()).thenReturn("STDOUT");
}
/**
* This method ends up being the core of the mock.
* It copies content from an existing file in the resources folder to the desired location
* in order to simulate a successful transformation.
*
* @param actualTargetExtension Requested extension.
* @param testFile The test file (transformed) - basically the result.
* @param targetFile The location where the content from the testFile should be copied
* @throws IOException in case of any errors.
*/
void generateTargetFileFromResourceFile(String actualTargetExtension, File testFile,
File targetFile) throws IOException
{
if (testFile != null)
{
FileChannel source = new FileInputStream(testFile).getChannel();
FileChannel target = new FileOutputStream(targetFile).getChannel();
target.transferFrom(source, 0, source.size());
}
else
{
testFile = getTestFile("quick." + actualTargetExtension, false);
if (testFile != null)
{
FileChannel source = new FileInputStream(testFile).getChannel();
FileChannel target = new FileOutputStream(targetFile).getChannel();
target.transferFrom(source, 0, source.size());
}
}
}
protected byte[] readTestFile(String extension) throws IOException
{
return Files.readAllBytes(getTestFile("quick."+extension, true).toPath());
@@ -329,4 +392,60 @@ public abstract class AbstractTransformerControllerTest
assertEquals("", expectedMaxTime, probeTestTransform.maxTime);
}
}
@Test
public void testPojoTransform() throws Exception
{
// Files
String sourceFileRef = UUID.randomUUID().toString();
File sourceFile = getTestFile("quick." + sourceExtension, true);
String targetFileRef = UUID.randomUUID().toString();
// Transformation Request POJO
TransformRequest transformRequest = new TransformRequest();
transformRequest.setRequestId("1");
transformRequest.setSchema(1);
transformRequest.setClientData("Alfresco Digital Business Platform");
transformRequest.setTransformationRequestOptions(new HashMap<>());
transformRequest.setSourceReference(sourceFileRef);
transformRequest.setSourceExtension(sourceExtension);
// TODO: ATS-53
transformRequest.setSourceMediaType("TODO");
transformRequest.setSourceSize(sourceFile.length());
transformRequest.setTargetExtension(targetExtension);
transformRequest.setTargetMediaType("TODO");
// HTTP Request
HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=quick." + sourceExtension);
ResponseEntity<Resource> response = new ResponseEntity<>(new FileSystemResource(
sourceFile), headers, HttpStatus.OK);
when(alfrescoSharedFileStoreClient.retrieveFile(sourceFileRef)).thenReturn(response);
when(alfrescoSharedFileStoreClient.saveFile(any())).thenReturn(new FileRefResponse(new FileRefEntity(targetFileRef)));
when(mockExecutionResult.getExitValue()).thenReturn(0);
// Update the Transformation Request with any specific params before sending it
updateTransformRequestWithSpecificOptions(transformRequest);
// Serialize and call the transformer
String tr = objectMapper.writeValueAsString(transformRequest);
String transformationReplyAsString = mockMvc.perform(MockMvcRequestBuilders.post("/transform")
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).content(tr))
.andExpect(status().is(HttpStatus.CREATED.value()))
.andReturn().getResponse().getContentAsString();
TransformReply transformReply = objectMapper.readValue(transformationReplyAsString, TransformReply.class);
// Assert the reply
assertEquals(transformRequest.getRequestId(), transformReply.getRequestId());
assertEquals(transformRequest.getClientData(), transformReply.getClientData());
assertEquals(transformRequest.getSchema(), transformReply.getSchema());
}
protected abstract void updateTransformRequestWithSpecificOptions(TransformRequest transformRequest);
}