From dda632c7a594251e668f0c41b1d4afffae95991f Mon Sep 17 00:00:00 2001 From: Lucian Tuca Date: Fri, 17 Aug 2018 09:32:25 +0100 Subject: [PATCH] feature/ATS-16 --- .../AlfrescoPdfRendererController.java | 61 +++- .../AlfrescoPdfRendererControllerTest.java | 20 +- .../transformer/ImageMagickController.java | 121 +++++--- .../ImageMagickControllerTest.java | 21 +- .../transformer/LibreOfficeController.java | 23 +- .../LibreOfficeControllerTest.java | 49 +-- .../alfresco/transformer/TikaController.java | 43 ++- .../transformer/TikaControllerTest.java | 64 +++- .../transformer/TikaHttpRequestTest.java | 2 +- .../src/test/resources/quick.pdf | Bin 0 -> 23697 bytes alfresco-transformer-base/README.md | 59 ++++ alfresco-transformer-base/pom.xml | 4 + .../AbstractTransformerController.java | 284 +++++++++++++++++- .../AlfrescoSharedFileStoreClient.java | 82 +++++ .../org/alfresco/transformer/Application.java | 1 + .../transformer/WebApplicationConfig.java | 13 + .../transformer/model/FileRefEntity.java | 57 ++++ .../transformer/model/FileRefResponse.java | 30 ++ .../src/main/resources/application.properties | 10 - .../src/main/resources/application.yaml | 19 ++ .../AbstractTransformerControllerTest.java | 159 ++++++++-- pom.xml | 6 + 22 files changed, 983 insertions(+), 145 deletions(-) create mode 100644 alfresco-docker-tika/src/test/resources/quick.pdf create mode 100644 alfresco-transformer-base/src/main/java/org/alfresco/transformer/AlfrescoSharedFileStoreClient.java create mode 100644 alfresco-transformer-base/src/main/java/org/alfresco/transformer/model/FileRefEntity.java create mode 100644 alfresco-transformer-base/src/main/java/org/alfresco/transformer/model/FileRefResponse.java delete mode 100644 alfresco-transformer-base/src/main/resources/application.properties create mode 100644 alfresco-transformer-base/src/main/resources/application.yaml diff --git a/alfresco-docker-alfresco-pdf-renderer/src/main/java/org/alfresco/transformer/AlfrescoPdfRendererController.java b/alfresco-docker-alfresco-pdf-renderer/src/main/java/org/alfresco/transformer/AlfrescoPdfRendererController.java index b2fc1ef1..ab7a230b 100644 --- a/alfresco-docker-alfresco-pdf-renderer/src/main/java/org/alfresco/transformer/AlfrescoPdfRendererController.java +++ b/alfresco-docker-alfresco-pdf-renderer/src/main/java/org/alfresco/transformer/AlfrescoPdfRendererController.java @@ -11,22 +11,24 @@ */ package org.alfresco.transformer; +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.StringJoiner; + +import javax.servlet.http.HttpServletRequest; + import org.alfresco.util.exec.RuntimeExec; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; -import javax.servlet.http.HttpServletRequest; -import java.io.File; -import java.util.HashMap; -import java.util.Map; -import java.util.StringJoiner; - /** * Controller for the Docker based alfresco-pdf-renderer transformer. * @@ -111,7 +113,35 @@ public class AlfrescoPdfRendererController extends AbstractTransformerController }; } - @PostMapping("/transform") + @Override + protected void processTransform(File sourceFile, File targetFile, + Map transformOptions, Long timeout) + { + String page = transformOptions.get("page"); + Integer pageOption = page == null ? null : Integer.parseInt(page); + + String width = transformOptions.get("width"); + Integer widthOption = width == null ? null : Integer.parseInt(width); + + String height = transformOptions.get("height"); + Integer heightOption = height == null ? null : Integer.parseInt(height); + + String allowEnlargement = transformOptions.get("allowEnlargement"); + Boolean allowEnlargementOption = + allowEnlargement == null ? null : Boolean.parseBoolean(allowEnlargement); + + String maintainAspectRatio = transformOptions.get("maintainAspectRatio"); + Boolean maintainAspectRatioOption = + maintainAspectRatio == null ? null : Boolean.parseBoolean(maintainAspectRatio); + + String options = buildTransformOptions(pageOption, widthOption, heightOption, + allowEnlargementOption, maintainAspectRatioOption); + + executeTransformCommand(options, sourceFile, targetFile, timeout); + } + + @Deprecated + @PostMapping(value = "/transform", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity transform(HttpServletRequest request, @RequestParam("file") MultipartFile sourceMultipartFile, @RequestParam("targetExtension") String targetExtension, @@ -124,11 +154,21 @@ public class AlfrescoPdfRendererController extends AbstractTransformerController @RequestParam(value = "allowEnlargement", required = false) Boolean allowEnlargement, @RequestParam(value = "maintainAspectRatio", required = false) Boolean maintainAspectRatio) { - String targetFilename = createTargetFileName(sourceMultipartFile, targetExtension); + String targetFilename = createTargetFileName(sourceMultipartFile.getOriginalFilename(), targetExtension); File sourceFile = createSourceFile(request, sourceMultipartFile); File targetFile = createTargetFile(request, targetFilename); // Both files are deleted by TransformInterceptor.afterCompletion + String options = buildTransformOptions(page, width, height, allowEnlargement, + maintainAspectRatio); + executeTransformCommand(options, sourceFile, targetFile, timeout); + + return createAttachment(targetFilename, targetFile, testDelay); + } + + + public String buildTransformOptions(Integer page,Integer width,Integer height,Boolean allowEnlargement,Boolean maintainAspectRatio) + { StringJoiner args = new StringJoiner(" "); if (width != null && width >= 0) { @@ -150,9 +190,6 @@ public class AlfrescoPdfRendererController extends AbstractTransformerController { args.add("--page=" + page); } - String options = args.toString(); - executeTransformCommand(options, sourceFile, targetFile, timeout); - - return createAttachment(targetFilename, targetFile, testDelay); + return args.toString(); } } diff --git a/alfresco-docker-alfresco-pdf-renderer/src/test/java/org/alfresco/transformer/AlfrescoPdfRendererControllerTest.java b/alfresco-docker-alfresco-pdf-renderer/src/test/java/org/alfresco/transformer/AlfrescoPdfRendererControllerTest.java index 6b2dc12c..e65aad03 100644 --- a/alfresco-docker-alfresco-pdf-renderer/src/test/java/org/alfresco/transformer/AlfrescoPdfRendererControllerTest.java +++ b/alfresco-docker-alfresco-pdf-renderer/src/test/java/org/alfresco/transformer/AlfrescoPdfRendererControllerTest.java @@ -25,6 +25,11 @@ */ package org.alfresco.transformer; +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 org.alfresco.transform.client.model.TransformRequest; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -33,10 +38,6 @@ import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import java.io.IOException; - -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; - /** * Test the AlfrescoPdfRendererController without a server. * Super class includes tests for the AbstractTransformerController. @@ -49,8 +50,10 @@ public class AlfrescoPdfRendererControllerTest extends AbstractTransformerContro private AlfrescoPdfRendererController controller; @Before - public void before() throws IOException + public void before() throws Exception { + controller.setAlfrescoSharedFileStoreClient(alfrescoSharedFileStoreClient); + super.controller = controller; super.mockTransformCommand(controller, "pdf", "png", "application/pdf", true); } @@ -93,4 +96,11 @@ public class AlfrescoPdfRendererControllerTest extends AbstractTransformerContro .andExpect(content().bytes(expectedTargetFileBytes)) .andExpect(header().string("Content-Disposition", "attachment; filename*= UTF-8''quick."+targetExtension)); } + + @Override + protected void updateTransformRequestWithSpecificOptions(TransformRequest transformRequest) + { + transformRequest.setSourceExtension("pdf"); + transformRequest.setTargetExtension("png"); + } } diff --git a/alfresco-docker-imagemagick/src/main/java/org/alfresco/transformer/ImageMagickController.java b/alfresco-docker-imagemagick/src/main/java/org/alfresco/transformer/ImageMagickController.java index ef493414..87aee38f 100644 --- a/alfresco-docker-imagemagick/src/main/java/org/alfresco/transformer/ImageMagickController.java +++ b/alfresco-docker-imagemagick/src/main/java/org/alfresco/transformer/ImageMagickController.java @@ -11,20 +11,26 @@ */ package org.alfresco.transformer; +import java.io.File; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringJoiner; + +import javax.servlet.http.HttpServletRequest; + import org.alfresco.util.exec.RuntimeExec; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; -import javax.servlet.http.HttpServletRequest; -import java.io.File; -import java.util.*; - /** * Controller for the Docker based ImageMagick transformer. * @@ -121,7 +127,7 @@ public class ImageMagickController extends AbstractTransformerController }; } - @PostMapping("/transform") + @PostMapping(value = "/transform", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity transform(HttpServletRequest request, @RequestParam("file") MultipartFile sourceMultipartFile, @RequestParam("targetExtension") String targetExtension, @@ -159,6 +165,68 @@ public class ImageMagickController extends AbstractTransformerController // ACS 6.0, this is relatively safe as it requires an AMP to be installed // which supplies the commandOptions. @RequestParam(value = "commandOptions", required = false) String commandOptions) + { + String targetFilename = createTargetFileName(sourceMultipartFile.getOriginalFilename(), + targetExtension); + File sourceFile = createSourceFile(request, sourceMultipartFile); + File targetFile = createTargetFile(request, targetFilename); + // Both files are deleted by TransformInterceptor.afterCompletion + + String options = buildTransformOptions(startPage, endPage , alphaRemove, autoOrient, cropGravity, cropWidth, cropHeight, cropPercentage, + cropXOffset, cropYOffset, thumbnail, resizeWidth, resizeHeight, resizePercentage, allowEnlargement, maintainAspectRatio, commandOptions); + String pageRange = calculatePageRange(startPage, endPage); + + executeTransformCommand(options, sourceFile, pageRange, targetFile, timeout); + + return createAttachment(targetFilename, targetFile, testDelay); + } + + @Override + protected void processTransform(File sourceFile, File targetFile, + Map transformOptions, Long timeout) + { + Integer startPage = stringToInteger(transformOptions.get("startPage")); + Integer endPage = stringToInteger(transformOptions.get("endPage")); + Boolean alphaRemove = stringToBoolean(transformOptions.get("alphaRemove")); + Boolean autoOrient = stringToBoolean(transformOptions.get("autoOrient")); + String cropGravity = transformOptions.get("cropGravity"); + Integer cropWidth = stringToInteger(transformOptions.get("cropWidth")); + Integer cropHeight = stringToInteger(transformOptions.get("cropHeight")); + Boolean cropPercentage = stringToBoolean(transformOptions.get("cropPercentage")); + Integer cropXOffset = stringToInteger(transformOptions.get("cropXOffset")); + Integer cropYOffset = stringToInteger(transformOptions.get("cropYOffset")); + Boolean thumbnail = stringToBoolean(transformOptions.get("thumbnail")); + Integer resizeWidth = stringToInteger(transformOptions.get("resizeWidth")); + Integer resizeHeight = stringToInteger(transformOptions.get("resizeHeight")); + Boolean resizePercentage = stringToBoolean(transformOptions.get("resizePercentage")); + Boolean allowEnlargement = stringToBoolean(transformOptions.get("allowEnlargement")); + Boolean maintainAspectRatio = stringToBoolean(transformOptions.get("maintainAspectRatio")); + String commandOptions = transformOptions.get("commandOptions"); + + String options = buildTransformOptions(startPage, endPage , alphaRemove, autoOrient, cropGravity, cropWidth, cropHeight, cropPercentage, + cropXOffset, cropYOffset, thumbnail, resizeWidth, resizeHeight, resizePercentage, allowEnlargement, maintainAspectRatio, commandOptions); + String pageRange = calculatePageRange(startPage, endPage); + + executeTransformCommand(options, sourceFile, pageRange, targetFile, timeout); + } + + private void executeTransformCommand(String options, File sourceFile, String pageRange, File targetFile, Long timeout) + { + LogEntry.setOptions(pageRange+(pageRange.isEmpty() ? "" : " ")+options); + + Map properties = new HashMap(5); + properties.put("options", options); + properties.put("source", sourceFile.getAbsolutePath()+pageRange); + properties.put("target", targetFile.getAbsolutePath()); + + executeTransformCommand(properties, targetFile, timeout); + } + + private String buildTransformOptions(Integer startPage, Integer endPage, Boolean alphaRemove, + Boolean autoOrient, String cropGravity, Integer cropWidth, Integer cropHeight, + Boolean cropPercentage, Integer cropXOffset, Integer cropYOffset, Boolean thumbnail, + Integer resizeWidth, Integer resizeHeight, Boolean resizePercentage, + Boolean allowEnlargement, Boolean maintainAspectRatio, String commandOptions) { if (cropGravity != null) { @@ -173,11 +241,6 @@ public class ImageMagickController extends AbstractTransformerController } } - String targetFilename = createTargetFileName(sourceMultipartFile, targetExtension); - File sourceFile = createSourceFile(request, sourceMultipartFile); - File targetFile = createTargetFile(request, targetFilename); - // Both files are deleted by TransformInterceptor.afterCompletion - StringJoiner args = new StringJoiner(" "); if (alphaRemove != null && alphaRemove) { @@ -190,7 +253,7 @@ public class ImageMagickController extends AbstractTransformerController } if (cropGravity != null || cropWidth != null || cropHeight != null || cropPercentage != null || - cropXOffset != null || cropYOffset != null) + cropXOffset != null || cropYOffset != null) { if (cropGravity != null) { @@ -268,32 +331,20 @@ public class ImageMagickController extends AbstractTransformerController } } - String pageRange = - startPage == null - ? endPage == null - ? "" - : "["+endPage+']' - : endPage == null || startPage.equals(endPage) - ? "["+startPage+']' - : "["+startPage+'-'+endPage+']'; - - String options = - (commandOptions == null || "".equals(commandOptions.trim()) ? "" : commandOptions + ' ') + - args.toString(); - executeTransformCommand(options, sourceFile, pageRange, targetFile, timeout); - - return createAttachment(targetFilename, targetFile, testDelay); + return (commandOptions == null || "".equals(commandOptions.trim()) ? "" : commandOptions + ' ') + + args.toString(); } - private void executeTransformCommand(String options, File sourceFile, String pageRange, File targetFile, Long timeout) + private String calculatePageRange(Integer startPage, Integer endPage) { - LogEntry.setOptions(pageRange+(pageRange.isEmpty() ? "" : " ")+options); - - Map properties = new HashMap(5); - properties.put("options", options); - properties.put("source", sourceFile.getAbsolutePath()+pageRange); - properties.put("target", targetFile.getAbsolutePath()); - - executeTransformCommand(properties, targetFile, timeout); + return + startPage == null + ? endPage == null + ? "" + : "["+endPage+']' + : endPage == null || startPage.equals(endPage) + ? "["+startPage+']' + : "["+startPage+'-'+endPage+']'; } + } diff --git a/alfresco-docker-imagemagick/src/test/java/org/alfresco/transformer/ImageMagickControllerTest.java b/alfresco-docker-imagemagick/src/test/java/org/alfresco/transformer/ImageMagickControllerTest.java index 08feba17..2b69ff71 100644 --- a/alfresco-docker-imagemagick/src/test/java/org/alfresco/transformer/ImageMagickControllerTest.java +++ b/alfresco-docker-imagemagick/src/test/java/org/alfresco/transformer/ImageMagickControllerTest.java @@ -25,6 +25,13 @@ */ package org.alfresco.transformer; +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.IOException; + +import org.alfresco.transform.client.model.TransformRequest; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -33,10 +40,6 @@ import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import java.io.IOException; - -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; - /** * Test the ImageMagickController without a server. * Super class includes tests for the AbstractTransformerController. @@ -51,6 +54,9 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest @Before public void before() throws IOException { + controller.setAlfrescoSharedFileStoreClient(alfrescoSharedFileStoreClient); + super.controller = controller; + super.mockTransformCommand(controller, "jpg", "png", "image/jpg", true); } @@ -164,4 +170,11 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest .andExpect(content().bytes(expectedTargetFileBytes)) .andExpect(header().string("Content-Disposition", "attachment; filename*= UTF-8''quick."+targetExtension)); } + + @Override + protected void updateTransformRequestWithSpecificOptions(TransformRequest transformRequest) + { + transformRequest.setSourceExtension("png"); + transformRequest.setTargetExtension("png"); + } } diff --git a/alfresco-docker-libreoffice/src/main/java/org/alfresco/transformer/LibreOfficeController.java b/alfresco-docker-libreoffice/src/main/java/org/alfresco/transformer/LibreOfficeController.java index caa16274..d6f7feeb 100644 --- a/alfresco-docker-libreoffice/src/main/java/org/alfresco/transformer/LibreOfficeController.java +++ b/alfresco-docker-libreoffice/src/main/java/org/alfresco/transformer/LibreOfficeController.java @@ -11,7 +11,12 @@ */ package org.alfresco.transformer; -import com.sun.star.task.ErrorCodeIOException; +import java.io.File; +import java.io.IOException; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + import org.apache.commons.logging.LogFactory; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; @@ -21,15 +26,14 @@ import org.artofsolving.jodconverter.office.OfficeException; import org.artofsolving.jodconverter.office.OfficeManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; -import javax.servlet.http.HttpServletRequest; -import java.io.File; -import java.io.IOException; +import com.sun.star.task.ErrorCodeIOException; /** * Controller for the Docker based LibreOffice transformer. @@ -135,14 +139,14 @@ public class LibreOfficeController extends AbstractTransformerController }; } - @PostMapping("/transform") + @PostMapping(value = "/transform", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity transform(HttpServletRequest request, @RequestParam("file") MultipartFile sourceMultipartFile, @RequestParam("targetExtension") String targetExtension, @RequestParam(value = "timeout", required = false) Long timeout, @RequestParam(value = "testDelay", required = false) Long testDelay) { - String targetFilename = createTargetFileName(sourceMultipartFile, targetExtension); + String targetFilename = createTargetFileName(sourceMultipartFile.getOriginalFilename(), targetExtension); File sourceFile = createSourceFile(request, sourceMultipartFile); File targetFile = createTargetFile(request, targetFilename); // Both files are deleted by TransformInterceptor.afterCompletion @@ -152,6 +156,13 @@ public class LibreOfficeController extends AbstractTransformerController return createAttachment(targetFilename, targetFile, testDelay); } + @Override + protected void processTransform(File sourceFile, File targetFile, + Map transformOptions, Long timeout) + { + executeTransformCommand(sourceFile, targetFile, timeout); + } + protected void executeTransformCommand(File sourceFile, File targetFile, Long timeout) { timeout = timeout != null && timeout > 0 ? timeout : 0; diff --git a/alfresco-docker-libreoffice/src/test/java/org/alfresco/transformer/LibreOfficeControllerTest.java b/alfresco-docker-libreoffice/src/test/java/org/alfresco/transformer/LibreOfficeControllerTest.java index ecfe8235..08c67b72 100644 --- a/alfresco-docker-libreoffice/src/test/java/org/alfresco/transformer/LibreOfficeControllerTest.java +++ b/alfresco-docker-libreoffice/src/test/java/org/alfresco/transformer/LibreOfficeControllerTest.java @@ -25,6 +25,22 @@ */ 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.Mockito.doAnswer; +import static org.mockito.Mockito.doThrow; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.Arrays; + +import org.alfresco.transform.client.model.TransformRequest; import org.artofsolving.jodconverter.office.OfficeException; import org.junit.Before; import org.junit.Test; @@ -35,22 +51,7 @@ import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.channels.FileChannel; -import java.nio.file.Files; -import java.util.Arrays; - -import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.*; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doThrow; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import org.springframework.util.StringUtils; /** * Test the LibreOfficeController without a server. @@ -66,6 +67,7 @@ public class LibreOfficeControllerTest extends AbstractTransformerControllerTest @Before public void before() throws IOException { + controller.setAlfrescoSharedFileStoreClient(alfrescoSharedFileStoreClient); super.controller = controller; sourceExtension = "doc"; @@ -83,6 +85,7 @@ public class LibreOfficeControllerTest extends AbstractTransformerControllerTest { File sourceFile = invocation.getArgumentAt(0, File.class); File targetFile = invocation.getArgumentAt(1, File.class); + String actualTargetExtension = StringUtils.getFilenameExtension(targetFile.getAbsolutePath()); assertNotNull(sourceFile); assertNotNull(targetFile); @@ -101,12 +104,7 @@ public class LibreOfficeControllerTest extends AbstractTransformerControllerTest { String testFilename = actualTarget.substring(i+1); File testFile = getTestFile(testFilename, false); - if (testFile != null) - { - FileChannel source = new FileInputStream(testFile).getChannel(); - FileChannel target = new FileOutputStream(targetFile).getChannel(); - target.transferFrom(source, 0, source.size()); - } + generateTargetFileFromResourceFile(actualTargetExtension, testFile, targetFile); } // Check the supplied source file has not been changed. @@ -129,4 +127,11 @@ public class LibreOfficeControllerTest extends AbstractTransformerControllerTest .andExpect(status().is(400)) .andExpect(status().reason(containsString("LibreOffice - LibreOffice server conversion failed:"))); } + + @Override + protected void updateTransformRequestWithSpecificOptions(TransformRequest transformRequest) + { + transformRequest.setSourceExtension("doc"); + transformRequest.setTargetExtension("pdf"); + } } diff --git a/alfresco-docker-tika/src/main/java/org/alfresco/transformer/TikaController.java b/alfresco-docker-tika/src/main/java/org/alfresco/transformer/TikaController.java index 6c23e9d6..65e6b6e1 100644 --- a/alfresco-docker-tika/src/main/java/org/alfresco/transformer/TikaController.java +++ b/alfresco-docker-tika/src/main/java/org/alfresco/transformer/TikaController.java @@ -11,10 +11,25 @@ */ package org.alfresco.transformer; +import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_TEXT_PLAIN; +import static org.alfresco.transformer.Tika.INCLUDE_CONTENTS; +import static org.alfresco.transformer.Tika.NOT_EXTRACT_BOOKMARKS_TEXT; +import static org.alfresco.transformer.Tika.PDF_BOX; +import static org.alfresco.transformer.Tika.TARGET_ENCODING; +import static org.alfresco.transformer.Tika.TARGET_MIMETYPE; +import static org.alfresco.transformer.Tika.TRANSFORM_NAMES; + +import java.io.File; +import java.io.IOException; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + import org.apache.commons.logging.LogFactory; import org.apache.tika.exception.TikaException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; @@ -22,13 +37,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import org.xml.sax.SAXException; -import javax.servlet.http.HttpServletRequest; -import java.io.File; -import java.io.IOException; - -import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_TEXT_PLAIN; -import static org.alfresco.transformer.Tika.*; - /** * Controller for the Docker based Tika transformers. * @@ -102,7 +110,7 @@ public class TikaController extends AbstractTransformerController }; } - @PostMapping("/transform") + @PostMapping(value = "/transform", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity transform(HttpServletRequest request, @RequestParam("file") MultipartFile sourceMultipartFile, @RequestParam("targetExtension") String targetExtension, @@ -122,7 +130,7 @@ public class TikaController extends AbstractTransformerController throw new TransformException(400, "Invalid transform value"); } - String targetFilename = createTargetFileName(sourceMultipartFile, targetExtension); + String targetFilename = createTargetFileName(sourceMultipartFile.getOriginalFilename(), targetExtension); File sourceFile = createSourceFile(request, sourceMultipartFile); File targetFile = createTargetFile(request, targetFilename); // Both files are deleted by TransformInterceptor.afterCompletion @@ -137,4 +145,21 @@ public class TikaController extends AbstractTransformerController return createAttachment(targetFilename, targetFile, testDelay); } + + @Override + protected void processTransform(File sourceFile, File targetFile, + Map transformOptions, Long timeout) + { + + String transform = transformOptions.get("transform"); + Boolean includeContents = stringToBoolean("includeContents"); + Boolean notExtractBookmarksText = stringToBoolean("notExtractBookmarksText"); + String targetMimetype = transformOptions.get("targetMimetype"); + String targetEncoding = transformOptions.get("targetEncoding"); + + callTransform(sourceFile, targetFile, transform, + includeContents != null && includeContents ? INCLUDE_CONTENTS : null, + notExtractBookmarksText != null && notExtractBookmarksText ? NOT_EXTRACT_BOOKMARKS_TEXT: null, + TARGET_MIMETYPE + targetMimetype, TARGET_ENCODING + targetEncoding); + } } diff --git a/alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaControllerTest.java b/alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaControllerTest.java index dd711d73..27d0e572 100644 --- a/alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaControllerTest.java +++ b/alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaControllerTest.java @@ -25,6 +25,44 @@ */ package org.alfresco.transformer; +import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_HTML; +import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_OPENXML_PRESENTATION; +import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET; +import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_OPENXML_WORDPROCESSING; +import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_OUTLOOK_MSG; +import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_PDF; +import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_TEXT_CSV; +import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_TEXT_PLAIN; +import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_WORD; +import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_XHTML; +import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_XML; +import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_ZIP; +import static org.alfresco.transformer.Tika.ARCHIVE; +import static org.alfresco.transformer.Tika.CSV; +import static org.alfresco.transformer.Tika.DOC; +import static org.alfresco.transformer.Tika.DOCX; +import static org.alfresco.transformer.Tika.HTML; +import static org.alfresco.transformer.Tika.MSG; +import static org.alfresco.transformer.Tika.OUTLOOK_MSG; +import static org.alfresco.transformer.Tika.PDF; +import static org.alfresco.transformer.Tika.PDF_BOX; +import static org.alfresco.transformer.Tika.POI; +import static org.alfresco.transformer.Tika.POI_OFFICE; +import static org.alfresco.transformer.Tika.POI_OO_XML; +import static org.alfresco.transformer.Tika.PPTX; +import static org.alfresco.transformer.Tika.TEXT_MINING; +import static org.alfresco.transformer.Tika.TIKA_AUTO; +import static org.alfresco.transformer.Tika.TXT; +import static org.alfresco.transformer.Tika.XHTML; +import static org.alfresco.transformer.Tika.XML; +import static org.alfresco.transformer.Tika.XSLX; +import static org.alfresco.transformer.Tika.ZIP; +import static org.springframework.test.util.AssertionErrors.assertTrue; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.alfresco.transform.client.model.TransformRequest; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -34,12 +72,6 @@ import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; -import static org.alfresco.repo.content.MimetypeMap.*; -import static org.alfresco.transformer.Tika.*; -import static org.springframework.test.util.AssertionErrors.assertTrue; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - /** * Test the TikaController without a server. * Super class includes tests for the AbstractTransformerController. @@ -63,6 +95,16 @@ public class TikaControllerTest extends AbstractTransformerControllerTest String targetEncoding = "UTF-8"; String targetMimetype = MIMETYPE_TEXT_PLAIN; + @Before + public void before() throws Exception + { + controller.setAlfrescoSharedFileStoreClient(alfrescoSharedFileStoreClient); + super.controller = controller; + + sourceExtension = "pdf"; + targetExtension = "txt"; + } + private void transform(String transform, String sourceExtension, String targetExtension, String sourceMimetype, String targetMimetype, Boolean includeContents, String expectedContentContains) throws Exception @@ -350,4 +392,14 @@ public class TikaControllerTest extends AbstractTransformerControllerTest .andExpect(status().is(200)) .andExpect(header().string("Content-Disposition", "attachment; filename*= UTF-8''quick." + targetExtension)); } + + @Override + protected void updateTransformRequestWithSpecificOptions(TransformRequest transformRequest) + { + transformRequest.setSourceExtension(sourceExtension); + transformRequest.setTargetExtension(targetExtension); + transformRequest.getTransformationRequestOptions().put("transform", "PdfBox"); + transformRequest.getTransformationRequestOptions().put("targetMimetype", "text/plain"); + transformRequest.getTransformationRequestOptions().put("targetEncoding", "UTF-8"); + } } diff --git a/alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaHttpRequestTest.java b/alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaHttpRequestTest.java index 25547e11..d368ef2a 100644 --- a/alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaHttpRequestTest.java +++ b/alfresco-docker-tika/src/test/java/org/alfresco/transformer/TikaHttpRequestTest.java @@ -47,5 +47,5 @@ public class TikaHttpRequestTest extends AbstractHttpRequestTest protected String getSourceExtension() { return "pdf"; - }; + } } diff --git a/alfresco-docker-tika/src/test/resources/quick.pdf b/alfresco-docker-tika/src/test/resources/quick.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a1779afd8b4d1b7d75456c61900c5cead5444abb GIT binary patch literal 23697 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≺ND&( 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 Pz?x-07<5&PtcCX{dE{yb literal 0 HcmV?d00001 diff --git a/alfresco-transformer-base/README.md b/alfresco-transformer-base/README.md index 5439183e..b0e052ce 100644 --- a/alfresco-transformer-base/README.md +++ b/alfresco-transformer-base/README.md @@ -111,6 +111,65 @@ public class AlfrescoPdfRendererController extends AbstractTransformerController } ~~~ +* *TransformerName*Controller#processTransform(File sourceFile, File targetFile, Map 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 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 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: diff --git a/alfresco-transformer-base/pom.xml b/alfresco-transformer-base/pom.xml index b9d651da..8270af86 100644 --- a/alfresco-transformer-base/pom.xml +++ b/alfresco-transformer-base/pom.xml @@ -26,6 +26,10 @@ org.alfresco alfresco-core + + org.alfresco + alfresco-transform-data-model + diff --git a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/AbstractTransformerController.java b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/AbstractTransformerController.java index 75da9fd0..f041e82e 100644 --- a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/AbstractTransformerController.java +++ b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/AbstractTransformerController.java @@ -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.*; - /** *

Abstract Controller, provides structure and helper methods to sub-class transformer controllers.

* @@ -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 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 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 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; + } } diff --git a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/AlfrescoSharedFileStoreClient.java b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/AlfrescoSharedFileStoreClient.java new file mode 100644 index 00000000..bbf8a033 --- /dev/null +++ b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/AlfrescoSharedFileStoreClient.java @@ -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 + */ + public ResponseEntity 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 map = new LinkedMultiValueMap<>(); + map.add("file", value); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + HttpEntity> requestEntity = new HttpEntity<>(map, + headers); + ResponseEntity responseEntity = restTemplate + .exchange(fileStoreUrl, HttpMethod.POST, requestEntity, FileRefResponse.class); + return responseEntity.getBody(); + } + catch (HttpClientErrorException e) + { + throw new TransformException(e.getStatusCode().value(), e.getMessage(), e); + } + } +} diff --git a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/Application.java b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/Application.java index 2d2ad7f8..bb2b9b7d 100644 --- a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/Application.java +++ b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/Application.java @@ -35,4 +35,5 @@ public class Application { SpringApplication.run(Application.class, args); } + } diff --git a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/WebApplicationConfig.java b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/WebApplicationConfig.java index 983e3163..720dd662 100644 --- a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/WebApplicationConfig.java +++ b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/WebApplicationConfig.java @@ -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(); + } } diff --git a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/model/FileRefEntity.java b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/model/FileRefEntity.java new file mode 100644 index 00000000..83a292eb --- /dev/null +++ b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/model/FileRefEntity.java @@ -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); + } +} diff --git a/alfresco-transformer-base/src/main/java/org/alfresco/transformer/model/FileRefResponse.java b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/model/FileRefResponse.java new file mode 100644 index 00000000..3c4b13a2 --- /dev/null +++ b/alfresco-transformer-base/src/main/java/org/alfresco/transformer/model/FileRefResponse.java @@ -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; + } +} diff --git a/alfresco-transformer-base/src/main/resources/application.properties b/alfresco-transformer-base/src/main/resources/application.properties deleted file mode 100644 index ca637b84..00000000 --- a/alfresco-transformer-base/src/main/resources/application.properties +++ /dev/null @@ -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 \ No newline at end of file diff --git a/alfresco-transformer-base/src/main/resources/application.yaml b/alfresco-transformer-base/src/main/resources/application.yaml new file mode 100644 index 00000000..95ca9000 --- /dev/null +++ b/alfresco-transformer-base/src/main/resources/application.yaml @@ -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} \ No newline at end of file diff --git a/alfresco-transformer-base/src/test/java/org/alfresco/transformer/AbstractTransformerControllerTest.java b/alfresco-transformer-base/src/test/java/org/alfresco/transformer/AbstractTransformerControllerTest.java index 5c619442..ee67c2ae 100644 --- a/alfresco-transformer-base/src/test/java/org/alfresco/transformer/AbstractTransformerControllerTest.java +++ b/alfresco-transformer-base/src/test/java/org/alfresco/transformer/AbstractTransformerControllerTest.java @@ -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 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); } diff --git a/pom.xml b/pom.xml index a4a70ccb..9e25a262 100644 --- a/pom.xml +++ b/pom.xml @@ -24,6 +24,7 @@ 3.0.1.1 1.2.3 ${project.version} + 0.0.4 @@ -85,6 +86,11 @@ pdfbox ${dependency.pdfbox.version} + + org.alfresco + alfresco-transform-data-model + ${alfresco-transform-data-model.version} +