Merge branch 'master' into fix/mnt-20337_LO_6.1.6

This commit is contained in:
Cezar.Leahu 2019-08-19 18:43:27 +03:00
commit 2cdde6928c
64 changed files with 1559 additions and 1260 deletions

View File

@ -65,7 +65,6 @@
<artifactId>dom4j</artifactId> <artifactId>dom4j</artifactId>
<version>2.1.1</version> <version>2.1.1</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -30,11 +30,10 @@ import static org.alfresco.transformer.fs.FileManager.createAttachment;
import static org.alfresco.transformer.fs.FileManager.createSourceFile; import static org.alfresco.transformer.fs.FileManager.createSourceFile;
import static org.alfresco.transformer.fs.FileManager.createTargetFile; import static org.alfresco.transformer.fs.FileManager.createTargetFile;
import static org.alfresco.transformer.fs.FileManager.createTargetFileName; import static org.alfresco.transformer.fs.FileManager.createTargetFileName;
import static org.alfresco.transformer.logging.StandardMessages.LICENCE;
import static org.springframework.http.HttpStatus.OK; import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
import java.io.File; import java.io.File;
import java.util.Arrays;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -46,7 +45,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -76,20 +74,12 @@ import org.springframework.web.multipart.MultipartFile;
@Controller @Controller
public class AlfrescoPdfRendererController extends AbstractTransformerController public class AlfrescoPdfRendererController extends AbstractTransformerController
{ {
private static final Logger logger = LoggerFactory.getLogger(AlfrescoPdfRendererController.class); private static final Logger logger = LoggerFactory.getLogger(
AlfrescoPdfRendererController.class);
@Autowired @Autowired
private PdfRendererCommandExecutor commandExecutor; private PdfRendererCommandExecutor commandExecutor;
@Autowired
public AlfrescoPdfRendererController()
{
logger.info("-----------------------------------------------------------------------------------------------------------------------------------------------------------");
Arrays.stream(LICENCE.split("\\n")).forEach(logger::info);
logger.info("alfresco-pdf-renderer uses the PDFium library from Google Inc. See the license at https://pdfium.googlesource.com/pdfium/+/master/LICENSE or in /pdfium.txt");
logger.info("-----------------------------------------------------------------------------------------------------------------------------------------------------------");
}
@Override @Override
public String getTransformerName() public String getTransformerName()
{ {
@ -137,7 +127,7 @@ public class AlfrescoPdfRendererController extends AbstractTransformerController
} }
@Deprecated @Deprecated
@PostMapping(value = "/transform", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @PostMapping(value = "/transform", consumes = MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<Resource> transform(HttpServletRequest request, public ResponseEntity<Resource> transform(HttpServletRequest request,
@RequestParam("file") MultipartFile sourceMultipartFile, @RequestParam("file") MultipartFile sourceMultipartFile,
@RequestParam("targetExtension") String targetExtension, @RequestParam("targetExtension") String targetExtension,
@ -150,7 +140,8 @@ public class AlfrescoPdfRendererController extends AbstractTransformerController
@RequestParam(value = "allowPdfEnlargement", required = false) Boolean allowPdfEnlargement, @RequestParam(value = "allowPdfEnlargement", required = false) Boolean allowPdfEnlargement,
@RequestParam(value = "maintainPdfAspectRatio", required = false) Boolean maintainPdfAspectRatio) @RequestParam(value = "maintainPdfAspectRatio", required = false) Boolean maintainPdfAspectRatio)
{ {
String targetFilename = createTargetFileName(sourceMultipartFile.getOriginalFilename(), targetExtension); String targetFilename = createTargetFileName(sourceMultipartFile.getOriginalFilename(),
targetExtension);
getProbeTestTransform().incrementTransformerCount(); getProbeTestTransform().incrementTransformerCount();
File sourceFile = createSourceFile(request, sourceMultipartFile); File sourceFile = createSourceFile(request, sourceMultipartFile);
File targetFile = createTargetFile(request, targetFilename); File targetFile = createTargetFile(request, targetFilename);

View File

@ -26,25 +26,36 @@
*/ */
package org.alfresco.transformer; package org.alfresco.transformer;
import static org.alfresco.transformer.logging.StandardMessages.LICENCE;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer; import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.event.EventListener;
import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.MeterRegistry;
@SpringBootApplication @SpringBootApplication
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) @EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class Application public class Application
{ {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Value("${container.name}") @Value("${container.name}")
private String containerName; private String containerName;
@Bean @Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() { public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags()
{
return registry -> registry.config().commonTags("containerName", containerName); return registry -> registry.config().commonTags("containerName", containerName);
} }
@ -52,4 +63,15 @@ public class Application
{ {
SpringApplication.run(Application.class, args); SpringApplication.run(Application.class, args);
} }
@EventListener(ApplicationReadyEvent.class)
public void startup()
{
logger.info("-----------------------------------------------------------------------------------------------------------------------------------------------------------");
Arrays.stream(LICENCE.split("\\n")).forEach(logger::info);
logger.info("alfresco-pdf-renderer uses the PDFium library from Google Inc. See the license at https://pdfium.googlesource.com/pdfium/+/master/LICENSE or in /pdfium.txt");
logger.info("-----------------------------------------------------------------------------------------------------------------------------------------------------------");
logger.info("Starting application components... Done");
}
} }

View File

@ -44,9 +44,7 @@ final class OptionsBuilder
private Boolean allowPdfEnlargement; private Boolean allowPdfEnlargement;
private Boolean maintainPdfAspectRatio; private Boolean maintainPdfAspectRatio;
private OptionsBuilder() private OptionsBuilder() {}
{
}
public OptionsBuilder withPage(final String page) public OptionsBuilder withPage(final String page)
{ {

View File

@ -33,11 +33,19 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static org.springframework.http.HttpHeaders.ACCEPT;
import static org.springframework.http.HttpHeaders.CONTENT_DISPOSITION;
import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.OK; import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.http.MediaType.APPLICATION_PDF_VALUE;
import static org.springframework.http.MediaType.IMAGE_PNG_VALUE;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 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.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.util.StringUtils.getFilenameExtension;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -64,14 +72,11 @@ import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile; import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.util.StringUtils;
/** /**
* Test the AlfrescoPdfRendererController without a server. * Test the AlfrescoPdfRendererController without a server.
@ -118,7 +123,8 @@ public class AlfrescoPdfRendererControllerTest extends AbstractTransformerContro
expectedSourceSuffix = null; expectedSourceSuffix = null;
expectedSourceFileBytes = readTestFile(sourceExtension); expectedSourceFileBytes = readTestFile(sourceExtension);
expectedTargetFileBytes = readTargetFileBytes ? readTestFile(targetExtension) : null; expectedTargetFileBytes = readTargetFileBytes ? readTestFile(targetExtension) : null;
sourceFile = new MockMultipartFile("file", "quick." + sourceExtension, sourceMimetype, expectedSourceFileBytes); sourceFile = new MockMultipartFile("file", "quick." + sourceExtension, sourceMimetype,
expectedSourceFileBytes);
when(mockTransformCommand.execute(any(), anyLong())).thenAnswer( when(mockTransformCommand.execute(any(), anyLong())).thenAnswer(
(Answer<RuntimeExec.ExecutionResult>) invocation -> { (Answer<RuntimeExec.ExecutionResult>) invocation -> {
@ -128,14 +134,17 @@ public class AlfrescoPdfRendererControllerTest extends AbstractTransformerContro
String actualOptions = actualProperties.get("options"); String actualOptions = actualProperties.get("options");
String actualSource = actualProperties.get("source"); String actualSource = actualProperties.get("source");
String actualTarget = actualProperties.get("target"); String actualTarget = actualProperties.get("target");
String actualTargetExtension = StringUtils.getFilenameExtension(actualTarget); String actualTargetExtension = getFilenameExtension(actualTarget);
assertNotNull(actualSource); assertNotNull(actualSource);
assertNotNull(actualTarget); assertNotNull(actualTarget);
if (expectedSourceSuffix != null) if (expectedSourceSuffix != null)
{ {
assertTrue("The source file \""+actualSource+"\" should have ended in \""+expectedSourceSuffix+"\"", actualSource.endsWith(expectedSourceSuffix)); assertTrue("The source file \"" + actualSource +
actualSource = actualSource.substring(0, actualSource.length()-expectedSourceSuffix.length()); "\" should have ended in \"" + expectedSourceSuffix + "\"",
actualSource.endsWith(expectedSourceSuffix));
actualSource = actualSource.substring(0,
actualSource.length() - expectedSourceSuffix.length());
} }
assertNotNull(actualOptions); assertNotNull(actualOptions);
@ -155,7 +164,7 @@ public class AlfrescoPdfRendererControllerTest extends AbstractTransformerContro
int i = actualTarget.lastIndexOf('_'); int i = actualTarget.lastIndexOf('_');
if (i >= 0) if (i >= 0)
{ {
String testFilename = actualTarget.substring(i+1); String testFilename = actualTarget.substring(i + 1);
File testFile = getTestFile(testFilename, false); File testFile = getTestFile(testFilename, false);
File targetFile = new File(actualTarget); File targetFile = new File(actualTarget);
generateTargetFileFromResourceFile(actualTargetExtension, testFile, generateTargetFileFromResourceFile(actualTargetExtension, testFile,
@ -164,7 +173,8 @@ public class AlfrescoPdfRendererControllerTest extends AbstractTransformerContro
// Check the supplied source file has not been changed. // Check the supplied source file has not been changed.
byte[] actualSourceFileBytes = Files.readAllBytes(new File(actualSource).toPath()); byte[] actualSourceFileBytes = Files.readAllBytes(new File(actualSource).toPath());
assertTrue("Source file is not the same", Arrays.equals(expectedSourceFileBytes, actualSourceFileBytes)); assertTrue("Source file is not the same",
Arrays.equals(expectedSourceFileBytes, actualSourceFileBytes));
return mockExecutionResult; return mockExecutionResult;
}); });
@ -174,7 +184,6 @@ public class AlfrescoPdfRendererControllerTest extends AbstractTransformerContro
when(mockExecutionResult.getStdOut()).thenReturn("STDOUT"); when(mockExecutionResult.getStdOut()).thenReturn("STDOUT");
} }
@Override @Override
protected AbstractTransformerController getController() protected AbstractTransformerController getController()
{ {
@ -185,7 +194,9 @@ public class AlfrescoPdfRendererControllerTest extends AbstractTransformerContro
public void optionsTest() throws Exception public void optionsTest() throws Exception
{ {
expectedOptions = "--width=321 --height=654 --allow-enlargement --maintain-aspect-ratio --page=2"; expectedOptions = "--width=321 --height=654 --allow-enlargement --maintain-aspect-ratio --page=2";
mockMvc.perform(MockMvcRequestBuilders.multipart("/transform") mockMvc
.perform(MockMvcRequestBuilders
.multipart("/transform")
.file(sourceFile) .file(sourceFile)
.param("targetExtension", targetExtension) .param("targetExtension", targetExtension)
@ -195,17 +206,19 @@ public class AlfrescoPdfRendererControllerTest extends AbstractTransformerContro
.param("height", "654") .param("height", "654")
.param("allowPdfEnlargement", "true") .param("allowPdfEnlargement", "true")
.param("maintainPdfAspectRatio", "true")) .param("maintainPdfAspectRatio", "true"))
.andExpect(status().is(OK.value())) .andExpect(status().is(OK.value()))
.andExpect(content().bytes(expectedTargetFileBytes)) .andExpect(content().bytes(expectedTargetFileBytes))
.andExpect(header().string("Content-Disposition", "attachment; filename*= UTF-8''quick."+targetExtension)); .andExpect(header().string("Content-Disposition",
"attachment; filename*= UTF-8''quick." + targetExtension));
} }
@Test @Test
public void optionsNegateBooleansTest() throws Exception public void optionsNegateBooleansTest() throws Exception
{ {
expectedOptions = "--width=321 --height=654 --page=2"; expectedOptions = "--width=321 --height=654 --page=2";
mockMvc.perform(MockMvcRequestBuilders.multipart("/transform") mockMvc
.perform(MockMvcRequestBuilders
.multipart("/transform")
.file(sourceFile) .file(sourceFile)
.param("targetExtension", targetExtension) .param("targetExtension", targetExtension)
@ -215,10 +228,10 @@ public class AlfrescoPdfRendererControllerTest extends AbstractTransformerContro
.param("height", "654") .param("height", "654")
.param("allowPdfEnlargement", "false") .param("allowPdfEnlargement", "false")
.param("maintainPdfAspectRatio", "false")) .param("maintainPdfAspectRatio", "false"))
.andExpect(status().is(OK.value())) .andExpect(status().is(OK.value()))
.andExpect(content().bytes(expectedTargetFileBytes)) .andExpect(content().bytes(expectedTargetFileBytes))
.andExpect(header().string("Content-Disposition", "attachment; filename*= UTF-8''quick."+targetExtension)); .andExpect(header().string("Content-Disposition",
"attachment; filename*= UTF-8''quick." + targetExtension));
} }
@Override @Override
@ -226,8 +239,8 @@ public class AlfrescoPdfRendererControllerTest extends AbstractTransformerContro
{ {
transformRequest.setSourceExtension("pdf"); transformRequest.setSourceExtension("pdf");
transformRequest.setTargetExtension("png"); transformRequest.setTargetExtension("png");
transformRequest.setSourceMediaType(MediaType.APPLICATION_PDF_VALUE); transformRequest.setSourceMediaType(APPLICATION_PDF_VALUE);
transformRequest.setTargetMediaType(MediaType.IMAGE_PNG_VALUE); transformRequest.setTargetMediaType(IMAGE_PNG_VALUE);
} }
@Test @Test
@ -237,7 +250,8 @@ public class AlfrescoPdfRendererControllerTest extends AbstractTransformerContro
mockMvc.perform(mockMvcRequest("/transform", sourceFile, "targetExtension", "xxx")) mockMvc.perform(mockMvcRequest("/transform", sourceFile, "targetExtension", "xxx"))
.andExpect(status().is(BAD_REQUEST.value())) .andExpect(status().is(BAD_REQUEST.value()))
.andExpect(status().reason(containsString("Transformer exit code was not 0: \nSTDERR"))); .andExpect(status()
.reason(containsString("Transformer exit code was not 0: \nSTDERR")));
} }
@Test @Test
@ -248,7 +262,6 @@ public class AlfrescoPdfRendererControllerTest extends AbstractTransformerContro
File sourceFile = getTestFile("quick." + sourceExtension, true); File sourceFile = getTestFile("quick." + sourceExtension, true);
String targetFileRef = UUID.randomUUID().toString(); String targetFileRef = UUID.randomUUID().toString();
// Transformation Request POJO // Transformation Request POJO
TransformRequest transformRequest = new TransformRequest(); TransformRequest transformRequest = new TransformRequest();
transformRequest.setRequestId("1"); transformRequest.setRequestId("1");
@ -262,12 +275,13 @@ public class AlfrescoPdfRendererControllerTest extends AbstractTransformerContro
// HTTP Request // HTTP Request
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=quick." + sourceExtension); headers.set(CONTENT_DISPOSITION, "attachment; filename=quick." + sourceExtension);
ResponseEntity<Resource> response = new ResponseEntity<>(new FileSystemResource( ResponseEntity<Resource> response = new ResponseEntity<>(new FileSystemResource(
sourceFile), headers, OK); sourceFile), headers, OK);
when(alfrescoSharedFileStoreClient.retrieveFile(sourceFileRef)).thenReturn(response); when(alfrescoSharedFileStoreClient.retrieveFile(sourceFileRef)).thenReturn(response);
when(alfrescoSharedFileStoreClient.saveFile(any())).thenReturn(new FileRefResponse(new FileRefEntity(targetFileRef))); when(alfrescoSharedFileStoreClient.saveFile(any()))
.thenReturn(new FileRefResponse(new FileRefEntity(targetFileRef)));
when(mockExecutionResult.getExitValue()).thenReturn(0); when(mockExecutionResult.getExitValue()).thenReturn(0);
// Update the Transformation Request with any specific params before sending it // Update the Transformation Request with any specific params before sending it
@ -275,18 +289,21 @@ public class AlfrescoPdfRendererControllerTest extends AbstractTransformerContro
// Serialize and call the transformer // Serialize and call the transformer
String tr = objectMapper.writeValueAsString(transformRequest); String tr = objectMapper.writeValueAsString(transformRequest);
String transformationReplyAsString = mockMvc.perform(MockMvcRequestBuilders.post("/transform") String transformationReplyAsString = mockMvc
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .perform(MockMvcRequestBuilders
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).content(tr)) .post("/transform")
.andExpect(status().is(HttpStatus.CREATED.value())) .header(ACCEPT, APPLICATION_JSON_VALUE)
.header(CONTENT_TYPE, APPLICATION_JSON_VALUE)
.content(tr))
.andExpect(status().is(CREATED.value()))
.andReturn().getResponse().getContentAsString(); .andReturn().getResponse().getContentAsString();
TransformReply transformReply = objectMapper.readValue(transformationReplyAsString, TransformReply.class); TransformReply transformReply = objectMapper.readValue(transformationReplyAsString,
TransformReply.class);
// Assert the reply // Assert the reply
assertEquals(transformRequest.getRequestId(), transformReply.getRequestId()); assertEquals(transformRequest.getRequestId(), transformReply.getRequestId());
assertEquals(transformRequest.getClientData(), transformReply.getClientData()); assertEquals(transformRequest.getClientData(), transformReply.getClientData());
assertEquals(transformRequest.getSchema(), transformReply.getSchema()); assertEquals(transformRequest.getSchema(), transformReply.getSchema());
} }
} }

View File

@ -48,7 +48,8 @@ public class AlfrescoPdfRendererQueueTransformServiceIT extends AbstractQueueTra
@Override @Override
protected TransformRequest buildRequest() protected TransformRequest buildRequest()
{ {
return TransformRequest.builder() return TransformRequest
.builder()
.withRequestId(UUID.randomUUID().toString()) .withRequestId(UUID.randomUUID().toString())
.withSourceMediaType(MIMETYPE_OPENXML_WORDPROCESSING) .withSourceMediaType(MIMETYPE_OPENXML_WORDPROCESSING)
.withTargetMediaType(MIMETYPE_PDF) .withTargetMediaType(MIMETYPE_PDF)

View File

@ -65,7 +65,6 @@
<artifactId>dom4j</artifactId> <artifactId>dom4j</artifactId>
<version>2.1.1</version> <version>2.1.1</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -26,25 +26,36 @@
*/ */
package org.alfresco.transformer; package org.alfresco.transformer;
import static org.alfresco.transformer.logging.StandardMessages.LICENCE;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer; import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.event.EventListener;
import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.MeterRegistry;
@SpringBootApplication @SpringBootApplication
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) @EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class Application public class Application
{ {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Value("${container.name}") @Value("${container.name}")
private String containerName; private String containerName;
@Bean @Bean
MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() { MeterRegistryCustomizer<MeterRegistry> metricsCommonTags()
{
return registry -> registry.config().commonTags("containerName", containerName); return registry -> registry.config().commonTags("containerName", containerName);
} }
@ -52,4 +63,15 @@ public class Application
{ {
SpringApplication.run(Application.class, args); SpringApplication.run(Application.class, args);
} }
@EventListener(ApplicationReadyEvent.class)
public void startup()
{
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
Arrays.stream(LICENCE.split("\\n")).forEach(logger::info);
logger.info("This transformer uses ImageMagick from ImageMagick Studio LLC. See the license at http://www.imagemagick.org/script/license.php or in /ImageMagick-license.txt");
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
logger.info("Starting application components... Done");
}
} }

View File

@ -30,24 +30,22 @@ import static org.alfresco.transformer.fs.FileManager.createAttachment;
import static org.alfresco.transformer.fs.FileManager.createSourceFile; import static org.alfresco.transformer.fs.FileManager.createSourceFile;
import static org.alfresco.transformer.fs.FileManager.createTargetFile; import static org.alfresco.transformer.fs.FileManager.createTargetFile;
import static org.alfresco.transformer.fs.FileManager.createTargetFileName; import static org.alfresco.transformer.fs.FileManager.createTargetFileName;
import static org.alfresco.transformer.logging.StandardMessages.LICENCE;
import static org.alfresco.transformer.util.Util.stringToInteger; import static org.alfresco.transformer.util.Util.stringToInteger;
import static org.springframework.http.HttpStatus.OK; import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
import java.io.File; import java.io.File;
import java.util.Arrays;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.alfresco.transformer.executors.ImageMagickCommandExecutor; import org.alfresco.transformer.executors.ImageMagickCommandExecutor;
import org.alfresco.transformer.logging.LogEntry; import org.alfresco.transformer.logging.LogEntry;
import org.alfresco.transformer.probes.ProbeTestTransform; import org.alfresco.transformer.probes.ProbeTestTransform;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -84,15 +82,6 @@ public class ImageMagickController extends AbstractTransformerController
@Autowired @Autowired
private ImageMagickCommandExecutor commandExecutor; private ImageMagickCommandExecutor commandExecutor;
@Autowired
public ImageMagickController()
{
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
Arrays.stream(LICENCE.split("\\n")).forEach(logger::info);
logger.info("This transformer uses ImageMagick from ImageMagick Studio LLC. See the license at http://www.imagemagick.org/script/license.php or in /ImageMagick-license.txt");
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
}
@Override @Override
public String getTransformerName() public String getTransformerName()
{ {
@ -110,7 +99,7 @@ public class ImageMagickController extends AbstractTransformerController
{ {
// See the Javadoc on this method and Probes.md for the choice of these values. // See the Javadoc on this method and Probes.md for the choice of these values.
return new ProbeTestTransform(this, "quick.jpg", "quick.png", return new ProbeTestTransform(this, "quick.jpg", "quick.png",
35593, 1024, 150, 1024, 60*15+1,60*15) 35593, 1024, 150, 1024, 60 * 15 + 1, 60 * 15)
{ {
@Override @Override
protected void executeTransformCommand(File sourceFile, File targetFile) protected void executeTransformCommand(File sourceFile, File targetFile)
@ -120,7 +109,7 @@ public class ImageMagickController extends AbstractTransformerController
}; };
} }
@PostMapping(value = "/transform", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @PostMapping(value = "/transform", consumes = MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<Resource> transform(HttpServletRequest request, public ResponseEntity<Resource> transform(HttpServletRequest request,
@RequestParam("file") MultipartFile sourceMultipartFile, @RequestParam("file") MultipartFile sourceMultipartFile,
@RequestParam("targetExtension") String targetExtension, @RequestParam("targetExtension") String targetExtension,
@ -240,9 +229,9 @@ public class ImageMagickController extends AbstractTransformerController
return startPage == null return startPage == null
? endPage == null ? endPage == null
? "" ? ""
: "["+endPage+']' : "[" + endPage + ']'
: endPage == null || startPage.equals(endPage) : endPage == null || startPage.equals(endPage)
? "["+startPage+']' ? "[" + startPage + ']'
: "["+startPage+'-'+endPage+']'; : "[" + startPage + '-' + endPage + ']';
} }
} }

View File

@ -26,7 +26,6 @@
*/ */
package org.alfresco.transformer; package org.alfresco.transformer;
import static java.util.Arrays.asList;
import static org.alfresco.transformer.util.Util.stringToBoolean; import static org.alfresco.transformer.util.Util.stringToBoolean;
import static org.alfresco.transformer.util.Util.stringToInteger; import static org.alfresco.transformer.util.Util.stringToInteger;
import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.BAD_REQUEST;
@ -36,6 +35,8 @@ import java.util.StringJoiner;
import org.alfresco.transform.exceptions.TransformException; import org.alfresco.transform.exceptions.TransformException;
import com.google.common.collect.ImmutableList;
/** /**
* ImageMagick options builder. * ImageMagick options builder.
* *
@ -43,8 +44,8 @@ import org.alfresco.transform.exceptions.TransformException;
*/ */
final class OptionsBuilder final class OptionsBuilder
{ {
private static final List<String> GRAVITY_VALUES = asList("North", "NorthEast", "East", private static final List<String> GRAVITY_VALUES = ImmutableList.of("North", "NorthEast",
"SouthEast", "South", "SouthWest", "West", "NorthWest", "Center"); "East", "SouthEast", "South", "SouthWest", "West", "NorthWest", "Center");
private Integer startPage; private Integer startPage;
private Integer endPage; private Integer endPage;
@ -64,9 +65,7 @@ final class OptionsBuilder
private Boolean maintainAspectRatio; private Boolean maintainAspectRatio;
private String commandOptions; private String commandOptions;
private OptionsBuilder() private OptionsBuilder() {}
{
}
public OptionsBuilder withStartPage(final String startPage) public OptionsBuilder withStartPage(final String startPage)
{ {

View File

@ -33,11 +33,18 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static org.springframework.http.HttpHeaders.ACCEPT;
import static org.springframework.http.HttpHeaders.CONTENT_DISPOSITION;
import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.OK; import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.http.MediaType.IMAGE_PNG_VALUE;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 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.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.util.StringUtils.getFilenameExtension;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -63,14 +70,11 @@ import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile; import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.util.StringUtils;
/** /**
* Test the ImageMagickController without a server. * Test the ImageMagickController without a server.
@ -117,7 +121,8 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest
expectedSourceSuffix = null; expectedSourceSuffix = null;
expectedSourceFileBytes = readTestFile(sourceExtension); expectedSourceFileBytes = readTestFile(sourceExtension);
expectedTargetFileBytes = readTargetFileBytes ? readTestFile(targetExtension) : null; expectedTargetFileBytes = readTargetFileBytes ? readTestFile(targetExtension) : null;
sourceFile = new MockMultipartFile("file", "quick." + sourceExtension, sourceMimetype, expectedSourceFileBytes); sourceFile = new MockMultipartFile("file", "quick." + sourceExtension, sourceMimetype,
expectedSourceFileBytes);
when(mockTransformCommand.execute(any(), anyLong())).thenAnswer( when(mockTransformCommand.execute(any(), anyLong())).thenAnswer(
(Answer<RuntimeExec.ExecutionResult>) invocation -> { (Answer<RuntimeExec.ExecutionResult>) invocation -> {
@ -127,14 +132,17 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest
String actualOptions = actualProperties.get("options"); String actualOptions = actualProperties.get("options");
String actualSource = actualProperties.get("source"); String actualSource = actualProperties.get("source");
String actualTarget = actualProperties.get("target"); String actualTarget = actualProperties.get("target");
String actualTargetExtension = StringUtils.getFilenameExtension(actualTarget); String actualTargetExtension = getFilenameExtension(actualTarget);
assertNotNull(actualSource); assertNotNull(actualSource);
assertNotNull(actualTarget); assertNotNull(actualTarget);
if (expectedSourceSuffix != null) if (expectedSourceSuffix != null)
{ {
assertTrue("The source file \""+actualSource+"\" should have ended in \""+expectedSourceSuffix+"\"", actualSource.endsWith(expectedSourceSuffix)); assertTrue(
actualSource = actualSource.substring(0, actualSource.length()-expectedSourceSuffix.length()); "The source file \"" + actualSource + "\" should have ended in \"" + expectedSourceSuffix + "\"",
actualSource.endsWith(expectedSourceSuffix));
actualSource = actualSource.substring(0,
actualSource.length() - expectedSourceSuffix.length());
} }
assertNotNull(actualOptions); assertNotNull(actualOptions);
@ -154,7 +162,7 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest
int i = actualTarget.lastIndexOf('_'); int i = actualTarget.lastIndexOf('_');
if (i >= 0) if (i >= 0)
{ {
String testFilename = actualTarget.substring(i+1); String testFilename = actualTarget.substring(i + 1);
File testFile = getTestFile(testFilename, false); File testFile = getTestFile(testFilename, false);
File targetFile = new File(actualTarget); File targetFile = new File(actualTarget);
generateTargetFileFromResourceFile(actualTargetExtension, testFile, generateTargetFileFromResourceFile(actualTargetExtension, testFile,
@ -163,7 +171,8 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest
// Check the supplied source file has not been changed. // Check the supplied source file has not been changed.
byte[] actualSourceFileBytes = Files.readAllBytes(new File(actualSource).toPath()); byte[] actualSourceFileBytes = Files.readAllBytes(new File(actualSource).toPath());
assertTrue("Source file is not the same", Arrays.equals(expectedSourceFileBytes, actualSourceFileBytes)); assertTrue("Source file is not the same",
Arrays.equals(expectedSourceFileBytes, actualSourceFileBytes));
return mockExecutionResult; return mockExecutionResult;
}); });
@ -173,7 +182,6 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest
when(mockExecutionResult.getStdOut()).thenReturn("STDOUT"); when(mockExecutionResult.getStdOut()).thenReturn("STDOUT");
} }
@Override @Override
protected AbstractTransformerController getController() protected AbstractTransformerController getController()
{ {
@ -183,23 +191,28 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest
@Test @Test
public void cropGravityGoodTest() throws Exception public void cropGravityGoodTest() throws Exception
{ {
for (String value: new String[] {"North", "NorthEast", "East", "SouthEast", "South", "SouthWest", "West", "NorthWest", "Center"}) for (String value : new String[]{"North", "NorthEast", "East", "SouthEast", "South", "SouthWest", "West", "NorthWest", "Center"})
{ {
expectedOptions = "-gravity "+value+" +repage"; expectedOptions = "-gravity " + value + " +repage";
mockMvc.perform(MockMvcRequestBuilders.multipart("/transform") mockMvc
.perform(MockMvcRequestBuilders
.multipart("/transform")
.file(sourceFile) .file(sourceFile)
.param("targetExtension", targetExtension) .param("targetExtension", targetExtension)
.param("cropGravity", value)) .param("cropGravity", value))
.andExpect(status().is(OK.value())) .andExpect(status().is(OK.value()))
.andExpect(content().bytes(expectedTargetFileBytes)) .andExpect(content().bytes(expectedTargetFileBytes))
.andExpect(header().string("Content-Disposition", "attachment; filename*= UTF-8''quick."+targetExtension)); .andExpect(header().string("Content-Disposition",
"attachment; filename*= UTF-8''quick." + targetExtension));
} }
} }
@Test @Test
public void cropGravityBadTest() throws Exception public void cropGravityBadTest() throws Exception
{ {
mockMvc.perform(MockMvcRequestBuilders.multipart("/transform") mockMvc
.perform(MockMvcRequestBuilders
.multipart("/transform")
.file(sourceFile) .file(sourceFile)
.param("targetExtension", targetExtension) .param("targetExtension", targetExtension)
.param("cropGravity", "badValue")) .param("cropGravity", "badValue"))
@ -211,7 +224,9 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest
{ {
expectedOptions = "-alpha remove -gravity SouthEast -crop 123x456%+90+12 +repage -thumbnail 321x654%!"; expectedOptions = "-alpha remove -gravity SouthEast -crop 123x456%+90+12 +repage -thumbnail 321x654%!";
expectedSourceSuffix = "[2-3]"; expectedSourceSuffix = "[2-3]";
mockMvc.perform(MockMvcRequestBuilders.multipart("/transform") mockMvc
.perform(MockMvcRequestBuilders
.multipart("/transform")
.file(sourceFile) .file(sourceFile)
.param("targetExtension", targetExtension) .param("targetExtension", targetExtension)
@ -234,10 +249,10 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest
.param("resizePercentage", "true") .param("resizePercentage", "true")
.param("allowEnlargement", "true") .param("allowEnlargement", "true")
.param("maintainAspectRatio", "true")) .param("maintainAspectRatio", "true"))
.andExpect(status().is(OK.value())) .andExpect(status().is(OK.value()))
.andExpect(content().bytes(expectedTargetFileBytes)) .andExpect(content().bytes(expectedTargetFileBytes))
.andExpect(header().string("Content-Disposition", "attachment; filename*= UTF-8''quick."+targetExtension)); .andExpect(header().string("Content-Disposition",
"attachment; filename*= UTF-8''quick." + targetExtension));
} }
@Test @Test
@ -245,7 +260,9 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest
{ {
expectedOptions = "-auto-orient -gravity SouthEast -crop 123x456+90+12 +repage -resize 321x654>"; expectedOptions = "-auto-orient -gravity SouthEast -crop 123x456+90+12 +repage -resize 321x654>";
expectedSourceSuffix = "[2-3]"; expectedSourceSuffix = "[2-3]";
mockMvc.perform(MockMvcRequestBuilders.multipart("/transform") mockMvc
.perform(MockMvcRequestBuilders
.multipart("/transform")
.file(sourceFile) .file(sourceFile)
.param("targetExtension", targetExtension) .param("targetExtension", targetExtension)
@ -268,10 +285,10 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest
.param("resizePercentage", "false") .param("resizePercentage", "false")
.param("allowEnlargement", "false") .param("allowEnlargement", "false")
.param("maintainAspectRatio", "false")) .param("maintainAspectRatio", "false"))
.andExpect(status().is(OK.value())) .andExpect(status().is(OK.value()))
.andExpect(content().bytes(expectedTargetFileBytes)) .andExpect(content().bytes(expectedTargetFileBytes))
.andExpect(header().string("Content-Disposition", "attachment; filename*= UTF-8''quick."+targetExtension)); .andExpect(header().string("Content-Disposition",
"attachment; filename*= UTF-8''quick." + targetExtension));
} }
@Test @Test
@ -279,7 +296,9 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest
{ {
// Example of why the commandOptions parameter is a bad idea. // Example of why the commandOptions parameter is a bad idea.
expectedOptions = "( horrible command / ); -resize 321x654>"; expectedOptions = "( horrible command / ); -resize 321x654>";
mockMvc.perform(MockMvcRequestBuilders.multipart("/transform") mockMvc
.perform(MockMvcRequestBuilders
.multipart("/transform")
.file(sourceFile) .file(sourceFile)
.param("targetExtension", targetExtension) .param("targetExtension", targetExtension)
.param("thumbnail", "false") .param("thumbnail", "false")
@ -288,7 +307,8 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest
.param("commandOptions", "( horrible command / );")) .param("commandOptions", "( horrible command / );"))
.andExpect(status().is(OK.value())) .andExpect(status().is(OK.value()))
.andExpect(content().bytes(expectedTargetFileBytes)) .andExpect(content().bytes(expectedTargetFileBytes))
.andExpect(header().string("Content-Disposition", "attachment; filename*= UTF-8''quick."+targetExtension)); .andExpect(header().string("Content-Disposition",
"attachment; filename*= UTF-8''quick." + targetExtension));
} }
@Override @Override
@ -296,8 +316,8 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest
{ {
transformRequest.setSourceExtension("png"); transformRequest.setSourceExtension("png");
transformRequest.setTargetExtension("png"); transformRequest.setTargetExtension("png");
transformRequest.setSourceMediaType(MediaType.IMAGE_PNG_VALUE); transformRequest.setSourceMediaType(IMAGE_PNG_VALUE);
transformRequest.setTargetMediaType(MediaType.IMAGE_PNG_VALUE); transformRequest.setTargetMediaType(IMAGE_PNG_VALUE);
} }
@Test @Test
@ -307,7 +327,8 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest
mockMvc.perform(mockMvcRequest("/transform", sourceFile, "targetExtension", "xxx")) mockMvc.perform(mockMvcRequest("/transform", sourceFile, "targetExtension", "xxx"))
.andExpect(status().is(BAD_REQUEST.value())) .andExpect(status().is(BAD_REQUEST.value()))
.andExpect(status().reason(containsString("Transformer exit code was not 0: \nSTDERR"))); .andExpect(
status().reason(containsString("Transformer exit code was not 0: \nSTDERR")));
} }
@Test @Test
@ -318,7 +339,6 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest
File sourceFile = getTestFile("quick." + sourceExtension, true); File sourceFile = getTestFile("quick." + sourceExtension, true);
String targetFileRef = UUID.randomUUID().toString(); String targetFileRef = UUID.randomUUID().toString();
// Transformation Request POJO // Transformation Request POJO
TransformRequest transformRequest = new TransformRequest(); TransformRequest transformRequest = new TransformRequest();
transformRequest.setRequestId("1"); transformRequest.setRequestId("1");
@ -332,12 +352,13 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest
// HTTP Request // HTTP Request
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=quick." + sourceExtension); headers.set(CONTENT_DISPOSITION, "attachment; filename=quick." + sourceExtension);
ResponseEntity<Resource> response = new ResponseEntity<>(new FileSystemResource( ResponseEntity<Resource> response = new ResponseEntity<>(new FileSystemResource(
sourceFile), headers, OK); sourceFile), headers, OK);
when(alfrescoSharedFileStoreClient.retrieveFile(sourceFileRef)).thenReturn(response); when(alfrescoSharedFileStoreClient.retrieveFile(sourceFileRef)).thenReturn(response);
when(alfrescoSharedFileStoreClient.saveFile(any())).thenReturn(new FileRefResponse(new FileRefEntity(targetFileRef))); when(alfrescoSharedFileStoreClient.saveFile(any()))
.thenReturn(new FileRefResponse(new FileRefEntity(targetFileRef)));
when(mockExecutionResult.getExitValue()).thenReturn(0); when(mockExecutionResult.getExitValue()).thenReturn(0);
// Update the Transformation Request with any specific params before sending it // Update the Transformation Request with any specific params before sending it
@ -345,18 +366,21 @@ public class ImageMagickControllerTest extends AbstractTransformerControllerTest
// Serialize and call the transformer // Serialize and call the transformer
String tr = objectMapper.writeValueAsString(transformRequest); String tr = objectMapper.writeValueAsString(transformRequest);
String transformationReplyAsString = mockMvc.perform(MockMvcRequestBuilders.post("/transform") String transformationReplyAsString = mockMvc
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .perform(MockMvcRequestBuilders
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).content(tr)) .post("/transform")
.andExpect(status().is(HttpStatus.CREATED.value())) .header(ACCEPT, APPLICATION_JSON_VALUE)
.header(CONTENT_TYPE, APPLICATION_JSON_VALUE)
.content(tr))
.andExpect(status().is(CREATED.value()))
.andReturn().getResponse().getContentAsString(); .andReturn().getResponse().getContentAsString();
TransformReply transformReply = objectMapper.readValue(transformationReplyAsString, TransformReply.class); TransformReply transformReply = objectMapper.readValue(transformationReplyAsString,
TransformReply.class);
// Assert the reply // Assert the reply
assertEquals(transformRequest.getRequestId(), transformReply.getRequestId()); assertEquals(transformRequest.getRequestId(), transformReply.getRequestId());
assertEquals(transformRequest.getClientData(), transformReply.getClientData()); assertEquals(transformRequest.getClientData(), transformReply.getClientData());
assertEquals(transformRequest.getSchema(), transformReply.getSchema()); assertEquals(transformRequest.getSchema(), transformReply.getSchema());
} }
} }

View File

@ -48,7 +48,8 @@ public class ImageMagickQueueTransformServiceIT extends AbstractQueueTransformSe
@Override @Override
protected TransformRequest buildRequest() protected TransformRequest buildRequest()
{ {
return TransformRequest.builder() return TransformRequest
.builder()
.withRequestId(UUID.randomUUID().toString()) .withRequestId(UUID.randomUUID().toString())
.withSourceMediaType(MIMETYPE_IMAGE_PNG) .withSourceMediaType(MIMETYPE_IMAGE_PNG)
.withTargetMediaType(MIMETYPE_IMAGE_JPEG) .withTargetMediaType(MIMETYPE_IMAGE_JPEG)
@ -56,6 +57,7 @@ public class ImageMagickQueueTransformServiceIT extends AbstractQueueTransformSe
.withSchema(1) .withSchema(1)
.withClientData("ACS") .withClientData("ACS")
.withSourceReference(UUID.randomUUID().toString()) .withSourceReference(UUID.randomUUID().toString())
.withSourceSize(32L).build(); .withSourceSize(32L)
.build();
} }
} }

View File

@ -26,25 +26,36 @@
*/ */
package org.alfresco.transformer; package org.alfresco.transformer;
import io.micrometer.core.instrument.MeterRegistry; import static org.alfresco.transformer.logging.StandardMessages.LICENCE;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer; import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.event.EventListener;
import io.micrometer.core.instrument.MeterRegistry;
@SpringBootApplication @SpringBootApplication
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) @EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class Application public class Application
{ {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Value("${container.name}") @Value("${container.name}")
private String containerName; private String containerName;
@Bean @Bean
MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() { MeterRegistryCustomizer<MeterRegistry> metricsCommonTags()
{
return registry -> registry.config().commonTags("containerName", containerName); return registry -> registry.config().commonTags("containerName", containerName);
} }
@ -52,4 +63,15 @@ public class Application
{ {
SpringApplication.run(Application.class, args); SpringApplication.run(Application.class, args);
} }
@EventListener(ApplicationReadyEvent.class)
public void startup()
{
logger.info("-------------------------------------------------------------------------------------------------------------------------------------------------------");
Arrays.stream(LICENCE.split("\\n")).forEach(logger::info);
logger.info("This transformer uses LibreOffice from The Document Foundation. See the license at https://www.libreoffice.org/download/license/ or in /libreoffice.txt");
logger.info("-------------------------------------------------------------------------------------------------------------------------------------------------------");
logger.info("Starting application components... Done");
}
} }

View File

@ -30,11 +30,10 @@ import static org.alfresco.transformer.fs.FileManager.createAttachment;
import static org.alfresco.transformer.fs.FileManager.createSourceFile; import static org.alfresco.transformer.fs.FileManager.createSourceFile;
import static org.alfresco.transformer.fs.FileManager.createTargetFile; import static org.alfresco.transformer.fs.FileManager.createTargetFile;
import static org.alfresco.transformer.fs.FileManager.createTargetFileName; import static org.alfresco.transformer.fs.FileManager.createTargetFileName;
import static org.alfresco.transformer.logging.StandardMessages.LICENCE;
import static org.springframework.http.HttpStatus.OK; import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
import java.io.File; import java.io.File;
import java.util.Arrays;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -46,7 +45,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -82,15 +80,6 @@ public class LibreOfficeController extends AbstractTransformerController
@Autowired @Autowired
private LibreOfficeJavaExecutor javaExecutor; private LibreOfficeJavaExecutor javaExecutor;
@Autowired
public LibreOfficeController()
{
logger.info("-------------------------------------------------------------------------------------------------------------------------------------------------------");
Arrays.stream(LICENCE.split("\\n")).forEach(logger::info);
logger.info("This transformer uses LibreOffice from The Document Foundation. See the license at https://www.libreoffice.org/download/license/ or in /libreoffice.txt");
logger.info("-------------------------------------------------------------------------------------------------------------------------------------------------------");
}
@Override @Override
public String getTransformerName() public String getTransformerName()
{ {
@ -108,7 +97,7 @@ public class LibreOfficeController extends AbstractTransformerController
{ {
// See the Javadoc on this method and Probes.md for the choice of these values. // See the Javadoc on this method and Probes.md for the choice of these values.
return new ProbeTestTransform(this, "quick.doc", "quick.pdf", return new ProbeTestTransform(this, "quick.doc", "quick.pdf",
11817, 1024, 150, 10240, 60*30+1, 60*15+20) 11817, 1024, 150, 10240, 60 * 30 + 1, 60 * 15 + 20)
{ {
@Override @Override
protected void executeTransformCommand(File sourceFile, File targetFile) protected void executeTransformCommand(File sourceFile, File targetFile)
@ -119,14 +108,15 @@ public class LibreOfficeController extends AbstractTransformerController
} }
//todo: the "timeout" request parameter is ignored; the timeout is preset at JodConverter creation //todo: the "timeout" request parameter is ignored; the timeout is preset at JodConverter creation
@PostMapping(value = "/transform", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @PostMapping(value = "/transform", consumes = MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<Resource> transform(HttpServletRequest request, public ResponseEntity<Resource> transform(HttpServletRequest request,
@RequestParam("file") MultipartFile sourceMultipartFile, @RequestParam("file") MultipartFile sourceMultipartFile,
@RequestParam("targetExtension") String targetExtension, @RequestParam("targetExtension") String targetExtension,
@RequestParam(value = "timeout", required = false) Long timeout, @RequestParam(value = "timeout", required = false) Long timeout,
@RequestParam(value = "testDelay", required = false) Long testDelay) @RequestParam(value = "testDelay", required = false) Long testDelay)
{ {
String targetFilename = createTargetFileName(sourceMultipartFile.getOriginalFilename(), targetExtension); String targetFilename = createTargetFileName(sourceMultipartFile.getOriginalFilename(),
targetExtension);
getProbeTestTransform().incrementTransformerCount(); getProbeTestTransform().incrementTransformerCount();
File sourceFile = createSourceFile(request, sourceMultipartFile); File sourceFile = createSourceFile(request, sourceMultipartFile);
File targetFile = createTargetFile(request, targetFilename); File targetFile = createTargetFile(request, targetFilename);

View File

@ -34,12 +34,14 @@ public interface JodConverter
{ {
/** /**
* Gets the JodConverter OfficeManager. * Gets the JodConverter OfficeManager.
*
* @return * @return
*/ */
OfficeManager getOfficeManager(); OfficeManager getOfficeManager();
/** /**
* This method returns a boolean indicating whether the JodConverter connection to OOo is available. * This method returns a boolean indicating whether the JodConverter connection to OOo is available.
*
* @return <code>true</code> if available, else <code>false</code> * @return <code>true</code> if available, else <code>false</code>
*/ */
boolean isAvailable(); boolean isAvailable();

View File

@ -128,7 +128,7 @@ public class JodConverterSharedInstance implements JodConverter
StringTokenizer tokenizer = new StringTokenizer(s, ","); StringTokenizer tokenizer = new StringTokenizer(s, ",");
int tokenCount = tokenizer.countTokens(); int tokenCount = tokenizer.countTokens();
portNumbers = new int[tokenCount]; portNumbers = new int[tokenCount];
for (int i = 0;tokenizer.hasMoreTokens();i++) for (int i = 0; tokenizer.hasMoreTokens(); i++)
{ {
try try
{ {
@ -163,7 +163,8 @@ public class JodConverterSharedInstance implements JodConverter
File tmp = new File(templateProfileDir); File tmp = new File(templateProfileDir);
if (!tmp.isDirectory()) if (!tmp.isDirectory())
{ {
throw new AlfrescoRuntimeException("OpenOffice template profile directory "+templateProfileDir+" does not exist."); throw new AlfrescoRuntimeException(
"OpenOffice template profile directory " + templateProfileDir + " does not exist.");
} }
this.templateProfileDir = tmp; this.templateProfileDir = tmp;
} }
@ -294,7 +295,8 @@ public class JodConverterSharedInstance implements JodConverter
String officeHome = getOfficeHome(); String officeHome = getOfficeHome();
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
logger.debug("JodConverter settings (null settings will be replaced by jodconverter defaults):"); logger.debug(
"JodConverter settings (null settings will be replaced by jodconverter defaults):");
logger.debug(" officeHome = {}", officeHome); logger.debug(" officeHome = {}", officeHome);
logger.debug(" enabled = {}", isEnabled()); logger.debug(" enabled = {}", isEnabled());
logger.debug(" portNumbers = {}", getString(portNumbers)); logger.debug(" portNumbers = {}", getString(portNumbers));
@ -390,7 +392,7 @@ public class JodConverterSharedInstance implements JodConverter
StringBuilder portInfo = new StringBuilder(); StringBuilder portInfo = new StringBuilder();
if (portNumbers != null) if (portNumbers != null)
{ {
for (int i = 0;i < portNumbers.length;i++) for (int i = 0; i < portNumbers.length; i++)
{ {
portInfo.append(portNumbers[i]); portInfo.append(portNumbers[i]);
if (i < portNumbers.length - 1) if (i < portNumbers.length - 1)
@ -422,7 +424,8 @@ public class JodConverterSharedInstance implements JodConverter
} }
} }
private List<File> findSofficePrograms(File searchRoot, List<File> results, int maxRecursionDepth) private List<File> findSofficePrograms(File searchRoot, List<File> results,
int maxRecursionDepth)
{ {
return this.findSofficePrograms(searchRoot, results, 0, maxRecursionDepth); return this.findSofficePrograms(searchRoot, results, 0, maxRecursionDepth);
} }
@ -448,6 +451,7 @@ public class JodConverterSharedInstance implements JodConverter
/** /**
* Logs some information on the specified file, including name and r/w/x permissions. * Logs some information on the specified file, including name and r/w/x permissions.
*
* @param f the file to log. * @param f the file to log.
*/ */
private void logFileInfo(File f) private void logFileInfo(File f)
@ -459,9 +463,7 @@ public class JodConverterSharedInstance implements JodConverter
StringBuilder msg = new StringBuilder(); StringBuilder msg = new StringBuilder();
msg.append(f).append(" "); msg.append(f).append(" ");
if (f.exists()) if (f.exists() && f.canRead())
{
if (f.canRead())
{ {
msg.append("(") msg.append("(")
.append(f.isDirectory() ? "d" : "-") .append(f.isDirectory() ? "d" : "-")
@ -470,7 +472,6 @@ public class JodConverterSharedInstance implements JodConverter
.append(f.canExecute() ? "x" : "-") .append(f.canExecute() ? "x" : "-")
.append(")"); .append(")");
} }
}
else else
{ {
msg.append("does not exist"); msg.append("does not exist");

View File

@ -35,14 +35,14 @@ import java.io.IOException;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import org.alfresco.transform.exceptions.TransformException; import org.alfresco.transform.exceptions.TransformException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.artofsolving.jodconverter.OfficeDocumentConverter; import org.artofsolving.jodconverter.OfficeDocumentConverter;
import org.artofsolving.jodconverter.office.OfficeException; import org.artofsolving.jodconverter.office.OfficeException;
import org.artofsolving.jodconverter.office.OfficeManager; import org.artofsolving.jodconverter.office.OfficeManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.sun.star.task.ErrorCodeIOException; import com.sun.star.task.ErrorCodeIOException;

View File

@ -34,7 +34,15 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static org.springframework.http.HttpHeaders.ACCEPT;
import static org.springframework.http.HttpHeaders.CONTENT_DISPOSITION;
import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.http.MediaType.IMAGE_PNG_VALUE;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.util.StringUtils.getFilenameExtension;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -59,13 +67,10 @@ import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile; import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.util.StringUtils;
/** /**
* Test the LibreOfficeController without a server. * Test the LibreOfficeController without a server.
@ -94,15 +99,18 @@ public class LibreOfficeControllerTest extends AbstractTransformerControllerTest
// The following is based on super.mockTransformCommand(...) // The following is based on super.mockTransformCommand(...)
// This is because LibreOffice used JodConverter rather than a RuntimeExec // This is because LibreOffice used JodConverter rather than a RuntimeExec
expectedSourceFileBytes = Files.readAllBytes(getTestFile("quick." + sourceExtension, true).toPath()); expectedSourceFileBytes = Files.readAllBytes(
expectedTargetFileBytes = Files.readAllBytes(getTestFile("quick." + targetExtension, true).toPath()); getTestFile("quick." + sourceExtension, true).toPath());
sourceFile = new MockMultipartFile("file", "quick." + sourceExtension, sourceMimetype, expectedSourceFileBytes); expectedTargetFileBytes = Files.readAllBytes(
getTestFile("quick." + targetExtension, true).toPath());
sourceFile = new MockMultipartFile("file", "quick." + sourceExtension, sourceMimetype,
expectedSourceFileBytes);
doAnswer(invocation -> doAnswer(invocation ->
{ {
File sourceFile = invocation.getArgument(0); File sourceFile = invocation.getArgument(0);
File targetFile = invocation.getArgument(1); File targetFile = invocation.getArgument(1);
String actualTargetExtension = StringUtils.getFilenameExtension(targetFile.getAbsolutePath()); String actualTargetExtension = getFilenameExtension(targetFile.getAbsolutePath());
assertNotNull(sourceFile); assertNotNull(sourceFile);
assertNotNull(targetFile); assertNotNull(targetFile);
@ -119,7 +127,8 @@ public class LibreOfficeControllerTest extends AbstractTransformerControllerTest
// Check the supplied source file has not been changed. // Check the supplied source file has not been changed.
byte[] actualSourceFileBytes = Files.readAllBytes(sourceFile.toPath()); byte[] actualSourceFileBytes = Files.readAllBytes(sourceFile.toPath());
assertTrue("Source file is not the same", Arrays.equals(expectedSourceFileBytes, actualSourceFileBytes)); assertTrue("Source file is not the same",
Arrays.equals(expectedSourceFileBytes, actualSourceFileBytes));
return null; return null;
}).when(javaExecutor).convert(any(), any()); }).when(javaExecutor).convert(any(), any());
@ -143,11 +152,14 @@ public class LibreOfficeControllerTest extends AbstractTransformerControllerTest
{ {
doThrow(OfficeException.class).when(javaExecutor).convert(any(), any()); doThrow(OfficeException.class).when(javaExecutor).convert(any(), any());
mockMvc.perform(MockMvcRequestBuilders.multipart("/transform") mockMvc
.perform(MockMvcRequestBuilders
.multipart("/transform")
.file(sourceFile) .file(sourceFile)
.param("targetExtension", "xxx")) .param("targetExtension", "xxx"))
.andExpect(status().is(400)) .andExpect(status().is(400))
.andExpect(status().reason(containsString("LibreOffice - LibreOffice server conversion failed:"))); .andExpect(status().reason(
containsString("LibreOffice - LibreOffice server conversion failed:")));
} }
@Override @Override
@ -156,7 +168,7 @@ public class LibreOfficeControllerTest extends AbstractTransformerControllerTest
transformRequest.setSourceExtension("doc"); transformRequest.setSourceExtension("doc");
transformRequest.setTargetExtension("pdf"); transformRequest.setTargetExtension("pdf");
transformRequest.setSourceMediaType("application/msword"); transformRequest.setSourceMediaType("application/msword");
transformRequest.setTargetMediaType(MediaType.IMAGE_PNG_VALUE); transformRequest.setTargetMediaType(IMAGE_PNG_VALUE);
} }
@Test @Test
@ -180,14 +192,13 @@ public class LibreOfficeControllerTest extends AbstractTransformerControllerTest
// HTTP Request // HTTP Request
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.CONTENT_DISPOSITION, headers.set(CONTENT_DISPOSITION, "attachment; filename=quick." + sourceExtension);
"attachment; filename=quick." + sourceExtension);
ResponseEntity<Resource> response = new ResponseEntity<>(new FileSystemResource( ResponseEntity<Resource> response = new ResponseEntity<>(new FileSystemResource(
sourceFile), headers, HttpStatus.OK); sourceFile), headers, OK);
when(alfrescoSharedFileStoreClient.retrieveFile(sourceFileRef)).thenReturn(response); when(alfrescoSharedFileStoreClient.retrieveFile(sourceFileRef)).thenReturn(response);
when(alfrescoSharedFileStoreClient.saveFile(any())).thenReturn( when(alfrescoSharedFileStoreClient.saveFile(any()))
new FileRefResponse(new FileRefEntity(targetFileRef))); .thenReturn(new FileRefResponse(new FileRefEntity(targetFileRef)));
when(mockExecutionResult.getExitValue()).thenReturn(0); when(mockExecutionResult.getExitValue()).thenReturn(0);
// Update the Transformation Request with any specific params before sending it // Update the Transformation Request with any specific params before sending it
@ -195,13 +206,13 @@ public class LibreOfficeControllerTest extends AbstractTransformerControllerTest
// Serialize and call the transformer // Serialize and call the transformer
String tr = objectMapper.writeValueAsString(transformRequest); String tr = objectMapper.writeValueAsString(transformRequest);
String transformationReplyAsString = mockMvc.perform( String transformationReplyAsString = mockMvc
MockMvcRequestBuilders.post("/transform") .perform(MockMvcRequestBuilders
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .post("/transform")
.header(HttpHeaders.CONTENT_TYPE, .header(ACCEPT, APPLICATION_JSON_VALUE)
MediaType.APPLICATION_JSON_VALUE).content(tr)) .header(CONTENT_TYPE, APPLICATION_JSON_VALUE)
.andExpect( .content(tr))
status().is(HttpStatus.CREATED.value())) .andExpect(status().is(CREATED.value()))
.andReturn().getResponse().getContentAsString(); .andReturn().getResponse().getContentAsString();
TransformReply transformReply = objectMapper.readValue(transformationReplyAsString, TransformReply transformReply = objectMapper.readValue(transformationReplyAsString,

View File

@ -47,7 +47,8 @@ public class LibreOfficeQueueTransformServiceIT extends AbstractQueueTransformSe
@Override @Override
protected TransformRequest buildRequest() protected TransformRequest buildRequest()
{ {
return TransformRequest.builder() return TransformRequest
.builder()
.withRequestId(UUID.randomUUID().toString()) .withRequestId(UUID.randomUUID().toString())
.withSourceMediaType(MIMETYPE_OPENXML_WORDPROCESSING) .withSourceMediaType(MIMETYPE_OPENXML_WORDPROCESSING)
.withTargetMediaType(MIMETYPE_OPENXML_WORDPROCESSING) .withTargetMediaType(MIMETYPE_OPENXML_WORDPROCESSING)
@ -55,6 +56,7 @@ public class LibreOfficeQueueTransformServiceIT extends AbstractQueueTransformSe
.withSchema(1) .withSchema(1)
.withClientData("ACS") .withClientData("ACS")
.withSourceReference(UUID.randomUUID().toString()) .withSourceReference(UUID.randomUUID().toString())
.withSourceSize(32L).build(); .withSourceSize(32L)
.build();
} }
} }

View File

@ -26,20 +26,30 @@
*/ */
package org.alfresco.transformer; package org.alfresco.transformer;
import static org.alfresco.transformer.logging.StandardMessages.LICENCE;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer; import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.event.EventListener;
import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.MeterRegistry;
@SpringBootApplication @SpringBootApplication
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) @EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class Application public class Application
{ {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Value("${container.name}") @Value("${container.name}")
private String containerName; private String containerName;
@ -53,4 +63,15 @@ public class Application
{ {
SpringApplication.run(Application.class, args); SpringApplication.run(Application.class, args);
} }
@EventListener(ApplicationReadyEvent.class)
public void startup()
{
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
Arrays.stream(LICENCE.split("\\n")).forEach(logger::info);
logger.info("Tika is from Apache. See the license at http://www.apache.org/licenses/LICENSE-2.0. or in /Apache\\ 2.0.txt");
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
logger.info("Starting application components... Done");
}
} }

View File

@ -37,13 +37,12 @@ import static org.alfresco.transformer.fs.FileManager.createAttachment;
import static org.alfresco.transformer.fs.FileManager.createSourceFile; import static org.alfresco.transformer.fs.FileManager.createSourceFile;
import static org.alfresco.transformer.fs.FileManager.createTargetFile; import static org.alfresco.transformer.fs.FileManager.createTargetFile;
import static org.alfresco.transformer.fs.FileManager.createTargetFileName; import static org.alfresco.transformer.fs.FileManager.createTargetFileName;
import static org.alfresco.transformer.logging.StandardMessages.LICENCE;
import static org.alfresco.transformer.util.Util.stringToBoolean; import static org.alfresco.transformer.util.Util.stringToBoolean;
import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.OK; import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
import java.io.File; import java.io.File;
import java.util.Arrays;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -56,7 +55,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -69,9 +67,9 @@ import org.springframework.web.multipart.MultipartFile;
* Status Codes: * Status Codes:
* *
* 200 Success * 200 Success
* 400 Bad Request: Invalid target mimetype &lt;mimetype> * 400 Bad Request: Invalid target mimetype <mimetype>
* 400 Bad Request: Request parameter &lt;name> is missing (missing mandatory parameter) * 400 Bad Request: Request parameter <name> is missing (missing mandatory parameter)
* 400 Bad Request: Request parameter &lt;name> is of the wrong type * 400 Bad Request: Request parameter <name> is of the wrong type
* 400 Bad Request: Transformer exit code was not 0 (possible problem with the source file) * 400 Bad Request: Transformer exit code was not 0 (possible problem with the source file)
* 400 Bad Request: The source filename was not supplied * 400 Bad Request: The source filename was not supplied
* 500 Internal Server Error: (no message with low level IO problems) * 500 Internal Server Error: (no message with low level IO problems)
@ -92,15 +90,6 @@ public class TikaController extends AbstractTransformerController
@Autowired @Autowired
private TikaJavaExecutor javaExecutor; private TikaJavaExecutor javaExecutor;
@Autowired
public TikaController()
{
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
Arrays.stream(LICENCE.split("\\n")).forEach(logger::info);
logger.info("Tika is from Apache. See the license at http://www.apache.org/licenses/LICENSE-2.0. or in /Apache\\ 2.0.txt");
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
}
@Override @Override
public String getTransformerName() public String getTransformerName()
{ {
@ -130,7 +119,7 @@ public class TikaController extends AbstractTransformerController
}; };
} }
@PostMapping(value = "/transform", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @PostMapping(value = "/transform", consumes = MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<Resource> transform(HttpServletRequest request, public ResponseEntity<Resource> transform(HttpServletRequest request,
@RequestParam("file") MultipartFile sourceMultipartFile, @RequestParam("file") MultipartFile sourceMultipartFile,
@RequestParam("targetExtension") String targetExtension, @RequestParam("targetExtension") String targetExtension,
@ -149,7 +138,8 @@ public class TikaController extends AbstractTransformerController
throw new TransformException(BAD_REQUEST.value(), "Invalid transform value"); throw new TransformException(BAD_REQUEST.value(), "Invalid transform value");
} }
String targetFilename = createTargetFileName(sourceMultipartFile.getOriginalFilename(), targetExtension); String targetFilename = createTargetFileName(sourceMultipartFile.getOriginalFilename(),
targetExtension);
getProbeTestTransform().incrementTransformerCount(); getProbeTestTransform().incrementTransformerCount();
File sourceFile = createSourceFile(request, sourceMultipartFile); File sourceFile = createSourceFile(request, sourceMultipartFile);
File targetFile = createTargetFile(request, targetFilename); File targetFile = createTargetFile(request, targetFilename);

View File

@ -26,7 +26,6 @@
*/ */
package org.alfresco.transformer.executors; package org.alfresco.transformer.executors;
import static java.util.Arrays.asList;
import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_HTML; import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_HTML;
import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_IMAGE_JPEG; import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_IMAGE_JPEG;
import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_IMAGE_PNG; import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_IMAGE_PNG;
@ -74,6 +73,8 @@ import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler; import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import com.google.common.collect.ImmutableList;
/** /**
* Stripped down command line Tika transformers. Not actually run as a separate process, but the code fits the patten * Stripped down command line Tika transformers. Not actually run as a separate process, but the code fits the patten
* used by transformers that do. * used by transformers that do.
@ -455,7 +456,7 @@ public class Tika
public static final String TIKA_AUTO = "TikaAuto"; public static final String TIKA_AUTO = "TikaAuto";
public static final String TEXT_MINING = "TextMining"; public static final String TEXT_MINING = "TextMining";
public static final List<String> TRANSFORM_NAMES = asList( public static final List<String> TRANSFORM_NAMES = ImmutableList.of(
ARCHIVE, OUTLOOK_MSG, PDF_BOX, POI_OFFICE, POI, POI_OO_XML, TIKA_AUTO, TEXT_MINING); ARCHIVE, OUTLOOK_MSG, PDF_BOX, POI_OFFICE, POI, POI_OO_XML, TIKA_AUTO, TEXT_MINING);
public static final String TARGET_MIMETYPE = "--targetMimetype="; public static final String TARGET_MIMETYPE = "--targetMimetype=";
@ -484,9 +485,10 @@ public class Tika
private final Parser tikaOfficeDetectParser = new TikaOfficeDetectParser(); private final Parser tikaOfficeDetectParser = new TikaOfficeDetectParser();
private final PDFParserConfig pdfParserConfig = new PDFParserConfig(); private final PDFParserConfig pdfParserConfig = new PDFParserConfig();
private DocumentSelector pdfBoxEmbededDocumentSelector = new DocumentSelector() private final DocumentSelector pdfBoxEmbededDocumentSelector = new DocumentSelector()
{ {
private final List<String> disabledMediaTypes = asList(MIMETYPE_IMAGE_JPEG, MIMETYPE_IMAGE_TIFF, MIMETYPE_IMAGE_PNG); private final List<String> disabledMediaTypes = ImmutableList.of(MIMETYPE_IMAGE_JPEG,
MIMETYPE_IMAGE_TIFF, MIMETYPE_IMAGE_PNG);
@Override @Override
public boolean select(Metadata metadata) public boolean select(Metadata metadata)
@ -518,16 +520,16 @@ public class Tika
} }
catch (IllegalArgumentException e) catch (IllegalArgumentException e)
{ {
System.err.println("ERROR "+e.getMessage()); System.err.println("ERROR " + e.getMessage());
System.exit(-1); System.exit(-1);
} }
catch (IllegalStateException | TikaException | IOException | SAXException e) catch (IllegalStateException | TikaException | IOException | SAXException e)
{ {
System.err.println("ERROR "+e.getMessage()); System.err.println("ERROR " + e.getMessage());
e.printStackTrace(); e.printStackTrace();
System.exit(-2); System.exit(-2);
} }
System.out.println("Finished in "+(System.currentTimeMillis()-start)+"ms"); System.out.println("Finished in " + (System.currentTimeMillis() - start) + "ms");
} }
// Extracts parameters form args // Extracts parameters form args
@ -541,7 +543,7 @@ public class Tika
Boolean includeContents = null; Boolean includeContents = null;
Boolean notExtractBookmarksText = null; Boolean notExtractBookmarksText = null;
for (String arg: args) for (String arg : args)
{ {
if (arg.startsWith("--")) if (arg.startsWith("--"))
{ {
@ -565,7 +567,7 @@ public class Tika
} }
else else
{ {
throw new IllegalArgumentException("Unexpected argument "+arg); throw new IllegalArgumentException("Unexpected argument " + arg);
} }
} }
else else
@ -584,7 +586,7 @@ public class Tika
} }
else else
{ {
throw new IllegalArgumentException("Unexpected argument "+arg); throw new IllegalArgumentException("Unexpected argument " + arg);
} }
} }
} }
@ -595,23 +597,24 @@ public class Tika
includeContents = includeContents == null ? false : includeContents; includeContents = includeContents == null ? false : includeContents;
notExtractBookmarksText = notExtractBookmarksText == null ? false : notExtractBookmarksText; notExtractBookmarksText = notExtractBookmarksText == null ? false : notExtractBookmarksText;
transform(transform, includeContents, notExtractBookmarksText, sourceFilename, targetFilename, targetMimetype, targetEncoding); transform(transform, includeContents, notExtractBookmarksText, sourceFilename,
targetFilename, targetMimetype, targetEncoding);
} }
private String getValue(String arg, boolean valueExpected, Object value, String optionName) private String getValue(String arg, boolean valueExpected, Object value, String optionName)
{ {
if (value != null) if (value != null)
{ {
throw new IllegalArgumentException("Duplicate "+optionName); throw new IllegalArgumentException("Duplicate " + optionName);
} }
String stringValue = arg.substring(optionName.length()).trim(); String stringValue = arg.substring(optionName.length()).trim();
if (!valueExpected && stringValue.length() > 0) if (!valueExpected && stringValue.length() > 0)
{ {
throw new IllegalArgumentException("Unexpected value with "+optionName); throw new IllegalArgumentException("Unexpected value with " + optionName);
} }
if (valueExpected && stringValue.length() == 0) if (valueExpected && stringValue.length() == 0)
{ {
throw new IllegalArgumentException("Expected value with "+optionName); throw new IllegalArgumentException("Expected value with " + optionName);
} }
return stringValue; return stringValue;
} }
@ -625,7 +628,7 @@ public class Tika
Parser parser = null; Parser parser = null;
DocumentSelector documentSelector = null; DocumentSelector documentSelector = null;
switch(transform) switch (transform)
{ {
case ARCHIVE: case ARCHIVE:
parser = packageParser; parser = packageParser;
@ -650,11 +653,12 @@ public class Tika
break; break;
} }
transform(parser, documentSelector, includeContents, notExtractBookmarksText, sourceFilename, targetFilename, targetMimetype, targetEncoding); transform(parser, documentSelector, includeContents, notExtractBookmarksText,
sourceFilename, targetFilename, targetMimetype, targetEncoding);
} }
private void transform(Parser parser, DocumentSelector documentSelector,
private void transform(Parser parser, DocumentSelector documentSelector, Boolean includeContents, Boolean includeContents,
Boolean notExtractBookmarksText, Boolean notExtractBookmarksText,
String sourceFilename, String sourceFilename,
String targetFilename, String targetMimetype, String targetEncoding) String targetFilename, String targetMimetype, String targetEncoding)
@ -688,7 +692,7 @@ public class Tika
} }
else else
{ {
SAXTransformerFactory factory = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); SAXTransformerFactory factory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
TransformerHandler transformerHandler; TransformerHandler transformerHandler;
transformerHandler = factory.newTransformerHandler(); transformerHandler = factory.newTransformerHandler();
transformerHandler.getTransformer().setOutputProperty(OutputKeys.INDENT, "yes"); transformerHandler.getTransformer().setOutputProperty(OutputKeys.INDENT, "yes");
@ -725,42 +729,52 @@ public class Tika
/** /**
* A wrapper around the normal Tika BodyContentHandler for CSV rather encoding than tab separated. * A wrapper around the normal Tika BodyContentHandler for CSV rather encoding than tab separated.
*/ */
protected static class CsvContentHandler extends BodyContentHandler { protected static class CsvContentHandler extends BodyContentHandler
private static final char[] comma = new char[]{ ',' }; {
private static final char[] comma = new char[]{','};
private static final Pattern all_nums = Pattern.compile("[\\d\\.\\-\\+]+"); private static final Pattern all_nums = Pattern.compile("[\\d\\.\\-\\+]+");
private boolean inCell = false; private boolean inCell = false;
private boolean needsComma = false; private boolean needsComma = false;
protected CsvContentHandler(Writer output) { protected CsvContentHandler(Writer output)
{
super(output); super(output);
} }
@Override @Override
public void ignorableWhitespace(char[] ch, int start, int length) public void ignorableWhitespace(char[] ch, int start, int length)
throws SAXException { throws SAXException
if(length == 1 && ch[0] == '\t') { {
if (length == 1 && ch[0] == '\t')
{
// Ignore tabs, as they mess up the CSV output // Ignore tabs, as they mess up the CSV output
} else { }
else
{
super.ignorableWhitespace(ch, start, length); super.ignorableWhitespace(ch, start, length);
} }
} }
@Override @Override
public void characters(char[] ch, int start, int length) public void characters(char[] ch, int start, int length)
throws SAXException { throws SAXException
if(inCell) { {
StringBuffer t = new StringBuffer(new String(ch,start,length)); if (inCell)
{
StringBuffer t = new StringBuffer(new String(ch, start, length));
// Quote if not all numbers // Quote if not all numbers
if(all_nums.matcher(t).matches()) if (all_nums.matcher(t).matches())
{ {
super.characters(ch, start, length); super.characters(ch, start, length);
} }
else else
{ {
for(int i=t.length()-1; i>=0; i--) { for (int i = t.length() - 1; i >= 0; i--)
if(t.charAt(i) == '\"') { {
if (t.charAt(i) == '\"')
{
// Double up double quotes // Double up double quotes
t.insert(i, '\"'); t.insert(i, '\"');
i--; i--;
@ -771,33 +785,45 @@ public class Tika
char[] c = t.toString().toCharArray(); char[] c = t.toString().toCharArray();
super.characters(c, 0, c.length); super.characters(c, 0, c.length);
} }
} else { }
else
{
super.characters(ch, start, length); super.characters(ch, start, length);
} }
} }
@Override @Override
public void startElement(String uri, String localName, String name, public void startElement(String uri, String localName, String name,
Attributes atts) throws SAXException { Attributes atts) throws SAXException
if(localName.equals("td")) { {
if (localName.equals("td"))
{
inCell = true; inCell = true;
if(needsComma) { if (needsComma)
{
super.characters(comma, 0, 1); super.characters(comma, 0, 1);
needsComma = true; needsComma = true;
} }
} else { }
else
{
super.startElement(uri, localName, name, atts); super.startElement(uri, localName, name, atts);
} }
} }
@Override @Override
public void endElement(String uri, String localName, String name) public void endElement(String uri, String localName, String name)
throws SAXException { throws SAXException
if(localName.equals("td")) { {
if (localName.equals("td"))
{
needsComma = true; needsComma = true;
inCell = false; inCell = false;
} else { }
if(localName.equals("tr")) { else
{
if (localName.equals("tr"))
{
needsComma = false; needsComma = false;
} }
super.endElement(uri, localName, name); super.endElement(uri, localName, name);
@ -830,5 +856,4 @@ public class Tika
return context; return context;
} }
} }

View File

@ -58,11 +58,13 @@ import org.xml.sax.SAXException;
* *
* @author Nick Burch * @author Nick Burch
*/ */
public class TikaOfficeDetectParser implements Parser { public class TikaOfficeDetectParser implements Parser
{
private final Parser ole2Parser = new OfficeParser(); private final Parser ole2Parser = new OfficeParser();
private final Parser ooxmlParser = new OOXMLParser(); private final Parser ooxmlParser = new OOXMLParser();
public Set<MediaType> getSupportedTypes(ParseContext parseContext) { public Set<MediaType> getSupportedTypes(ParseContext parseContext)
{
Set<MediaType> types = new HashSet<>(); Set<MediaType> types = new HashSet<>();
types.addAll(ole2Parser.getSupportedTypes(parseContext)); types.addAll(ole2Parser.getSupportedTypes(parseContext));
types.addAll(ooxmlParser.getSupportedTypes(parseContext)); types.addAll(ooxmlParser.getSupportedTypes(parseContext));
@ -93,7 +95,7 @@ public class TikaOfficeDetectParser implements Parser {
} }
// Which is it? // Which is it?
if(initial4[0] == POIFSConstants.OOXML_FILE_HEADER[0] && if (initial4[0] == POIFSConstants.OOXML_FILE_HEADER[0] &&
initial4[1] == POIFSConstants.OOXML_FILE_HEADER[1] && initial4[1] == POIFSConstants.OOXML_FILE_HEADER[1] &&
initial4[2] == POIFSConstants.OOXML_FILE_HEADER[2] && initial4[2] == POIFSConstants.OOXML_FILE_HEADER[2] &&
initial4[3] == POIFSConstants.OOXML_FILE_HEADER[3]) initial4[3] == POIFSConstants.OOXML_FILE_HEADER[3])

View File

@ -64,10 +64,18 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static org.springframework.http.HttpHeaders.ACCEPT;
import static org.springframework.http.HttpHeaders.CONTENT_DISPOSITION;
import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.OK; import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.http.MediaType.APPLICATION_PDF_VALUE;
import static org.springframework.http.MediaType.TEXT_PLAIN_VALUE;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.util.StringUtils.getFilenameExtension;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -93,15 +101,12 @@ import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile; import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.util.StringUtils;
/** /**
* Test the TikaController without a server. * Test the TikaController without a server.
@ -169,7 +174,7 @@ public class TikaControllerTest extends AbstractTransformerControllerTest
String actualOptions = actualProperties.get("options"); String actualOptions = actualProperties.get("options");
String actualSource = actualProperties.get("source"); String actualSource = actualProperties.get("source");
String actualTarget = actualProperties.get("target"); String actualTarget = actualProperties.get("target");
String actualTargetExtension = StringUtils.getFilenameExtension(actualTarget); String actualTargetExtension = getFilenameExtension(actualTarget);
assertNotNull(actualSource); assertNotNull(actualSource);
assertNotNull(actualTarget); assertNotNull(actualTarget);
@ -234,21 +239,26 @@ public class TikaControllerTest extends AbstractTransformerControllerTest
this.transform = transform; this.transform = transform;
this.targetMimetype = targetMimetype; this.targetMimetype = targetMimetype;
System.out.println("Test "+transform+" "+ sourceExtension +" to "+targetExtension); System.out.println("Test " + transform + " " + sourceExtension + " to " + targetExtension);
MockHttpServletRequestBuilder requestBuilder = includeContents == null MockHttpServletRequestBuilder requestBuilder = includeContents == null
? mockMvcRequest("/transform", sourceFile, "targetExtension", this.targetExtension) ? mockMvcRequest("/transform", sourceFile,
: mockMvcRequest("/transform", sourceFile, "targetExtension", this.targetExtension, "includeContents", includeContents.toString()); "targetExtension", this.targetExtension)
: mockMvcRequest("/transform", sourceFile,
"targetExtension", this.targetExtension, "includeContents", includeContents.toString());
MvcResult result = mockMvc.perform(requestBuilder) MvcResult result = mockMvc.perform(requestBuilder)
.andExpect(status().is(OK.value())) .andExpect(status().is(OK.value()))
.andExpect(header().string("Content-Disposition", "attachment; filename*= UTF-8''quick." + this.targetExtension)). .andExpect(header().string("Content-Disposition",
"attachment; filename*= UTF-8''quick." + this.targetExtension)).
andReturn(); andReturn();
String content = result.getResponse().getContentAsString(); String content = result.getResponse().getContentAsString();
assertTrue("The content did not include \""+expectedContentContains, content.contains(expectedContentContains)); assertTrue("The content did not include \"" + expectedContentContains,
content.contains(expectedContentContains));
} }
@Override @Override
// Add extra required parameters to the request. // Add extra required parameters to the request.
protected MockHttpServletRequestBuilder mockMvcRequest(String url, MockMultipartFile sourceFile, String... params) protected MockHttpServletRequestBuilder mockMvcRequest(String url, MockMultipartFile sourceFile,
String... params)
{ {
return super.mockMvcRequest(url, sourceFile, params) return super.mockMvcRequest(url, sourceFile, params)
.param("transform", transform) .param("transform", transform)
@ -337,7 +347,8 @@ public class TikaControllerTest extends AbstractTransformerControllerTest
{ {
mockTransformCommand(PDF, TXT, MIMETYPE_PDF, true); mockTransformCommand(PDF, TXT, MIMETYPE_PDF, true);
targetEncoding = "rubbish"; targetEncoding = "rubbish";
mockMvc.perform(mockMvcRequest("/transform", sourceFile, "targetExtension", targetExtension)) mockMvc.perform(
mockMvcRequest("/transform", sourceFile, "targetExtension", targetExtension))
.andExpect(status().is(INTERNAL_SERVER_ERROR.value())); .andExpect(status().is(INTERNAL_SERVER_ERROR.value()));
} }
@ -346,7 +357,7 @@ public class TikaControllerTest extends AbstractTransformerControllerTest
@Test @Test
public void zipToTextArchiveTest() throws Exception public void zipToTextArchiveTest() throws Exception
{ {
transform(ARCHIVE, ZIP, TXT, MIMETYPE_ZIP, MIMETYPE_TEXT_PLAIN,false, transform(ARCHIVE, ZIP, TXT, MIMETYPE_ZIP, MIMETYPE_TEXT_PLAIN, false,
"quick.html\n" + "quick.html\n" +
"\n" + "\n" +
"\n" + "\n" +
@ -358,7 +369,7 @@ public class TikaControllerTest extends AbstractTransformerControllerTest
@Test @Test
public void zipToTextIncludeArchiveTest() throws Exception public void zipToTextIncludeArchiveTest() throws Exception
{ {
transform(ARCHIVE, ZIP, TXT, MIMETYPE_ZIP, MIMETYPE_TEXT_PLAIN,true, transform(ARCHIVE, ZIP, TXT, MIMETYPE_ZIP, MIMETYPE_TEXT_PLAIN, true,
"quick.html\n" + "quick.html\n" +
"\n" + "\n" +
"\n" + "\n" +
@ -403,7 +414,8 @@ public class TikaControllerTest extends AbstractTransformerControllerTest
@Test @Test
public void msgToTxtOutlookMsgTest() throws Exception public void msgToTxtOutlookMsgTest() throws Exception
{ {
transform(OUTLOOK_MSG, MSG, TXT, MIMETYPE_OUTLOOK_MSG, MIMETYPE_TEXT_PLAIN, null, EXPECTED_MSG_CONTENT_CONTAINS); transform(OUTLOOK_MSG, MSG, TXT, MIMETYPE_OUTLOOK_MSG, MIMETYPE_TEXT_PLAIN, null,
EXPECTED_MSG_CONTENT_CONTAINS);
} }
// --- PdfBox --- // --- PdfBox ---
@ -411,31 +423,36 @@ public class TikaControllerTest extends AbstractTransformerControllerTest
@Test @Test
public void pdfToTxtPdfBoxTest() throws Exception public void pdfToTxtPdfBoxTest() throws Exception
{ {
transform(PDF_BOX, PDF, TXT, MIMETYPE_PDF, MIMETYPE_TEXT_PLAIN, null, EXPECTED_TEXT_CONTENT_CONTAINS); transform(PDF_BOX, PDF, TXT, MIMETYPE_PDF, MIMETYPE_TEXT_PLAIN, null,
EXPECTED_TEXT_CONTENT_CONTAINS);
} }
@Test @Test
public void pdfToCsvPdfBoxTest() throws Exception public void pdfToCsvPdfBoxTest() throws Exception
{ {
transform(PDF_BOX, PDF, CSV, MIMETYPE_PDF, MIMETYPE_TEXT_CSV, null, EXPECTED_TEXT_CONTENT_CONTAINS); // Yes it is just text transform(PDF_BOX, PDF, CSV, MIMETYPE_PDF, MIMETYPE_TEXT_CSV, null,
EXPECTED_TEXT_CONTENT_CONTAINS); // Yes it is just text
} }
@Test @Test
public void pdfToXmlPdfBoxTest() throws Exception public void pdfToXmlPdfBoxTest() throws Exception
{ {
transform(PDF_BOX, PDF, XML, MIMETYPE_PDF, MIMETYPE_XML, null, EXPECTED_XHTML_CONTENT_CONTAINS); // Yes it is just XHTML transform(PDF_BOX, PDF, XML, MIMETYPE_PDF, MIMETYPE_XML, null,
EXPECTED_XHTML_CONTENT_CONTAINS); // Yes it is just XHTML
} }
@Test @Test
public void pdfToXhtmlPdfBoxTest() throws Exception public void pdfToXhtmlPdfBoxTest() throws Exception
{ {
transform(PDF_BOX, PDF, XHTML, MIMETYPE_PDF, MIMETYPE_XHTML, null, EXPECTED_XHTML_CONTENT_CONTAINS); transform(PDF_BOX, PDF, XHTML, MIMETYPE_PDF, MIMETYPE_XHTML, null,
EXPECTED_XHTML_CONTENT_CONTAINS);
} }
@Test @Test
public void pdfToHtmlPdfBoxTest() throws Exception public void pdfToHtmlPdfBoxTest() throws Exception
{ {
transform(PDF_BOX, PDF, HTML, MIMETYPE_PDF, MIMETYPE_HTML, null, EXPECTED_XHTML_CONTENT_CONTAINS); // Yes it is just XHTML transform(PDF_BOX, PDF, HTML, MIMETYPE_PDF, MIMETYPE_HTML, null,
EXPECTED_XHTML_CONTENT_CONTAINS); // Yes it is just XHTML
} }
// --- Office --- // --- Office ---
@ -443,13 +460,15 @@ public class TikaControllerTest extends AbstractTransformerControllerTest
@Test @Test
public void msgToTxtOfficeTest() throws Exception public void msgToTxtOfficeTest() throws Exception
{ {
transform(POI_OFFICE, MSG, TXT, MIMETYPE_OUTLOOK_MSG, MIMETYPE_TEXT_PLAIN, null, EXPECTED_MSG_CONTENT_CONTAINS); transform(POI_OFFICE, MSG, TXT, MIMETYPE_OUTLOOK_MSG, MIMETYPE_TEXT_PLAIN, null,
EXPECTED_MSG_CONTENT_CONTAINS);
} }
@Test @Test
public void docToTxtOfficeTest() throws Exception public void docToTxtOfficeTest() throws Exception
{ {
transform(POI_OFFICE, DOC, TXT, MIMETYPE_WORD, MIMETYPE_TEXT_PLAIN, null, EXPECTED_TEXT_CONTENT_CONTAINS); transform(POI_OFFICE, DOC, TXT, MIMETYPE_WORD, MIMETYPE_TEXT_PLAIN, null,
EXPECTED_TEXT_CONTENT_CONTAINS);
} }
// --- Poi --- // --- Poi ---
@ -457,7 +476,8 @@ public class TikaControllerTest extends AbstractTransformerControllerTest
@Test @Test
public void xslxToCsvPoiTest() throws Exception public void xslxToCsvPoiTest() throws Exception
{ {
transform(POI, XSLX, CSV, MIMETYPE_OPENXML_SPREADSHEET, MIMETYPE_TEXT_CSV, null, EXPECTED_CSV_CONTENT_CONTAINS); transform(POI, XSLX, CSV, MIMETYPE_OPENXML_SPREADSHEET, MIMETYPE_TEXT_CSV, null,
EXPECTED_CSV_CONTENT_CONTAINS);
} }
// --- OOXML --- // --- OOXML ---
@ -465,13 +485,15 @@ public class TikaControllerTest extends AbstractTransformerControllerTest
@Test @Test
public void docxToTxtOoXmlTest() throws Exception public void docxToTxtOoXmlTest() throws Exception
{ {
transform(POI_OO_XML, DOCX, TXT, MIMETYPE_OPENXML_WORDPROCESSING, MIMETYPE_TEXT_PLAIN, null, EXPECTED_TEXT_CONTENT_CONTAINS); transform(POI_OO_XML, DOCX, TXT, MIMETYPE_OPENXML_WORDPROCESSING, MIMETYPE_TEXT_PLAIN, null,
EXPECTED_TEXT_CONTENT_CONTAINS);
} }
@Test @Test
public void pptxToTxtOoXmlTest() throws Exception public void pptxToTxtOoXmlTest() throws Exception
{ {
transform(POI_OO_XML, PPTX, TXT, MIMETYPE_OPENXML_PRESENTATION, MIMETYPE_TEXT_PLAIN, null, EXPECTED_TEXT_CONTENT_CONTAINS); transform(POI_OO_XML, PPTX, TXT, MIMETYPE_OPENXML_PRESENTATION, MIMETYPE_TEXT_PLAIN, null,
EXPECTED_TEXT_CONTENT_CONTAINS);
} }
// --- TikaAuto --- // --- TikaAuto ---
@ -479,13 +501,15 @@ public class TikaControllerTest extends AbstractTransformerControllerTest
@Test @Test
public void ppxtToTxtTikaAutoTest() throws Exception public void ppxtToTxtTikaAutoTest() throws Exception
{ {
transform(TIKA_AUTO, PPTX, TXT, MIMETYPE_OPENXML_PRESENTATION, MIMETYPE_TEXT_PLAIN, null, EXPECTED_TEXT_CONTENT_CONTAINS); transform(TIKA_AUTO, PPTX, TXT, MIMETYPE_OPENXML_PRESENTATION, MIMETYPE_TEXT_PLAIN, null,
EXPECTED_TEXT_CONTENT_CONTAINS);
} }
@Test @Test
public void doctToTxtTikaAutoTest() throws Exception public void doctToTxtTikaAutoTest() throws Exception
{ {
transform(TIKA_AUTO, DOCX, TXT, MIMETYPE_OPENXML_WORDPROCESSING, MIMETYPE_TEXT_PLAIN, null, EXPECTED_TEXT_CONTENT_CONTAINS); transform(TIKA_AUTO, DOCX, TXT, MIMETYPE_OPENXML_WORDPROCESSING, MIMETYPE_TEXT_PLAIN, null,
EXPECTED_TEXT_CONTENT_CONTAINS);
} }
// --- TextMining --- // --- TextMining ---
@ -493,16 +517,20 @@ public class TikaControllerTest extends AbstractTransformerControllerTest
@Test @Test
public void docToTxtTextMiningTest() throws Exception public void docToTxtTextMiningTest() throws Exception
{ {
transform(TEXT_MINING, DOC, TXT, MIMETYPE_WORD, MIMETYPE_TEXT_PLAIN, null, EXPECTED_TEXT_CONTENT_CONTAINS); transform(TEXT_MINING, DOC, TXT, MIMETYPE_WORD, MIMETYPE_TEXT_PLAIN, null,
EXPECTED_TEXT_CONTENT_CONTAINS);
} }
@Test @Test
public void pdfToTxtExtractBookmarksTest() throws Exception public void pdfToTxtExtractBookmarksTest() throws Exception
{ {
mockTransformCommand(PDF, TXT, MIMETYPE_PDF, true); mockTransformCommand(PDF, TXT, MIMETYPE_PDF, true);
mockMvc.perform(mockMvcRequest("/transform", sourceFile, "targetExtension", targetExtension).param("notExtractBookmarksText", "true")) mockMvc.perform(
mockMvcRequest("/transform", sourceFile, "targetExtension", targetExtension).param(
"notExtractBookmarksText", "true"))
.andExpect(status().is(OK.value())) .andExpect(status().is(OK.value()))
.andExpect(header().string("Content-Disposition", "attachment; filename*= UTF-8''quick." + targetExtension)); .andExpect(header().string("Content-Disposition",
"attachment; filename*= UTF-8''quick." + targetExtension));
} }
@Override @Override
@ -510,10 +538,10 @@ public class TikaControllerTest extends AbstractTransformerControllerTest
{ {
transformRequest.setSourceExtension(sourceExtension); transformRequest.setSourceExtension(sourceExtension);
transformRequest.setTargetExtension(targetExtension); transformRequest.setTargetExtension(targetExtension);
transformRequest.setSourceMediaType(MediaType.APPLICATION_PDF_VALUE); transformRequest.setSourceMediaType(APPLICATION_PDF_VALUE);
transformRequest.setTargetMediaType(MediaType.TEXT_PLAIN_VALUE); transformRequest.setTargetMediaType(TEXT_PLAIN_VALUE);
transformRequest.getTransformRequestOptions().put("transform", "PdfBox"); transformRequest.getTransformRequestOptions().put("transform", "PdfBox");
transformRequest.getTransformRequestOptions().put("targetMimetype", MediaType.TEXT_PLAIN_VALUE); transformRequest.getTransformRequestOptions().put("targetMimetype", TEXT_PLAIN_VALUE);
transformRequest.getTransformRequestOptions().put("targetEncoding", "UTF-8"); transformRequest.getTransformRequestOptions().put("targetEncoding", "UTF-8");
} }
@ -525,7 +553,6 @@ public class TikaControllerTest extends AbstractTransformerControllerTest
File sourceFile = getTestFile("quick." + sourceExtension, true); File sourceFile = getTestFile("quick." + sourceExtension, true);
String targetFileRef = UUID.randomUUID().toString(); String targetFileRef = UUID.randomUUID().toString();
// Transformation Request POJO // Transformation Request POJO
TransformRequest transformRequest = new TransformRequest(); TransformRequest transformRequest = new TransformRequest();
transformRequest.setRequestId("1"); transformRequest.setRequestId("1");
@ -539,12 +566,13 @@ public class TikaControllerTest extends AbstractTransformerControllerTest
// HTTP Request // HTTP Request
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=quick." + sourceExtension); headers.set(CONTENT_DISPOSITION, "attachment; filename=quick." + sourceExtension);
ResponseEntity<Resource> response = new ResponseEntity<>(new FileSystemResource( ResponseEntity<Resource> response = new ResponseEntity<>(new FileSystemResource(
sourceFile), headers, OK); sourceFile), headers, OK);
when(alfrescoSharedFileStoreClient.retrieveFile(sourceFileRef)).thenReturn(response); when(alfrescoSharedFileStoreClient.retrieveFile(sourceFileRef)).thenReturn(response);
when(alfrescoSharedFileStoreClient.saveFile(any())).thenReturn(new FileRefResponse(new FileRefEntity(targetFileRef))); when(alfrescoSharedFileStoreClient.saveFile(any()))
.thenReturn(new FileRefResponse(new FileRefEntity(targetFileRef)));
when(mockExecutionResult.getExitValue()).thenReturn(0); when(mockExecutionResult.getExitValue()).thenReturn(0);
// Update the Transformation Request with any specific params before sending it // Update the Transformation Request with any specific params before sending it
@ -552,18 +580,21 @@ public class TikaControllerTest extends AbstractTransformerControllerTest
// Serialize and call the transformer // Serialize and call the transformer
String tr = objectMapper.writeValueAsString(transformRequest); String tr = objectMapper.writeValueAsString(transformRequest);
String transformationReplyAsString = mockMvc.perform(MockMvcRequestBuilders.post("/transform") String transformationReplyAsString = mockMvc
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .perform(MockMvcRequestBuilders
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).content(tr)) .post("/transform")
.andExpect(status().is(HttpStatus.CREATED.value())) .header(ACCEPT, APPLICATION_JSON_VALUE)
.header(CONTENT_TYPE, APPLICATION_JSON_VALUE)
.content(tr))
.andExpect(status().is(CREATED.value()))
.andReturn().getResponse().getContentAsString(); .andReturn().getResponse().getContentAsString();
TransformReply transformReply = objectMapper.readValue(transformationReplyAsString, TransformReply.class); TransformReply transformReply = objectMapper.readValue(transformationReplyAsString,
TransformReply.class);
// Assert the reply // Assert the reply
assertEquals(transformRequest.getRequestId(), transformReply.getRequestId()); assertEquals(transformRequest.getRequestId(), transformReply.getRequestId());
assertEquals(transformRequest.getClientData(), transformReply.getClientData()); assertEquals(transformRequest.getClientData(), transformReply.getClientData());
assertEquals(transformRequest.getSchema(), transformReply.getSchema()); assertEquals(transformRequest.getSchema(), transformReply.getSchema());
} }
} }

View File

@ -48,7 +48,8 @@ public class TikaQueueTransformServiceIT extends AbstractQueueTransformServiceIT
@Override @Override
protected TransformRequest buildRequest() protected TransformRequest buildRequest()
{ {
return TransformRequest.builder() return TransformRequest
.builder()
.withRequestId(UUID.randomUUID().toString()) .withRequestId(UUID.randomUUID().toString())
.withSourceMediaType(MIMETYPE_OPENXML_WORDPROCESSING) .withSourceMediaType(MIMETYPE_OPENXML_WORDPROCESSING)
.withTargetMediaType(MIMETYPE_TEXT_PLAIN) .withTargetMediaType(MIMETYPE_TEXT_PLAIN)

View File

@ -26,24 +26,32 @@
*/ */
package org.alfresco.transformer; package org.alfresco.transformer;
import io.micrometer.core.instrument.MeterRegistry; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer; import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.event.EventListener;
import io.micrometer.core.instrument.MeterRegistry;
@SpringBootApplication @SpringBootApplication
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) @EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class Application public class Application
{ {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Value("${container.name}") @Value("${container.name}")
private String containerName; private String containerName;
@Bean @Bean
MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() { MeterRegistryCustomizer<MeterRegistry> metricsCommonTags()
{
return registry -> registry.config().commonTags("containerName", containerName); return registry -> registry.config().commonTags("containerName", containerName);
} }
@ -51,4 +59,16 @@ public class Application
{ {
SpringApplication.run(Application.class, args); SpringApplication.run(Application.class, args);
} }
@EventListener(ApplicationReadyEvent.class)
public void startup()
{
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
logger.info("The transformers in this project use libraries from Apache. See the license at http://www.apache.org/licenses/LICENSE-2.0. or in /Apache\\\\ 2.0.txt");
logger.info("Additional libraries used:");
logger.info("* htmlparser http://htmlparser.sourceforge.net/license.html");
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
logger.info("Starting application components... Done");
}
} }

View File

@ -64,15 +64,6 @@ public class MiscController extends AbstractTransformerController
@Autowired @Autowired
private SelectingTransformer transformer; private SelectingTransformer transformer;
public MiscController()
{
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
logger.info("The transformers in this project use libraries from Apache. See the license at http://www.apache.org/licenses/LICENSE-2.0. or in /Apache\\\\ 2.0.txt");
logger.info("Additional libraries used:");
logger.info("* htmlparser http://htmlparser.sourceforge.net/license.html");
logger.info("--------------------------------------------------------------------------------------------------------------------------------------------------------------");
}
@Override @Override
public String getTransformerName() public String getTransformerName()
{ {
@ -92,7 +83,7 @@ public class MiscController extends AbstractTransformerController
// See the Javadoc on this method and Probes.md for the choice of these values. // See the Javadoc on this method and Probes.md for the choice of these values.
return new ProbeTestTransform(this, "quick.html", "quick.txt", return new ProbeTestTransform(this, "quick.html", "quick.txt",
119, 30, 150, 1024, 119, 30, 150, 1024,
60*2+1,60*2) 60 * 2 + 1, 60 * 2)
{ {
@Override @Override
protected void executeTransformCommand(File sourceFile, File targetFile) protected void executeTransformCommand(File sourceFile, File targetFile)
@ -100,22 +91,27 @@ public class MiscController extends AbstractTransformerController
Map<String, String> parameters = new HashMap<>(); Map<String, String> parameters = new HashMap<>();
parameters.put(SOURCE_ENCODING, "UTF-8"); parameters.put(SOURCE_ENCODING, "UTF-8");
parameters.put(TARGET_ENCODING, "UTF-8"); parameters.put(TARGET_ENCODING, "UTF-8");
transformer.transform(sourceFile, targetFile, MIMETYPE_HTML, MIMETYPE_TEXT_PLAIN, parameters); transformer.transform(sourceFile, targetFile, MIMETYPE_HTML, MIMETYPE_TEXT_PLAIN,
parameters);
} }
}; };
} }
@Override @Override
public void processTransform(File sourceFile, File targetFile, Map<String, String> transformOptions, Long timeout) public void processTransform(File sourceFile, File targetFile,
Map<String, String> transformOptions, Long timeout)
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
logger.debug("Processing request with: sourceFile '{}', targetFile '{}', transformOptions" + logger.debug(
"Processing request with: sourceFile '{}', targetFile '{}', transformOptions" +
" '{}', timeout {} ms", sourceFile, targetFile, transformOptions, timeout); " '{}', timeout {} ms", sourceFile, targetFile, transformOptions, timeout);
} }
String sourceMimetype = transformOptions.get("sourceMimetype"); String sourceMimetype = transformOptions.get("sourceMimetype");
String targetMimetype = transformOptions.get("targetMimetype"); String targetMimetype = transformOptions.get("targetMimetype");
transformer.transform(sourceFile, targetFile, sourceMimetype, targetMimetype, transformOptions); transformer.transform(sourceFile, targetFile, sourceMimetype, targetMimetype,
transformOptions);
} }
@PostMapping(value = "/transform", consumes = MULTIPART_FORM_DATA_VALUE) @PostMapping(value = "/transform", consumes = MULTIPART_FORM_DATA_VALUE)
@ -129,11 +125,13 @@ public class MiscController extends AbstractTransformerController
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
logger.debug("Processing request with: sourceMimetype '{}', targetMimetype '{}' , targetExtension '{}' " + logger.debug(
"Processing request with: sourceMimetype '{}', targetMimetype '{}' , targetExtension '{}' " +
", parameters '{}'", sourceMimetype, targetMimetype, targetExtension, parameters); ", parameters '{}'", sourceMimetype, targetMimetype, targetExtension, parameters);
} }
String targetFilename = createTargetFileName(sourceMultipartFile.getOriginalFilename(), targetExtension); String targetFilename = createTargetFileName(sourceMultipartFile.getOriginalFilename(),
targetExtension);
getProbeTestTransform().incrementTransformerCount(); getProbeTestTransform().incrementTransformerCount();
File sourceFile = createSourceFile(request, sourceMultipartFile); File sourceFile = createSourceFile(request, sourceMultipartFile);
File targetFile = createTargetFile(request, targetFilename); File targetFile = createTargetFile(request, targetFilename);

View File

@ -26,12 +26,10 @@
*/ */
package org.alfresco.transformer.transformers; package org.alfresco.transformer.transformers;
import org.alfresco.error.AlfrescoRuntimeException; import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IMAGE_JPEG;
import org.alfresco.transform.client.model.Mimetype; import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IWORK_KEYNOTE;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IWORK_NUMBERS;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IWORK_PAGES;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.File; import java.io.File;
@ -39,13 +37,16 @@ import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IWORK_KEYNOTE; import org.alfresco.error.AlfrescoRuntimeException;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IWORK_NUMBERS; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IWORK_PAGES; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableList;
/** /**
* Converts Apple iWorks files to JPEGs for thumbnailing & previewing. * Converts Apple iWorks files to JPEGs for thumbnailing & previewing.
@ -60,24 +61,25 @@ import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IWORK_PAGES;
*/ */
public class AppleIWorksContentTransformer implements SelectableTransformer public class AppleIWorksContentTransformer implements SelectableTransformer
{ {
private static final Logger logger = LoggerFactory.getLogger(AppleIWorksContentTransformer.class); private static final Logger logger = LoggerFactory.getLogger(
AppleIWorksContentTransformer.class);
// Apple's zip entry names for previews in iWorks have changed over time. // Apple's zip entry names for previews in iWorks have changed over time.
private static final List<String> PDF_PATHS = Arrays.asList( private static final List<String> PDF_PATHS = ImmutableList.of(
"QuickLook/Preview.pdf"); // iWorks 2008/9 "QuickLook/Preview.pdf"); // iWorks 2008/9
private static final List<String> JPG_PATHS = Arrays.asList( private static final List<String> JPG_PATHS = ImmutableList.of(
"QuickLook/Thumbnail.jpg", // iWorks 2008/9 "QuickLook/Thumbnail.jpg", // iWorks 2008/9
"preview.jpg"); // iWorks 2013/14 (720 x 552) We use the best quality image. Others are: "preview.jpg"); // iWorks 2013/14 (720 x 552) We use the best quality image. Others are:
// (225 x 173) preview-web.jpg // (225 x 173) preview-web.jpg
// (53 x 41) preview-micro.jpg // (53 x 41) preview-micro.jpg
@Override @Override
public boolean isTransformable(String sourceMimetype, String targetMimetype, Map<String, String> parameters) public boolean isTransformable(String sourceMimetype, String targetMimetype,
Map<String, String> parameters)
{ {
boolean transformable = MIMETYPE_IWORK_KEYNOTE.equals(sourceMimetype) return MIMETYPE_IWORK_KEYNOTE.equals(sourceMimetype) ||
|| MIMETYPE_IWORK_NUMBERS.equals(sourceMimetype) MIMETYPE_IWORK_NUMBERS.equals(sourceMimetype) ||
|| MIMETYPE_IWORK_PAGES.equals(sourceMimetype); MIMETYPE_IWORK_PAGES.equals(sourceMimetype);
return transformable;
} }
@Override @Override
@ -86,20 +88,19 @@ public class AppleIWorksContentTransformer implements SelectableTransformer
final String sourceMimetype = parameters.get(SOURCE_MIMETYPE); final String sourceMimetype = parameters.get(SOURCE_MIMETYPE);
final String targetMimetype = parameters.get(TARGET_MIMETYPE); final String targetMimetype = parameters.get(TARGET_MIMETYPE);
if(logger.isDebugEnabled()) logger.debug("Performing IWorks to jpeg transform with sourceMimetype={} targetMimetype={}",
{ sourceMimetype, targetMimetype);
logger.debug("Performing IWorks to jpeg transform with sourceMimetype=" + sourceMimetype
+ " targetMimetype=" + targetMimetype);
}
// iWorks files are zip (or package) files. // iWorks files are zip (or package) files.
// If it's not a zip file, the resultant ZipException will be caught as an IOException below. // If it's not a zip file, the resultant ZipException will be caught as an IOException below.
try (ZipArchiveInputStream iWorksZip = new ZipArchiveInputStream( new BufferedInputStream( new FileInputStream(sourceFile)))) try (ZipArchiveInputStream iWorksZip = new ZipArchiveInputStream(
new BufferedInputStream(new FileInputStream(sourceFile))))
{ {
// Look through the zip file entries for the preview/thumbnail. // Look through the zip file entries for the preview/thumbnail.
List<String> paths = Mimetype.MIMETYPE_IMAGE_JPEG.equals(targetMimetype) ? JPG_PATHS : PDF_PATHS; List<String> paths = MIMETYPE_IMAGE_JPEG.equals(targetMimetype) ? JPG_PATHS : PDF_PATHS;
ZipArchiveEntry entry; ZipArchiveEntry entry;
boolean found = false; boolean found = false;
while ((entry=iWorksZip.getNextZipEntry()) != null) while ((entry = iWorksZip.getNextZipEntry()) != null)
{ {
String name = entry.getName(); String name = entry.getName();
if (paths.contains(name)) if (paths.contains(name))
@ -110,14 +111,17 @@ public class AppleIWorksContentTransformer implements SelectableTransformer
} }
} }
if (! found) if (!found)
{ {
throw new AlfrescoRuntimeException("The source " + sourceMimetype + " file did not contain a " + targetMimetype + " preview"); throw new AlfrescoRuntimeException(
"The source " + sourceMimetype + " file did not contain a " + targetMimetype + " preview");
} }
} }
catch (IOException e) catch (IOException e)
{ {
throw new AlfrescoRuntimeException("Unable to transform " + sourceMimetype + " file. It should have been a zip format file.", e); throw new AlfrescoRuntimeException(
"Unable to transform " + sourceMimetype + " file. It should have been a zip format file.",
e);
} }
} }
} }

View File

@ -26,16 +26,12 @@
*/ */
package org.alfresco.transformer.transformers; package org.alfresco.transformer.transformers;
import org.htmlparser.Parser; import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_HTML;
import org.htmlparser.beans.StringBean; import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_PLAIN;
import org.htmlparser.util.ParserException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.io.Writer; import java.io.Writer;
import java.net.URLConnection; import java.net.URLConnection;
@ -43,8 +39,11 @@ import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.IllegalCharsetNameException;
import java.util.Map; import java.util.Map;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_HTML; import org.htmlparser.Parser;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_PLAIN; import org.htmlparser.beans.StringBean;
import org.htmlparser.util.ParserException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* Content transformer which wraps the HTML Parser library for * Content transformer which wraps the HTML Parser library for
@ -67,30 +66,32 @@ import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_PLAIN;
* the current settings around links and non-breaking spaces. * the current settings around links and non-breaking spaces.
* </p> * </p>
* *
* @author Derek Hulley
* @author eknizat
* @see <a href="http://htmlparser.sourceforge.net/">http://htmlparser.sourceforge.net</a> * @see <a href="http://htmlparser.sourceforge.net/">http://htmlparser.sourceforge.net</a>
* @see org.htmlparser.beans.StringBean * @see org.htmlparser.beans.StringBean
* @see <a href="http://sourceforge.net/tracker/?func=detail&aid=1644504&group_id=24399&atid=381401">HTML Parser</a> * @see <a href="http://sourceforge.net/tracker/?func=detail&aid=1644504&group_id=24399&atid=381401">HTML Parser</a>
*
* @author Derek Hulley
* @author eknizat
*/ */
public class HtmlParserContentTransformer implements SelectableTransformer public class HtmlParserContentTransformer implements SelectableTransformer
{ {
private static final Logger logger = LoggerFactory.getLogger(HtmlParserContentTransformer.class); private static final Logger logger = LoggerFactory.getLogger(
HtmlParserContentTransformer.class);
@Override @Override
public boolean isTransformable(String sourceMimetype, String targetMimetype, Map<String, String> parameters) public boolean isTransformable(String sourceMimetype, String targetMimetype,
Map<String, String> parameters)
{ {
return MIMETYPE_HTML.equals(sourceMimetype) && MIMETYPE_TEXT_PLAIN.equals(targetMimetype); return MIMETYPE_HTML.equals(sourceMimetype) && MIMETYPE_TEXT_PLAIN.equals(targetMimetype);
} }
@Override @Override
public void transform(File sourceFile, File targetFile, Map<String, String> parameters) throws Exception public void transform(File sourceFile, File targetFile, Map<String, String> parameters)
throws Exception
{ {
String sourceEncoding = parameters.get(SOURCE_ENCODING); String sourceEncoding = parameters.get(SOURCE_ENCODING);
checkEncodingParameter(sourceEncoding, SOURCE_ENCODING); checkEncodingParameter(sourceEncoding, SOURCE_ENCODING);
if(logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
logger.debug("Performing HTML to text transform with sourceEncoding=" + sourceEncoding); logger.debug("Performing HTML to text transform with sourceEncoding=" + sourceEncoding);
} }
@ -105,29 +106,31 @@ public class HtmlParserContentTransformer implements SelectableTransformer
String text = extractor.getStrings(); String text = extractor.getStrings();
// write it to the writer // write it to the writer
try ( Writer writer = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(targetFile)))) try (Writer writer = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(targetFile))))
{ {
writer.write(text); writer.write(text);
} }
} }
private void checkEncodingParameter(String encoding, String paramterName) private void checkEncodingParameter(String encoding, String parameterName)
{ {
try try
{ {
if (encoding != null && !Charset.isSupported(encoding)) if (encoding != null && !Charset.isSupported(encoding))
{ {
throw new IllegalArgumentException(paramterName + "=" + encoding + " is not supported by the JVM."); throw new IllegalArgumentException(
parameterName + "=" + encoding + " is not supported by the JVM.");
} }
} }
catch (IllegalCharsetNameException e) catch (IllegalCharsetNameException e)
{ {
throw new IllegalArgumentException(paramterName + "=" + encoding + " is not a valid encoding."); throw new IllegalArgumentException(
parameterName + "=" + encoding + " is not a valid encoding.");
} }
} }
/** /**
*
* <p> * <p>
* This code is based on a class of the same name, originally implemented in alfresco-repository. * This code is based on a class of the same name, originally implemented in alfresco-repository.
* </p> * </p>
@ -139,8 +142,6 @@ public class HtmlParserContentTransformer implements SelectableTransformer
* This allows us to correctly handle HTML files where the encoding * This allows us to correctly handle HTML files where the encoding
* is specified against the content property (rather than in the * is specified against the content property (rather than in the
* HTML Head Meta), see ALF-10466 for details. * HTML Head Meta), see ALF-10466 for details.
*
*
*/ */
private class EncodingAwareStringBean extends StringBean private class EncodingAwareStringBean extends StringBean
{ {
@ -158,7 +159,7 @@ public class HtmlParserContentTransformer implements SelectableTransformer
String previousURL = getURL(); String previousURL = getURL();
String newURL = file.getAbsolutePath(); String newURL = file.getAbsolutePath();
if ( (previousURL == null) || (!newURL.equals(previousURL)) ) if (previousURL == null || !newURL.equals(previousURL))
{ {
try try
{ {
@ -178,8 +179,10 @@ public class HtmlParserContentTransformer implements SelectableTransformer
mParser.setEncoding(encoding); mParser.setEncoding(encoding);
} }
mPropertySupport.firePropertyChange(StringBean.PROP_URL_PROPERTY, previousURL, getURL()); mPropertySupport.firePropertyChange(StringBean.PROP_URL_PROPERTY, previousURL,
mPropertySupport.firePropertyChange(StringBean.PROP_CONNECTION_PROPERTY, conn, mParser.getConnection()); getURL());
mPropertySupport.firePropertyChange(StringBean.PROP_CONNECTION_PROPERTY, conn,
mParser.getConnection());
setStrings(); setStrings();
} }
catch (ParserException pe) catch (ParserException pe)
@ -189,7 +192,8 @@ public class HtmlParserContentTransformer implements SelectableTransformer
} }
} }
public String getEncoding(){ public String getEncoding()
{
return mParser.getEncoding(); return mParser.getEncoding();
} }
} }

View File

@ -26,8 +26,36 @@
*/ */
package org.alfresco.transformer.transformers; package org.alfresco.transformer.transformers;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IMAGE_JPEG;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_PRESENTATION;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_PRESENTATION_ADDIN;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_PRESENTATION_MACRO;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_PRESENTATION_SLIDE;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_PRESENTATION_SLIDESHOW;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_PRESENTATION_SLIDESHOW_MACRO;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_PRESENTATION_SLIDE_MACRO;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_PRESENTATION_TEMPLATE;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_PRESENTATION_TEMPLATE_MACRO;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_SPREADSHEET;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_SPREADSHEET_ADDIN_MACRO;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_SPREADSHEET_BINARY_MACRO;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_SPREADSHEET_MACRO;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_SPREADSHEET_TEMPLATE;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_SPREADSHEET_TEMPLATE_MACRO;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_WORDPROCESSING;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_WORDPROCESSING_MACRO;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_WORD_TEMPLATE;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_OPENXML_WORD_TEMPLATE_MACRO;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.transform.client.model.Mimetype;
import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackageRelationship;
@ -36,15 +64,7 @@ import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.File; import com.google.common.collect.ImmutableList;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/** /**
* Extracts out Thumbnail JPEGs from OOXML files for thumbnailing & previewing. * Extracts out Thumbnail JPEGs from OOXML files for thumbnailing & previewing.
@ -53,47 +73,50 @@ import java.util.Map;
* *
* @author Nick Burch * @author Nick Burch
* @author eknizat * @author eknizat
*
*/ */
public class OOXMLThumbnailContentTransformer implements SelectableTransformer public class OOXMLThumbnailContentTransformer implements SelectableTransformer
{ {
private static final Logger logger = LoggerFactory.getLogger(OOXMLThumbnailContentTransformer.class); private static final Logger logger = LoggerFactory.getLogger(
OOXMLThumbnailContentTransformer.class);
private static final List<String> OOXML_MIMETYPES = Arrays.asList(new String[]{ private static final List<String> OOXML_MIMETYPES = ImmutableList.of(
Mimetype.MIMETYPE_OPENXML_WORDPROCESSING, MIMETYPE_OPENXML_WORDPROCESSING,
Mimetype.MIMETYPE_OPENXML_WORDPROCESSING_MACRO, MIMETYPE_OPENXML_WORDPROCESSING_MACRO,
Mimetype.MIMETYPE_OPENXML_WORD_TEMPLATE, MIMETYPE_OPENXML_WORD_TEMPLATE,
Mimetype.MIMETYPE_OPENXML_WORD_TEMPLATE_MACRO, MIMETYPE_OPENXML_WORD_TEMPLATE_MACRO,
Mimetype.MIMETYPE_OPENXML_PRESENTATION, MIMETYPE_OPENXML_PRESENTATION,
Mimetype.MIMETYPE_OPENXML_PRESENTATION_MACRO, MIMETYPE_OPENXML_PRESENTATION_MACRO,
Mimetype.MIMETYPE_OPENXML_PRESENTATION_SLIDESHOW, MIMETYPE_OPENXML_PRESENTATION_SLIDESHOW,
Mimetype.MIMETYPE_OPENXML_PRESENTATION_SLIDESHOW_MACRO, MIMETYPE_OPENXML_PRESENTATION_SLIDESHOW_MACRO,
Mimetype.MIMETYPE_OPENXML_PRESENTATION_TEMPLATE, MIMETYPE_OPENXML_PRESENTATION_TEMPLATE,
Mimetype.MIMETYPE_OPENXML_PRESENTATION_TEMPLATE_MACRO, MIMETYPE_OPENXML_PRESENTATION_TEMPLATE_MACRO,
Mimetype.MIMETYPE_OPENXML_PRESENTATION_ADDIN, MIMETYPE_OPENXML_PRESENTATION_ADDIN,
Mimetype.MIMETYPE_OPENXML_PRESENTATION_SLIDE, MIMETYPE_OPENXML_PRESENTATION_SLIDE,
Mimetype.MIMETYPE_OPENXML_PRESENTATION_SLIDE_MACRO, MIMETYPE_OPENXML_PRESENTATION_SLIDE_MACRO,
Mimetype.MIMETYPE_OPENXML_SPREADSHEET, MIMETYPE_OPENXML_SPREADSHEET,
Mimetype.MIMETYPE_OPENXML_SPREADSHEET_TEMPLATE, MIMETYPE_OPENXML_SPREADSHEET_TEMPLATE,
Mimetype.MIMETYPE_OPENXML_SPREADSHEET_MACRO, MIMETYPE_OPENXML_SPREADSHEET_MACRO,
Mimetype.MIMETYPE_OPENXML_SPREADSHEET_TEMPLATE_MACRO, MIMETYPE_OPENXML_SPREADSHEET_TEMPLATE_MACRO,
Mimetype.MIMETYPE_OPENXML_SPREADSHEET_ADDIN_MACRO, MIMETYPE_OPENXML_SPREADSHEET_ADDIN_MACRO,
Mimetype.MIMETYPE_OPENXML_SPREADSHEET_BINARY_MACRO}); MIMETYPE_OPENXML_SPREADSHEET_BINARY_MACRO);
@Override @Override
public boolean isTransformable(String sourceMimetype, String targetMimetype, Map<String, String> parameters) public boolean isTransformable(String sourceMimetype, String targetMimetype,
Map<String, String> parameters)
{ {
// only support [OOXML] -> JPEG // only support [OOXML] -> JPEG
return Mimetype.MIMETYPE_IMAGE_JPEG.equals(targetMimetype) && OOXML_MIMETYPES.contains(sourceMimetype); return MIMETYPE_IMAGE_JPEG.equals(targetMimetype) &&
OOXML_MIMETYPES.contains(sourceMimetype);
} }
@Override @Override
public void transform(File sourceFile, File targetFile, Map<String, String> parameters) throws Exception public void transform(File sourceFile, File targetFile, Map<String, String> parameters)
throws Exception
{ {
final String sourceMimetype = parameters.get(SOURCE_MIMETYPE); final String sourceMimetype = parameters.get(SOURCE_MIMETYPE);
final String targetMimetype = parameters.get(TARGET_MIMETYPE); final String targetMimetype = parameters.get(TARGET_MIMETYPE);
if(logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
logger.debug("Performing OOXML to jpeg transform with sourceMimetype=" + sourceMimetype logger.debug("Performing OOXML to jpeg transform with sourceMimetype=" + sourceMimetype
+ " targetMimetype=" + targetMimetype); + " targetMimetype=" + targetMimetype);
@ -103,7 +126,8 @@ public class OOXMLThumbnailContentTransformer implements SelectableTransformer
{ {
// Does it have a thumbnail? // Does it have a thumbnail?
PackageRelationshipCollection rels = pkg.getRelationshipsByType(PackageRelationshipTypes.THUMBNAIL); PackageRelationshipCollection rels = pkg.getRelationshipsByType(
PackageRelationshipTypes.THUMBNAIL);
if (rels.size() > 0) if (rels.size() > 0)
{ {
// Get the thumbnail part // Get the thumbnail part
@ -118,7 +142,8 @@ public class OOXMLThumbnailContentTransformer implements SelectableTransformer
else else
{ {
logger.debug("No thumbnail present in file."); logger.debug("No thumbnail present in file.");
throw new Exception("No thumbnail present in file, unable to generate " + targetMimetype); throw new Exception(
"No thumbnail present in file, unable to generate " + targetMimetype);
} }
} }
catch (IOException e) catch (IOException e)

View File

@ -26,15 +26,10 @@
*/ */
package org.alfresco.transformer.transformers; package org.alfresco.transformer.transformers;
import org.alfresco.transformer.logging.LogEntry;
import java.io.File; import java.io.File;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
/** /**
*
* Implemented by transformers used by {@link SelectingTransformer}. * Implemented by transformers used by {@link SelectingTransformer}.
* *
* @author eknizat * @author eknizat
@ -48,21 +43,23 @@ public interface SelectableTransformer
/** /**
* Implementation of the actual transformation. * Implementation of the actual transformation.
*
* @param sourceFile * @param sourceFile
* @param targetFile * @param targetFile
* @param parameters * @param parameters
* @throws Exception * @throws Exception
*/ */
public void transform(File sourceFile, File targetFile, Map<String, String> parameters) throws Exception; void transform(File sourceFile, File targetFile, Map<String, String> parameters)
throws Exception;
/** /**
* Determine whether this transformer is applicable for the given MIME types. * Determine whether this transformer is applicable for the given MIME types.
*
* @param sourceMimetype * @param sourceMimetype
* @param targetMimetype * @param targetMimetype
* @param parameters * @param parameters
* @return * @return
*/ */
public boolean isTransformable(String sourceMimetype, String targetMimetype, Map<String, String> parameters); boolean isTransformable(String sourceMimetype, String targetMimetype,
Map<String, String> parameters);
} }

View File

@ -26,6 +26,14 @@
*/ */
package org.alfresco.transformer.transformers; package org.alfresco.transformer.transformers;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.transform.exceptions.TransformException; import org.alfresco.transform.exceptions.TransformException;
import org.alfresco.transformer.logging.LogEntry; import org.alfresco.transformer.logging.LogEntry;
@ -33,52 +41,47 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.io.File; import com.google.common.collect.ImmutableList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
/** /**
*
* The SelectingTransformer selects a registered {@link SelectableTransformer} * The SelectingTransformer selects a registered {@link SelectableTransformer}
* and delegates the transformation to its implementation. * and delegates the transformation to its implementation.
* *
* @author eknizat * @author eknizat
*
*/ */
@Component @Component
public class SelectingTransformer public class SelectingTransformer
{ {
private static final Logger logger = LoggerFactory.getLogger(SelectingTransformer.class); private static final Logger logger = LoggerFactory.getLogger(SelectingTransformer.class);
private List<SelectableTransformer> transformers = new LinkedList<>(); private final List<SelectableTransformer> transformers;
public SelectingTransformer() public SelectingTransformer()
{ {
transformers.add(new AppleIWorksContentTransformer()); transformers = ImmutableList.of(
transformers.add(new HtmlParserContentTransformer()); new AppleIWorksContentTransformer(),
transformers.add(new StringExtractingContentTransformer()); new HtmlParserContentTransformer(),
transformers.add(new TextToPdfContentTransformer()); new StringExtractingContentTransformer(),
// transformers.add(new OOXMLThumbnailContentTransformer()); // Doesn't work with java 11, transformer and test disabled new TextToPdfContentTransformer()
// new OOXMLThumbnailContentTransformer()); // Doesn't work with java 11, transformer and test disabled
);
} }
/** /**
* Performs a transform using a transformer selected based on the provided sourceMimetype and targetMimetype * Performs a transform using a transformer selected based on the provided sourceMimetype and targetMimetype
*
* @param sourceFile File to transform from * @param sourceFile File to transform from
* @param targetFile File to transform to * @param targetFile File to transform to
* @param sourceMimetype Mimetype of the source file * @param sourceMimetype Mimetype of the source file
* @throws TransformException * @throws TransformException
*/ */
public void transform(File sourceFile, File targetFile, String sourceMimetype, String targetMimetype, public void transform(File sourceFile, File targetFile, String sourceMimetype,
Map<String, String> parameters) throws TransformException String targetMimetype, Map<String, String> parameters) throws TransformException
{ {
try try
{ {
SelectableTransformer transformer = selectTransformer(sourceMimetype, targetMimetype, parameters); final SelectableTransformer transformer = selectTransformer(sourceMimetype,
targetMimetype, parameters);
logOptions(sourceFile, targetFile, parameters); logOptions(sourceFile, targetFile, parameters);
transformer.transform(sourceFile, targetFile, parameters); transformer.transform(sourceFile, targetFile, parameters);
} }
@ -109,15 +112,13 @@ public class SelectingTransformer
{ {
if (transformer.isTransformable(sourceMimetype, targetMimetype, parameters)) if (transformer.isTransformable(sourceMimetype, targetMimetype, parameters))
{ {
if (logger.isDebugEnabled()) logger.debug("Using {} to transform from {} to {}",
{ transformer.getClass().getName(), sourceMimetype, targetMimetype);
logger.debug("Using " + transformer.getClass().getName()
+ " to transform from " + sourceMimetype + " to " + targetMimetype );
}
return transformer; return transformer;
} }
} }
throw new AlfrescoRuntimeException( "Could not select a transformer for sourceMimetype=" + sourceMimetype throw new AlfrescoRuntimeException(
"Could not select a transformer for sourceMimetype=" + sourceMimetype
+ " targetMimetype=" + targetMimetype); + " targetMimetype=" + targetMimetype);
} }
@ -129,7 +130,8 @@ public class SelectingTransformer
private void logOptions(File sourceFile, File targetFile, Map<String, String> parameters) private void logOptions(File sourceFile, File targetFile, Map<String, String> parameters)
{ {
StringJoiner sj = new StringJoiner(" "); StringJoiner sj = new StringJoiner(" ");
parameters.forEach( (k, v) -> sj.add("--" + k + "=" + v)); // keeping the existing style used in other T-Engines parameters.forEach((k, v) -> sj.add(
"--" + k + "=" + v)); // keeping the existing style used in other T-Engines
sj.add(getExtension(sourceFile)); sj.add(getExtension(sourceFile));
sj.add(getExtension(targetFile)); sj.add(getExtension(targetFile));
LogEntry.setOptions(sj.toString()); LogEntry.setOptions(sj.toString());
@ -137,9 +139,8 @@ public class SelectingTransformer
private String getExtension(File file) private String getExtension(File file)
{ {
String name = file.getName(); final String name = file.getName();
int i = name.lastIndexOf('.'); int i = name.lastIndexOf('.');
String ext = i == -1 ? "???" : name.substring(i + 1); return i == -1 ? "???" : name.substring(i + 1);
return ext;
} }
} }

View File

@ -26,29 +26,25 @@
*/ */
package org.alfresco.transformer.transformers; package org.alfresco.transformer.transformers;
import org.apache.commons.logging.Log; import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_DITA;
import org.apache.commons.logging.LogFactory; import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_JAVASCRIPT;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_PLAIN;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.io.Reader; import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer; import java.io.Writer;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.IllegalCharsetNameException;
import java.util.Map; import java.util.Map;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_DITA; import org.apache.commons.logging.Log;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_JAVASCRIPT; import org.apache.commons.logging.LogFactory;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_PLAIN;
/** /**
* Converts any textual format to plain text. * Converts any textual format to plain text.
@ -60,7 +56,6 @@ import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_PLAIN;
* This code is based on a class of the same name originally implemented in alfresco-repository. * This code is based on a class of the same name originally implemented in alfresco-repository.
* </p> * </p>
* *
*
* @author Derek Hulley * @author Derek Hulley
* @author eknizat * @author eknizat
*/ */
@ -70,13 +65,13 @@ public class StringExtractingContentTransformer implements SelectableTransformer
private static final Log logger = LogFactory.getLog(StringExtractingContentTransformer.class); private static final Log logger = LogFactory.getLog(StringExtractingContentTransformer.class);
@Override @Override
public boolean isTransformable(String sourceMimetype, String targetMimetype, Map<String, String> parameters) public boolean isTransformable(String sourceMimetype, String targetMimetype,
Map<String, String> parameters)
{ {
boolean transformable = (sourceMimetype.startsWith("text/") return (sourceMimetype.startsWith("text/")
|| MIMETYPE_JAVASCRIPT.equals(sourceMimetype) || MIMETYPE_JAVASCRIPT.equals(sourceMimetype)
|| MIMETYPE_DITA.equals(sourceMimetype)) || MIMETYPE_DITA.equals(sourceMimetype))
&& MIMETYPE_TEXT_PLAIN.equals(targetMimetype); && MIMETYPE_TEXT_PLAIN.equals(targetMimetype);
return transformable;
} }
/** /**
@ -88,13 +83,14 @@ public class StringExtractingContentTransformer implements SelectableTransformer
* be unformatted but valid. * be unformatted but valid.
*/ */
@Override @Override
public void transform(File sourceFile, File targetFile, Map<String, String> parameters) throws Exception public void transform(File sourceFile, File targetFile, Map<String, String> parameters)
throws Exception
{ {
String sourceEncoding = parameters.get(SOURCE_ENCODING); String sourceEncoding = parameters.get(SOURCE_ENCODING);
String targetEncoding = parameters.get(TARGET_ENCODING); String targetEncoding = parameters.get(TARGET_ENCODING);
if(logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
logger.debug("Performing text to text transform with sourceEncoding=" + sourceEncoding logger.debug("Performing text to text transform with sourceEncoding=" + sourceEncoding
+ " targetEncoding=" + targetEncoding); + " targetEncoding=" + targetEncoding);
@ -107,23 +103,27 @@ public class StringExtractingContentTransformer implements SelectableTransformer
// Build reader // Build reader
if (sourceEncoding == null) if (sourceEncoding == null)
{ {
charReader = new BufferedReader(new InputStreamReader(new FileInputStream(sourceFile))); charReader = new BufferedReader(
new InputStreamReader(new FileInputStream(sourceFile)));
} }
else else
{ {
checkEncodingParameter(sourceEncoding, SOURCE_ENCODING); checkEncodingParameter(sourceEncoding, SOURCE_ENCODING);
charReader = new BufferedReader(new InputStreamReader(new FileInputStream(sourceFile), sourceEncoding)); charReader = new BufferedReader(
new InputStreamReader(new FileInputStream(sourceFile), sourceEncoding));
} }
// Build writer // Build writer
if (targetEncoding == null) if (targetEncoding == null)
{ {
charWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(targetFile))); charWriter = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(targetFile)));
} }
else else
{ {
checkEncodingParameter( targetEncoding, TARGET_ENCODING); checkEncodingParameter(targetEncoding, TARGET_ENCODING);
charWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(targetFile), targetEncoding)); charWriter = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(targetFile), targetEncoding));
} }
// copy from the one to the other // copy from the one to the other
@ -157,12 +157,14 @@ public class StringExtractingContentTransformer implements SelectableTransformer
{ {
if (!Charset.isSupported(encoding)) if (!Charset.isSupported(encoding))
{ {
throw new IllegalArgumentException(paramterName + "=" + encoding + " is not supported by the JVM."); throw new IllegalArgumentException(
paramterName + "=" + encoding + " is not supported by the JVM.");
} }
} }
catch (IllegalCharsetNameException e) catch (IllegalCharsetNameException e)
{ {
throw new IllegalArgumentException(paramterName + "=" + encoding + " is not a valid encoding."); throw new IllegalArgumentException(
paramterName + "=" + encoding + " is not a valid encoding.");
} }
} }
} }

View File

@ -26,14 +26,11 @@
*/ */
package org.alfresco.transformer.transformers; package org.alfresco.transformer.transformers;
import org.alfresco.error.AlfrescoRuntimeException; import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_DITA;
import org.apache.pdfbox.pdmodel.PDDocument; import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_PDF;
import org.apache.pdfbox.pdmodel.PDPage; import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_CSV;
import org.apache.pdfbox.pdmodel.PDPageContentStream; import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_PLAIN;
import org.apache.pdfbox.pdmodel.font.PDType1Font; import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_XML;
import org.apache.pdfbox.tools.TextToPDF;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -49,14 +46,16 @@ import java.nio.charset.Charset;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_DITA; import org.alfresco.error.AlfrescoRuntimeException;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_PDF; import org.apache.pdfbox.pdmodel.PDDocument;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_CSV; import org.apache.pdfbox.pdmodel.PDPage;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_PLAIN; import org.apache.pdfbox.pdmodel.PDPageContentStream;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_XML; import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.tools.TextToPDF;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
*
* <p> * <p>
* This code is based on a class of the same name originally implemented in alfresco-repository. * This code is based on a class of the same name originally implemented in alfresco-repository.
* </p> * </p>
@ -65,14 +64,14 @@ import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_XML;
* *
* @author Derek Hulley * @author Derek Hulley
* @author eknizat * @author eknizat
*/ */
public class TextToPdfContentTransformer implements SelectableTransformer public class TextToPdfContentTransformer implements SelectableTransformer
{ {
private static final Logger logger = LoggerFactory.getLogger(TextToPdfContentTransformer.class); private static final Logger logger = LoggerFactory.getLogger(TextToPdfContentTransformer.class);
public static final String PAGE_LIMIT = "pageLimit"; public static final String PAGE_LIMIT = "pageLimit";
private PagedTextToPDF transformer; private final PagedTextToPDF transformer;
public TextToPdfContentTransformer() public TextToPdfContentTransformer()
{ {
@ -83,11 +82,12 @@ public class TextToPdfContentTransformer implements SelectableTransformer
{ {
try try
{ {
transformer.setFont(transformer.getStandardFont(fontName)); transformer.setFont(PagedTextToPDF.getStandardFont(fontName));
} }
catch (Throwable e) catch (Throwable e)
{ {
throw new AlfrescoRuntimeException("Unable to set Standard Font for PDF generation: " + fontName, e); throw new AlfrescoRuntimeException(
"Unable to set Standard Font for PDF generation: " + fontName, e);
} }
} }
@ -99,29 +99,30 @@ public class TextToPdfContentTransformer implements SelectableTransformer
} }
catch (Throwable e) catch (Throwable e)
{ {
throw new AlfrescoRuntimeException("Unable to set Font Size for PDF generation: " + fontSize); throw new AlfrescoRuntimeException(
"Unable to set Font Size for PDF generation: " + fontSize);
} }
} }
@Override @Override
public boolean isTransformable(String sourceMimetype, String targetMimetype, Map<String, String> parameters) public boolean isTransformable(String sourceMimetype, String targetMimetype,
Map<String, String> parameters)
{ {
boolean transformable = ( (MIMETYPE_TEXT_PLAIN.equals(sourceMimetype) return (MIMETYPE_TEXT_PLAIN.equals(sourceMimetype) ||
|| MIMETYPE_TEXT_CSV.equals(sourceMimetype) MIMETYPE_TEXT_CSV.equals(sourceMimetype) ||
|| MIMETYPE_DITA.equals(sourceMimetype) MIMETYPE_DITA.equals(sourceMimetype) ||
|| MIMETYPE_XML.equals(sourceMimetype) ) MIMETYPE_XML.equals(sourceMimetype)) &&
&& MIMETYPE_PDF.equals(targetMimetype)); MIMETYPE_PDF.equals(targetMimetype);
return transformable;
} }
@Override @Override
public void transform(File sourceFile, File targetFile, Map<String, String> parameters) throws Exception public void transform(File sourceFile, File targetFile, Map<String, String> parameters)
throws Exception
{ {
String sourceEncoding = parameters.get(SOURCE_ENCODING); String sourceEncoding = parameters.get(SOURCE_ENCODING);
String stringPageLimit = parameters.get(PAGE_LIMIT); String stringPageLimit = parameters.get(PAGE_LIMIT);
int pageLimit = -1; int pageLimit = -1;
if ( stringPageLimit != null) if (stringPageLimit != null)
{ {
pageLimit = parseInt(stringPageLimit, PAGE_LIMIT); pageLimit = parseInt(stringPageLimit, PAGE_LIMIT);
} }
@ -148,18 +149,19 @@ public class TextToPdfContentTransformer implements SelectableTransformer
protected InputStreamReader buildReader(InputStream is, String encoding) protected InputStreamReader buildReader(InputStream is, String encoding)
{ {
// If they gave an encoding, try to use it // If they gave an encoding, try to use it
if(encoding != null) if (encoding != null)
{ {
Charset charset = null; Charset charset = null;
try try
{ {
charset = Charset.forName(encoding); charset = Charset.forName(encoding);
} catch(Exception e) }
catch (Exception e)
{ {
logger.warn("JVM doesn't understand encoding '" + encoding + logger.warn("JVM doesn't understand encoding '" + encoding +
"' when transforming text to pdf"); "' when transforming text to pdf");
} }
if(charset != null) if (charset != null)
{ {
logger.debug("Processing plain text in encoding " + charset.displayName()); logger.debug("Processing plain text in encoding " + charset.displayName());
return new InputStreamReader(is, charset); return new InputStreamReader(is, charset);
@ -175,24 +177,31 @@ public class TextToPdfContentTransformer implements SelectableTransformer
{ {
// REPO-1066: duplicating the following lines from org.apache.pdfbox.tools.TextToPDF because they made them private // REPO-1066: duplicating the following lines from org.apache.pdfbox.tools.TextToPDF because they made them private
// before the upgrade to pdfbox 2.0.8, in pdfbox 1.8, this piece of code was public in org.apache.pdfbox.pdmodel.font.PDType1Font // before the upgrade to pdfbox 2.0.8, in pdfbox 1.8, this piece of code was public in org.apache.pdfbox.pdmodel.font.PDType1Font
static PDType1Font getStandardFont(String name) { static PDType1Font getStandardFont(String name)
return (PDType1Font)STANDARD_14.get(name); {
return STANDARD_14.get(name);
} }
private static final Map<String, PDType1Font> STANDARD_14 = new HashMap<String, PDType1Font>();
private static final Map<String, PDType1Font> STANDARD_14 = new HashMap<>();
static static
{ {
STANDARD_14.put(PDType1Font.TIMES_ROMAN.getBaseFont(), PDType1Font.TIMES_ROMAN); STANDARD_14.put(PDType1Font.TIMES_ROMAN.getBaseFont(), PDType1Font.TIMES_ROMAN);
STANDARD_14.put(PDType1Font.TIMES_BOLD.getBaseFont(), PDType1Font.TIMES_BOLD); STANDARD_14.put(PDType1Font.TIMES_BOLD.getBaseFont(), PDType1Font.TIMES_BOLD);
STANDARD_14.put(PDType1Font.TIMES_ITALIC.getBaseFont(), PDType1Font.TIMES_ITALIC); STANDARD_14.put(PDType1Font.TIMES_ITALIC.getBaseFont(), PDType1Font.TIMES_ITALIC);
STANDARD_14.put(PDType1Font.TIMES_BOLD_ITALIC.getBaseFont(), PDType1Font.TIMES_BOLD_ITALIC); STANDARD_14.put(PDType1Font.TIMES_BOLD_ITALIC.getBaseFont(),
PDType1Font.TIMES_BOLD_ITALIC);
STANDARD_14.put(PDType1Font.HELVETICA.getBaseFont(), PDType1Font.HELVETICA); STANDARD_14.put(PDType1Font.HELVETICA.getBaseFont(), PDType1Font.HELVETICA);
STANDARD_14.put(PDType1Font.HELVETICA_BOLD.getBaseFont(), PDType1Font.HELVETICA_BOLD); STANDARD_14.put(PDType1Font.HELVETICA_BOLD.getBaseFont(), PDType1Font.HELVETICA_BOLD);
STANDARD_14.put(PDType1Font.HELVETICA_OBLIQUE.getBaseFont(), PDType1Font.HELVETICA_OBLIQUE); STANDARD_14.put(PDType1Font.HELVETICA_OBLIQUE.getBaseFont(),
STANDARD_14.put(PDType1Font.HELVETICA_BOLD_OBLIQUE.getBaseFont(), PDType1Font.HELVETICA_BOLD_OBLIQUE); PDType1Font.HELVETICA_OBLIQUE);
STANDARD_14.put(PDType1Font.HELVETICA_BOLD_OBLIQUE.getBaseFont(),
PDType1Font.HELVETICA_BOLD_OBLIQUE);
STANDARD_14.put(PDType1Font.COURIER.getBaseFont(), PDType1Font.COURIER); STANDARD_14.put(PDType1Font.COURIER.getBaseFont(), PDType1Font.COURIER);
STANDARD_14.put(PDType1Font.COURIER_BOLD.getBaseFont(), PDType1Font.COURIER_BOLD); STANDARD_14.put(PDType1Font.COURIER_BOLD.getBaseFont(), PDType1Font.COURIER_BOLD);
STANDARD_14.put(PDType1Font.COURIER_OBLIQUE.getBaseFont(), PDType1Font.COURIER_OBLIQUE); STANDARD_14.put(PDType1Font.COURIER_OBLIQUE.getBaseFont(), PDType1Font.COURIER_OBLIQUE);
STANDARD_14.put(PDType1Font.COURIER_BOLD_OBLIQUE.getBaseFont(), PDType1Font.COURIER_BOLD_OBLIQUE); STANDARD_14.put(PDType1Font.COURIER_BOLD_OBLIQUE.getBaseFont(),
PDType1Font.COURIER_BOLD_OBLIQUE);
STANDARD_14.put(PDType1Font.SYMBOL.getBaseFont(), PDType1Font.SYMBOL); STANDARD_14.put(PDType1Font.SYMBOL.getBaseFont(), PDType1Font.SYMBOL);
STANDARD_14.put(PDType1Font.ZAPF_DINGBATS.getBaseFont(), PDType1Font.ZAPF_DINGBATS); STANDARD_14.put(PDType1Font.ZAPF_DINGBATS.getBaseFont(), PDType1Font.ZAPF_DINGBATS);
} }
@ -210,23 +219,23 @@ public class TextToPdfContentTransformer implements SelectableTransformer
try try
{ {
final int margin = 40; final int margin = 40;
float height = getFont().getFontDescriptor().getFontBoundingBox().getHeight()/1000; float height = getFont().getFontDescriptor().getFontBoundingBox().getHeight() / 1000;
//calculate font height and increase by 5 percent. //calculate font height and increase by 5 percent.
height = height*getFontSize()*1.05f; height = height * getFontSize() * 1.05f;
doc = new PDDocument(); doc = new PDDocument();
BufferedReader data = new BufferedReader( text ); BufferedReader data = new BufferedReader(text);
String nextLine = null; String nextLine;
PDPage page = new PDPage(); PDPage page = new PDPage();
PDPageContentStream contentStream = null; PDPageContentStream contentStream = null;
float y = -1; float y = -1;
float maxStringLength = page.getMediaBox().getWidth() - 2*margin; float maxStringLength = page.getMediaBox().getWidth() - 2 * margin;
// There is a special case of creating a PDF document from an empty string. // There is a special case of creating a PDF document from an empty string.
boolean textIsEmpty = true; boolean textIsEmpty = true;
outer: outer:
while( (nextLine = data.readLine()) != null ) while ((nextLine = data.readLine()) != null)
{ {
// The input text is nonEmpty. New pages will be created and added // The input text is nonEmpty. New pages will be created and added
@ -234,29 +243,30 @@ public class TextToPdfContentTransformer implements SelectableTransformer
// the text. // the text.
textIsEmpty = false; textIsEmpty = false;
String[] lineWords = nextLine.trim().split( " " ); String[] lineWords = nextLine.trim().split(" ");
int lineIndex = 0; int lineIndex = 0;
while( lineIndex < lineWords.length ) while (lineIndex < lineWords.length)
{ {
StringBuffer nextLineToDraw = new StringBuffer(); final StringBuilder nextLineToDraw = new StringBuilder();
float lengthIfUsingNextWord = 0; float lengthIfUsingNextWord = 0;
do do
{ {
nextLineToDraw.append( lineWords[lineIndex] ); nextLineToDraw.append(lineWords[lineIndex]);
nextLineToDraw.append( " " ); nextLineToDraw.append(" ");
lineIndex++; lineIndex++;
if( lineIndex < lineWords.length ) if (lineIndex < lineWords.length)
{ {
String lineWithNextWord = nextLineToDraw.toString() + lineWords[lineIndex]; String lineWithNextWord = nextLineToDraw.toString() + lineWords[lineIndex];
lengthIfUsingNextWord = lengthIfUsingNextWord =
(getFont().getStringWidth( lineWithNextWord )/1000) * getFontSize(); (getFont().getStringWidth(
lineWithNextWord) / 1000) * getFontSize();
} }
} }
while( lineIndex < lineWords.length && while (lineIndex < lineWords.length &&
lengthIfUsingNextWord < maxStringLength ); lengthIfUsingNextWord < maxStringLength);
if( y < margin ) if (y < margin)
{ {
int test = pageCount +1; int test = pageCount + 1;
if (pageLimit > 0 && (pageCount++ >= pageLimit)) if (pageLimit > 0 && (pageCount++ >= pageLimit))
{ {
// pageLimits.getAction().throwIOExceptionIfRequired("Page limit ("+pageLimit+ // pageLimits.getAction().throwIOExceptionIfRequired("Page limit ("+pageLimit+
@ -267,8 +277,8 @@ public class TextToPdfContentTransformer implements SelectableTransformer
// We have crossed the end-of-page boundary and need to extend the // We have crossed the end-of-page boundary and need to extend the
// document by another page. // document by another page.
page = new PDPage(); page = new PDPage();
doc.addPage( page ); doc.addPage(page);
if( contentStream != null ) if (contentStream != null)
{ {
contentStream.endText(); contentStream.endText();
contentStream.close(); contentStream.close();
@ -277,18 +287,17 @@ public class TextToPdfContentTransformer implements SelectableTransformer
contentStream.setFont(getFont(), getFontSize()); contentStream.setFont(getFont(), getFontSize());
contentStream.beginText(); contentStream.beginText();
y = page.getMediaBox().getHeight() - margin + height; y = page.getMediaBox().getHeight() - margin + height;
contentStream.moveTextPositionByAmount( contentStream.moveTextPositionByAmount(margin, y);
margin, y );
} }
//System.out.println( "Drawing string at " + x + "," + y ); //System.out.println( "Drawing string at " + x + "," + y );
if( contentStream == null ) if (contentStream == null)
{ {
throw new IOException( "Error:Expected non-null content stream." ); throw new IOException("Error:Expected non-null content stream.");
} }
contentStream.moveTextPositionByAmount( 0, -height); contentStream.moveTextPositionByAmount(0, -height);
y -= height; y -= height;
contentStream.drawString( nextLineToDraw.toString() ); contentStream.drawString(nextLineToDraw.toString());
} }
} }
@ -300,15 +309,15 @@ public class TextToPdfContentTransformer implements SelectableTransformer
doc.addPage(page); doc.addPage(page);
} }
if( contentStream != null ) if (contentStream != null)
{ {
contentStream.endText(); contentStream.endText();
contentStream.close(); contentStream.close();
} }
} }
catch( IOException io ) catch (IOException io)
{ {
if( doc != null ) if (doc != null)
{ {
doc.close(); doc.close();
} }

View File

@ -26,30 +26,7 @@
*/ */
package org.alfresco.transformer; package org.alfresco.transformer;
import org.alfresco.error.AlfrescoRuntimeException; import static java.nio.charset.StandardCharsets.UTF_8;
import org.alfresco.transform.client.model.TransformRequest;
import org.alfresco.transformer.transformers.AppleIWorksContentTransformer;
import org.alfresco.transformer.transformers.HtmlParserContentTransformer;
import org.alfresco.transformer.transformers.SelectingTransformer;
import org.alfresco.transformer.transformers.StringExtractingContentTransformer;
import org.alfresco.transformer.transformers.TextToPdfContentTransformer;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_HTML; import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_HTML;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IMAGE_JPEG; import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IMAGE_JPEG;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IWORK_KEYNOTE; import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_IWORK_KEYNOTE;
@ -64,18 +41,37 @@ import static org.springframework.http.HttpStatus.OK;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.transform.client.model.TransformRequest;
import org.alfresco.transformer.transformers.SelectingTransformer;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@WebMvcTest(MiscController.class) @WebMvcTest(MiscController.class)
@Import({SelectingTransformer.class}) @Import({SelectingTransformer.class})
public class MiscControllerTest extends AbstractTransformerControllerTest public class MiscControllerTest extends AbstractTransformerControllerTest
{ {
@Autowired @Autowired
private MiscController controller; private MiscController controller;
private String sourceEncoding = "UTF-8"; private final String sourceEncoding = "UTF-8";
private String targetEncoding = "UTF-8"; private final String targetEncoding = "UTF-8";
private String targetMimetype = MIMETYPE_TEXT_PLAIN; private final String targetMimetype = MIMETYPE_TEXT_PLAIN;
@Before @Before
public void before() throws Exception public void before() throws Exception
@ -88,12 +84,13 @@ public class MiscControllerTest extends AbstractTransformerControllerTest
expectedSourceFileBytes = readTestFile(sourceExtension); expectedSourceFileBytes = readTestFile(sourceExtension);
expectedTargetFileBytes = readTestFile(targetExtension); expectedTargetFileBytes = readTestFile(targetExtension);
//expectedTargetFileBytes = null; //expectedTargetFileBytes = null;
sourceFile = new MockMultipartFile("file", "quick." + sourceExtension, sourceMimetype, expectedSourceFileBytes); sourceFile = new MockMultipartFile("file", "quick." + sourceExtension, sourceMimetype,
expectedSourceFileBytes);
} }
@Override @Override
protected void mockTransformCommand(String sourceExtension, String targetExtension, String sourceMimetype, boolean readTargetFileBytes) throws IOException protected void mockTransformCommand(String sourceExtension, String targetExtension,
String sourceMimetype, boolean readTargetFileBytes) throws IOException
{ {
} }
@ -110,7 +107,8 @@ public class MiscControllerTest extends AbstractTransformerControllerTest
@Override @Override
// Add extra required parameters to the request. // Add extra required parameters to the request.
protected MockHttpServletRequestBuilder mockMvcRequest(String url, MockMultipartFile sourceFile, String... params) protected MockHttpServletRequestBuilder mockMvcRequest(String url, MockMultipartFile sourceFile,
String... params)
{ {
return super.mockMvcRequest(url, sourceFile, params) return super.mockMvcRequest(url, sourceFile, params)
.param("targetEncoding", targetEncoding) .param("targetEncoding", targetEncoding)
@ -130,7 +128,7 @@ public class MiscControllerTest extends AbstractTransformerControllerTest
@Test @Test
public void testHTMLtoString() throws Exception public void testHTMLtoString() throws Exception
{ {
final String NEWLINE = System.getProperty ("line.separator"); final String NEWLINE = System.getProperty("line.separator");
final String TITLE = "Testing!"; final String TITLE = "Testing!";
final String TEXT_P1 = "This is some text in English"; final String TEXT_P1 = "This is some text in English";
final String TEXT_P2 = "This is more text in English"; final String TEXT_P2 = "This is more text in English";
@ -150,18 +148,19 @@ public class MiscControllerTest extends AbstractTransformerControllerTest
"UTF-8", "UTF-8",
expected.getBytes()); expected.getBytes());
String contentResult = new String(result.getResponse().getContentAsByteArray(), targetEncoding); String contentResult = new String(result.getResponse().getContentAsByteArray(),
assertTrue("The content did not include \""+expected, contentResult.contains(expected)); targetEncoding);
assertTrue("The content did not include \"" + expected, contentResult.contains(expected));
} }
@Test @Test
public void testStringToString() throws Exception public void testStringToString() throws Exception
{ {
String expected = null; String expected;
byte[] content = null; byte[] content;
try try
{ {
content = "azAz10!<21>$%^&*()\t\r\n".getBytes("UTF-8"); content = "azAz10!<21>$%^&*()\t\r\n".getBytes(UTF_8);
expected = new String(content, "MacDingbat"); expected = new String(content, "MacDingbat");
} }
catch (UnsupportedEncodingException e) catch (UnsupportedEncodingException e)
@ -177,8 +176,9 @@ public class MiscControllerTest extends AbstractTransformerControllerTest
"UTF-8", "UTF-8",
content); content);
String contentResult = new String(result.getResponse().getContentAsByteArray(), targetEncoding); String contentResult = new String(result.getResponse().getContentAsByteArray(),
assertTrue("The content did not include \""+expected, contentResult.contains(expected)); targetEncoding);
assertTrue("The content did not include \"" + expected, contentResult.contains(expected));
} }
@Test @Test
@ -195,21 +195,21 @@ public class MiscControllerTest extends AbstractTransformerControllerTest
"UTF-8", "UTF-8",
content); content);
assertEquals("Returned content should be empty for an empty source file", 0, result.getResponse().getContentLength()); assertEquals("Returned content should be empty for an empty source file", 0,
result.getResponse().getContentLength());
} }
@Test @Test
public void textToPdf() throws Exception public void textToPdf() throws Exception
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String expected = null; for (int i = 1; i <= 5; i++)
for (int i=1; i<=5; i++)
{ {
sb.append(i); sb.append(i);
sb.append(" I must not talk in class or feed my homework to my cat.\n"); sb.append(" I must not talk in class or feed my homework to my cat.\n");
} }
sb.append("\nBart\n"); sb.append("\nBart\n");
expected = sb.toString(); String expected = sb.toString();
MvcResult result = sendText("txt", MvcResult result = sendText("txt",
"UTF-8", "UTF-8",
@ -257,23 +257,29 @@ public class MiscControllerTest extends AbstractTransformerControllerTest
imageBasedTransform("docx", MIMETYPE_OPENXML_WORDPROCESSING, MIMETYPE_IMAGE_JPEG, "jpeg"); imageBasedTransform("docx", MIMETYPE_OPENXML_WORDPROCESSING, MIMETYPE_IMAGE_JPEG, "jpeg");
} }
private void imageBasedTransform(String sourceExtension, String sourceMimetype, String targetMimetype, String targetExtension) throws Exception private void imageBasedTransform(String sourceExtension, String sourceMimetype,
String targetMimetype, String targetExtension) throws Exception
{ {
MockMultipartFile sourceFilex = new MockMultipartFile("file", "test_file." + sourceExtension, sourceMimetype, readTestFile(sourceExtension)); MockMultipartFile sourceFilex = new MockMultipartFile("file",
"test_file." + sourceExtension, sourceMimetype, readTestFile(sourceExtension));
MockHttpServletRequestBuilder requestBuilder = super.mockMvcRequest("/transform", sourceFilex) MockHttpServletRequestBuilder requestBuilder = super
.mockMvcRequest("/transform", sourceFilex)
.param("targetExtension", "jpeg") .param("targetExtension", "jpeg")
.param("targetMimetype", targetMimetype) .param("targetMimetype", targetMimetype)
.param("sourceMimetype", sourceMimetype); .param("sourceMimetype",
sourceMimetype);
MvcResult result = mockMvc.perform(requestBuilder) MvcResult result = mockMvc
.perform(requestBuilder)
.andExpect(status().is(OK.value())) .andExpect(status().is(OK.value()))
.andExpect(header().string("Content-Disposition", "attachment; filename*= UTF-8''test_file." + targetExtension)) .andExpect(header().string("Content-Disposition",
"attachment; filename*= UTF-8''test_file." + targetExtension))
.andReturn(); .andReturn();
assertTrue("Expected image content but content is empty.",result.getResponse().getContentLengthLong() > 0L); assertTrue("Expected image content but content is empty.",
result.getResponse().getContentLengthLong() > 0L);
} }
private MvcResult sendText(String sourceExtension, private MvcResult sendText(String sourceExtension,
String sourceEncoding, String sourceEncoding,
String sourceMimetype, String sourceMimetype,
@ -282,21 +288,23 @@ public class MiscControllerTest extends AbstractTransformerControllerTest
String targetEncoding, String targetEncoding,
byte[] content) throws Exception byte[] content) throws Exception
{ {
MockMultipartFile sourceFilex = new MockMultipartFile("file", "test_file." + sourceExtension, sourceMimetype, content); MockMultipartFile sourceFilex = new MockMultipartFile("file",
"test_file." + sourceExtension, sourceMimetype, content);
MockHttpServletRequestBuilder requestBuilder = super.mockMvcRequest("/transform", sourceFilex) MockHttpServletRequestBuilder requestBuilder = super
.mockMvcRequest("/transform", sourceFilex)
.param("targetExtension", targetExtension) .param("targetExtension", targetExtension)
.param("targetEncoding", targetEncoding) .param("targetEncoding", targetEncoding)
.param("targetMimetype", targetMimetype) .param("targetMimetype", targetMimetype)
.param("sourceEncoding", sourceEncoding) .param("sourceEncoding", sourceEncoding)
.param("sourceMimetype", sourceMimetype); .param("sourceMimetype", sourceMimetype);
return mockMvc
MvcResult result = mockMvc.perform(requestBuilder) .perform(requestBuilder)
.andExpect(status().is(OK.value())) .andExpect(status().is(OK.value()))
.andExpect(header().string("Content-Disposition", "attachment; filename*= "+targetEncoding+"''test_file." + targetExtension)). .andExpect(header().string("Content-Disposition",
andReturn(); "attachment; filename*= " + targetEncoding + "''test_file." + targetExtension))
return result; .andReturn();
} }
private String clean(String text) private String clean(String text)
@ -307,5 +315,4 @@ public class MiscControllerTest extends AbstractTransformerControllerTest
text = text.replaceAll("\\n", ""); text = text.replaceAll("\\n", "");
return text; return text;
} }
} }

View File

@ -26,16 +26,16 @@
*/ */
package org.alfresco.transformer; package org.alfresco.transformer;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_HTML;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_PLAIN;
import java.util.UUID;
import org.alfresco.transform.client.model.TransformRequest; import org.alfresco.transform.client.model.TransformRequest;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import java.util.UUID;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_HTML;
import static org.alfresco.transform.client.model.Mimetype.MIMETYPE_TEXT_PLAIN;
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = {"activemq.url=nio://localhost:61616"}) properties = {"activemq.url=nio://localhost:61616"})
@ -44,7 +44,8 @@ public class MiscQueueTransformServiceIT extends AbstractQueueTransformServiceIT
@Override @Override
protected TransformRequest buildRequest() protected TransformRequest buildRequest()
{ {
return TransformRequest.builder() return TransformRequest
.builder()
.withRequestId(UUID.randomUUID().toString()) .withRequestId(UUID.randomUUID().toString())
.withSourceMediaType(MIMETYPE_HTML) .withSourceMediaType(MIMETYPE_HTML)
.withTargetMediaType(MIMETYPE_TEXT_PLAIN) .withTargetMediaType(MIMETYPE_TEXT_PLAIN)

View File

@ -26,13 +26,8 @@
*/ */
package org.alfresco.transformer.transformers; package org.alfresco.transformer.transformers;
import org.junit.Test; import static org.alfresco.transformer.transformers.StringExtractingContentTransformer.SOURCE_ENCODING;
import org.junit.runner.RunWith; import static org.junit.Assert.assertEquals;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -41,9 +36,11 @@ import java.nio.file.Files;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static org.alfresco.transformer.transformers.StringExtractingContentTransformer.SOURCE_ENCODING; import org.junit.Test;
import static org.alfresco.transformer.transformers.StringExtractingContentTransformer.TARGET_ENCODING; import org.junit.runner.RunWith;
import static org.junit.Assert.*; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@Import(HtmlParserContentTransformer.class) @Import(HtmlParserContentTransformer.class)
@ -63,7 +60,7 @@ public class HtmlParserContentTransformerTest
@Test @Test
public void testEncodingHandling() throws Exception public void testEncodingHandling() throws Exception
{ {
final String NEWLINE = System.getProperty ("line.separator"); final String NEWLINE = System.getProperty("line.separator");
final String TITLE = "Testing!"; final String TITLE = "Testing!";
final String TEXT_P1 = "This is some text in English"; final String TEXT_P1 = "This is some text in English";
final String TEXT_P2 = "This is more text in English"; final String TEXT_P2 = "This is more text in English";
@ -82,7 +79,7 @@ public class HtmlParserContentTransformerTest
{ {
// Content set to ISO 8859-1 // Content set to ISO 8859-1
tmpS = File.createTempFile("AlfrescoTestSource_", ".html"); tmpS = File.createTempFile("AlfrescoTestSource_", ".html");
writeToFile(tmpS, partA+partB+partC, "ISO-8859-1"); writeToFile(tmpS, partA + partB + partC, "ISO-8859-1");
tmpD = File.createTempFile("AlfrescoTestTarget_", ".txt"); tmpD = File.createTempFile("AlfrescoTestTarget_", ".txt");
@ -96,7 +93,7 @@ public class HtmlParserContentTransformerTest
// Content set to UTF-8 // Content set to UTF-8
tmpS = File.createTempFile("AlfrescoTestSource_", ".html"); tmpS = File.createTempFile("AlfrescoTestSource_", ".html");
writeToFile(tmpS, partA+partB+partC, "UTF-8"); writeToFile(tmpS, partA + partB + partC, "UTF-8");
tmpD = File.createTempFile("AlfrescoTestTarget_", ".txt"); tmpD = File.createTempFile("AlfrescoTestTarget_", ".txt");
parameters = new HashMap<>(); parameters = new HashMap<>();
@ -106,10 +103,9 @@ public class HtmlParserContentTransformerTest
tmpS.delete(); tmpS.delete();
tmpD.delete(); tmpD.delete();
// Content set to UTF-16 // Content set to UTF-16
tmpS = File.createTempFile("AlfrescoTestSource_", ".html"); tmpS = File.createTempFile("AlfrescoTestSource_", ".html");
writeToFile(tmpS, partA+partB+partC, "UTF-16"); writeToFile(tmpS, partA + partB + partC, "UTF-16");
tmpD = File.createTempFile("AlfrescoTestTarget_", ".txt"); tmpD = File.createTempFile("AlfrescoTestTarget_", ".txt");
parameters = new HashMap<>(); parameters = new HashMap<>();
@ -129,9 +125,9 @@ public class HtmlParserContentTransformerTest
// Content set to ISO 8859-1, meta set to UTF-8 // Content set to ISO 8859-1, meta set to UTF-8
tmpS = File.createTempFile("AlfrescoTestSource_", ".html"); tmpS = File.createTempFile("AlfrescoTestSource_", ".html");
String str = partA+ String str = partA +
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">" + "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">" +
partB+partC; partB + partC;
writeToFile(tmpS, str, "UTF-8"); writeToFile(tmpS, str, "UTF-8");
@ -144,7 +140,6 @@ public class HtmlParserContentTransformerTest
tmpS.delete(); tmpS.delete();
tmpD.delete(); tmpD.delete();
// Note - we can't test UTF-16 with only a meta encoding, // Note - we can't test UTF-16 with only a meta encoding,
// because without that the parser won't know about the // because without that the parser won't know about the
// 2 byte format so won't be able to identify the meta tag // 2 byte format so won't be able to identify the meta tag
@ -164,10 +159,8 @@ public class HtmlParserContentTransformerTest
} }
} }
private String readFromFile(File file, String encoding) throws Exception private String readFromFile(File file, final String encoding) throws Exception
{ {
String content = "wrong content"; return new String(Files.readAllBytes(file.toPath()), encoding);
content = new String(Files.readAllBytes(file.toPath()), encoding);
return content;
} }
} }

View File

@ -26,15 +26,8 @@
*/ */
package org.alfresco.transformer.transformers; package org.alfresco.transformer.transformers;
import org.apache.pdfbox.pdmodel.PDDocument; import static org.alfresco.transformer.transformers.TextToPdfContentTransformer.PAGE_LIMIT;
import org.apache.pdfbox.text.PDFTextStripper; import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -43,8 +36,14 @@ import java.io.StringWriter;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static org.alfresco.transformer.transformers.TextToPdfContentTransformer.PAGE_LIMIT; import org.apache.pdfbox.pdmodel.PDDocument;
import static org.junit.Assert.*; import org.apache.pdfbox.text.PDFTextStripper;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@Import(TextToPdfContentTransformer.class) @Import(TextToPdfContentTransformer.class)
@ -60,7 +59,6 @@ public class TextToPdfContentTransformerTest
transformer.setFontSize(20); transformer.setFontSize(20);
} }
@Test @Test
public void testUnlimitedPages() throws Exception public void testUnlimitedPages() throws Exception
{ {
@ -88,11 +86,11 @@ public class TextToPdfContentTransformerTest
private void transformTextAndCheckPageLength(int pageLimit) throws Exception private void transformTextAndCheckPageLength(int pageLimit) throws Exception
{ {
int pageLength = 32; int pageLength = 32;
int lines = (pageLength+10) * ((pageLimit > 0) ? pageLimit : 1); int lines = (pageLength + 10) * ((pageLimit > 0) ? pageLimit : 1);
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String checkText = null; String checkText = null;
int cutoff = pageLimit * pageLength; int cutoff = pageLimit * pageLength;
for (int i=1; i<=lines; i++) for (int i = 1; i <= lines; i++)
{ {
sb.append(i); sb.append(i);
sb.append(" I must not talk in class or feed my homework to my cat.\n"); sb.append(" I must not talk in class or feed my homework to my cat.\n");
@ -105,12 +103,12 @@ public class TextToPdfContentTransformerTest
transformTextAndCheck(text, "UTF-8", checkText, String.valueOf(pageLimit)); transformTextAndCheck(text, "UTF-8", checkText, String.valueOf(pageLimit));
} }
private void transformTextAndCheck(String text, String encoding, String checkText, String pageLimit) throws Exception private void transformTextAndCheck(String text, String encoding, String checkText,
String pageLimit) throws Exception
{ {
// Get a reader for the text // Get a reader for the text
File sourceFile = File.createTempFile("AlfrescoTestSource_", ".txt"); File sourceFile = File.createTempFile("AlfrescoTestSource_", ".txt");
writeToFile(sourceFile,text, encoding); writeToFile(sourceFile, text, encoding);
// And a temp writer // And a temp writer
File targetFile = File.createTempFile("AlfrescoTestTarget_", ".pdf"); File targetFile = File.createTempFile("AlfrescoTestTarget_", ".pdf");

View File

@ -26,20 +26,22 @@
*/ */
package org.alfresco.transformer; package org.alfresco.transformer;
import static java.util.stream.Collectors.joining;
import static org.alfresco.transformer.fs.FileManager.buildFile; import static org.alfresco.transformer.fs.FileManager.buildFile;
import static org.alfresco.transformer.fs.FileManager.createTargetFileName; import static org.alfresco.transformer.fs.FileManager.createTargetFileName;
import static org.alfresco.transformer.fs.FileManager.deleteFile; import static org.alfresco.transformer.fs.FileManager.deleteFile;
import static org.alfresco.transformer.fs.FileManager.getFilenameFromContentDisposition; import static org.alfresco.transformer.fs.FileManager.getFilenameFromContentDisposition;
import static org.alfresco.transformer.fs.FileManager.save; import static org.alfresco.transformer.fs.FileManager.save;
import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.OK; import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.util.StringUtils.getFilenameExtension;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.stream.Collectors;
import org.alfresco.transform.client.model.TransformReply; import org.alfresco.transform.client.model.TransformReply;
import org.alfresco.transform.client.model.TransformRequest; import org.alfresco.transform.client.model.TransformRequest;
@ -59,7 +61,6 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.validation.DirectFieldBindingResult; import org.springframework.validation.DirectFieldBindingResult;
import org.springframework.validation.Errors; import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -101,7 +102,9 @@ import com.fasterxml.jackson.databind.ObjectMapper;
*/ */
public abstract class AbstractTransformerController implements TransformController public abstract class AbstractTransformerController implements TransformController
{ {
private static final Logger logger = LoggerFactory.getLogger(AbstractTransformerController.class); private static final Logger logger = LoggerFactory.getLogger(
AbstractTransformerController.class);
private static String ENGINE_CONFIG = "engine_config.json"; private static String ENGINE_CONFIG = "engine_config.json";
@Autowired @Autowired
@ -160,9 +163,12 @@ public abstract class AbstractTransformerController implements TransformControll
final Errors errors = validateTransformRequest(request); final Errors errors = validateTransformRequest(request);
if (!errors.getAllErrors().isEmpty()) if (!errors.getAllErrors().isEmpty())
{ {
reply.setStatus(HttpStatus.BAD_REQUEST.value()); reply.setStatus(BAD_REQUEST.value());
reply.setErrorDetails(errors.getAllErrors().stream().map(Object::toString) reply.setErrorDetails(errors
.collect(Collectors.joining(", "))); .getAllErrors()
.stream()
.map(Object::toString)
.collect(joining(", ")));
logger.error("Invalid request, sending {}", reply); logger.error("Invalid request, sending {}", reply);
return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus())); return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus()));
@ -246,8 +252,8 @@ public abstract class AbstractTransformerController implements TransformControll
reply.setStatus(e.getStatusCode().value()); reply.setStatus(e.getStatusCode().value());
reply.setErrorDetails(messageWithCause("Failed at writing the transformed file. ", e)); reply.setErrorDetails(messageWithCause("Failed at writing the transformed file. ", e));
logger.error("Failed to save target file (HttpClientErrorException), sending {}" + logger.error("Failed to save target file (HttpClientErrorException), sending " + reply,
reply, e); e);
return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus())); return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus()));
} }
catch (Exception e) catch (Exception e)
@ -278,9 +284,9 @@ public abstract class AbstractTransformerController implements TransformControll
} }
reply.setTargetReference(targetRef.getEntry().getFileRef()); reply.setTargetReference(targetRef.getEntry().getFileRef());
reply.setStatus(HttpStatus.CREATED.value()); reply.setStatus(CREATED.value());
logger.info("Sending successful {}, timeout {} ms", reply); logger.info("Sending successful {}, timeout {} ms", reply, timeout);
return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus())); return new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus()));
} }
@ -297,7 +303,7 @@ public abstract class AbstractTransformerController implements TransformControll
* @param sourceReference reference to the file in 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 * @return the file containing the source content for the transformation
*/ */
private File loadSourceFile(final String sourceReference) throws Exception private File loadSourceFile(final String sourceReference)
{ {
ResponseEntity<Resource> responseEntity = alfrescoSharedFileStoreClient ResponseEntity<Resource> responseEntity = alfrescoSharedFileStoreClient
.retrieveFile(sourceReference); .retrieveFile(sourceReference);
@ -306,7 +312,7 @@ public abstract class AbstractTransformerController implements TransformControll
HttpHeaders headers = responseEntity.getHeaders(); HttpHeaders headers = responseEntity.getHeaders();
String filename = getFilenameFromContentDisposition(headers); String filename = getFilenameFromContentDisposition(headers);
String extension = StringUtils.getFilenameExtension(filename); String extension = getFilenameExtension(filename);
MediaType contentType = headers.getContentType(); MediaType contentType = headers.getContentType();
long size = headers.getContentLength(); long size = headers.getContentLength();

View File

@ -26,6 +26,11 @@
*/ */
package org.alfresco.transformer; package org.alfresco.transformer;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import java.util.Optional;
import javax.jms.Destination; import javax.jms.Destination;
import javax.jms.JMSException; import javax.jms.JMSException;
import javax.jms.Message; import javax.jms.Message;
@ -44,8 +49,6 @@ import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.support.converter.MessageConversionException; import org.springframework.jms.support.converter.MessageConversionException;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.Optional;
/** /**
* Queue Transformer service. * Queue Transformer service.
* This service reads all the requests for the particular engine, forwards them to the worker * This service reads all the requests for the particular engine, forwards them to the worker
@ -56,12 +59,11 @@ import java.util.Optional;
* created on 18/12/2018 * created on 18/12/2018
*/ */
@Component @Component
@ConditionalOnProperty(name="activemq.url") @ConditionalOnProperty(name = "activemq.url")
public class QueueTransformService public class QueueTransformService
{ {
private static final Logger logger = LoggerFactory.getLogger(QueueTransformService.class); private static final Logger logger = LoggerFactory.getLogger(QueueTransformService.class);
// TODO: I know this is not smart but all the the transformation logic is in the Controller. // TODO: I know this is not smart but all the the transformation logic is in the Controller.
// The controller also manages the probes. There's tons of refactoring needed there, hence this. Sorry. // The controller also manages the probes. There's tons of refactoring needed there, hence this. Sorry.
@Autowired @Autowired
@ -98,7 +100,9 @@ public class QueueTransformService
} }
catch (JMSException e) catch (JMSException e)
{ {
logger.error("Cannot find 'replyTo' destination queue for message with correlationID {}. Stopping. ", correlationId); logger.error(
"Cannot find 'replyTo' destination queue for message with correlationID {}. Stopping. ",
correlationId);
return; return;
} }
@ -151,14 +155,14 @@ public class QueueTransformService
String message = String message =
"MessageConversionException during T-Request deserialization of message with correlationID " "MessageConversionException during T-Request deserialization of message with correlationID "
+ correlationId + ": "; + correlationId + ": ";
throw new TransformException(HttpStatus.BAD_REQUEST.value(), message + e.getMessage()); throw new TransformException(BAD_REQUEST.value(), message + e.getMessage());
} }
catch (JMSException e) catch (JMSException e)
{ {
String message = String message =
"JMSException during T-Request deserialization of message with correlationID " "JMSException during T-Request deserialization of message with correlationID "
+ correlationId + ": "; + correlationId + ": ";
throw new TransformException(HttpStatus.INTERNAL_SERVER_ERROR.value(), throw new TransformException(INTERNAL_SERVER_ERROR.value(),
message + e.getMessage()); message + e.getMessage());
} }
catch (Exception e) catch (Exception e)
@ -166,20 +170,23 @@ public class QueueTransformService
String message = String message =
"Exception during T-Request deserialization of message with correlationID " "Exception during T-Request deserialization of message with correlationID "
+ correlationId + ": "; + correlationId + ": ";
throw new TransformException(HttpStatus.INTERNAL_SERVER_ERROR.value(), throw new TransformException(INTERNAL_SERVER_ERROR.value(),
message + e.getMessage()); message + e.getMessage());
} }
} }
private void replyWithInternalSvErr(final Destination destination, final String msg, final String correlationId) private void replyWithInternalSvErr(final Destination destination, final String msg,
{
replyWithError(destination, HttpStatus.INTERNAL_SERVER_ERROR, msg, correlationId);
}
private void replyWithError(final Destination destination, final HttpStatus status, final String msg,
final String correlationId) final String correlationId)
{ {
final TransformReply reply = TransformReply.builder() replyWithError(destination, INTERNAL_SERVER_ERROR, msg, correlationId);
}
private void replyWithError(final Destination destination, final HttpStatus status,
final String msg,
final String correlationId)
{
final TransformReply reply = TransformReply
.builder()
.withStatus(status.value()) .withStatus(status.value())
.withErrorDetails(msg) .withErrorDetails(msg)
.build(); .build();

View File

@ -26,6 +26,9 @@
*/ */
package org.alfresco.transformer.clients; package org.alfresco.transformer.clients;
import static org.springframework.http.HttpMethod.POST;
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA;
import java.io.File; import java.io.File;
import org.alfresco.transform.exceptions.TransformException; import org.alfresco.transform.exceptions.TransformException;
@ -36,8 +39,6 @@ import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.http.HttpEntity; import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpClientErrorException;
@ -87,11 +88,11 @@ public class AlfrescoSharedFileStoreClient
LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>(); LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("file", value); map.add("file", value);
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA); headers.setContentType(MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map,
headers); headers);
ResponseEntity<FileRefResponse> responseEntity = restTemplate ResponseEntity<FileRefResponse> responseEntity = restTemplate
.exchange(fileStoreUrl, HttpMethod.POST, requestEntity, FileRefResponse.class); .exchange(fileStoreUrl, POST, requestEntity, FileRefResponse.class);
return responseEntity.getBody(); return responseEntity.getBody();
} }
catch (HttpClientErrorException e) catch (HttpClientErrorException e)

View File

@ -26,12 +26,12 @@
*/ */
package org.alfresco.transformer.config; package org.alfresco.transformer.config;
import org.alfresco.transform.client.model.TransformRequestValidator;
import org.alfresco.transformer.TransformInterceptor; import org.alfresco.transformer.TransformInterceptor;
import org.alfresco.transformer.clients.AlfrescoSharedFileStoreClient; import org.alfresco.transformer.clients.AlfrescoSharedFileStoreClient;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import org.alfresco.transform.client.model.TransformRequestValidator;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@ -40,16 +40,18 @@ public class WebApplicationConfig implements WebMvcConfigurer
{ {
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry)
registry.addInterceptor(transformInterceptor()).addPathPatterns("/transform", "/live", "/ready"); {
registry.addInterceptor(transformInterceptor()).addPathPatterns("/transform", "/live",
"/ready");
} }
@Bean @Bean
public TransformInterceptor transformInterceptor() { public TransformInterceptor transformInterceptor()
{
return new TransformInterceptor(); return new TransformInterceptor();
} }
@Bean @Bean
public RestTemplate restTemplate() public RestTemplate restTemplate()
{ {
@ -57,7 +59,8 @@ public class WebApplicationConfig implements WebMvcConfigurer
} }
@Bean @Bean
public AlfrescoSharedFileStoreClient alfrescoSharedFileStoreClient(){ public AlfrescoSharedFileStoreClient alfrescoSharedFileStoreClient()
{
return new AlfrescoSharedFileStoreClient(); return new AlfrescoSharedFileStoreClient();
} }

View File

@ -37,6 +37,7 @@ import org.alfresco.util.exec.RuntimeExec;
import org.alfresco.util.exec.RuntimeExec.ExecutionResult; import org.alfresco.util.exec.RuntimeExec.ExecutionResult;
/** /**
*
*/ */
public abstract class AbstractCommandExecutor implements CommandExecutor public abstract class AbstractCommandExecutor implements CommandExecutor
{ {

View File

@ -26,9 +26,12 @@
*/ */
package org.alfresco.transformer.fs; package org.alfresco.transformer.fs;
import static org.springframework.http.HttpHeaders.CONTENT_DISPOSITION;
import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.INSUFFICIENT_STORAGE; import static org.springframework.http.HttpStatus.INSUFFICIENT_STORAGE;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.util.StringUtils.getFilename;
import static org.springframework.util.StringUtils.getFilenameExtension;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -46,11 +49,11 @@ import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource; import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.UriUtils; import org.springframework.web.util.UriUtils;
/** /**
*
*/ */
public class FileManager public class FileManager
{ {
@ -76,7 +79,7 @@ public class FileManager
public static File buildFile(String filename) public static File buildFile(String filename)
{ {
filename = checkFilename( false, filename); filename = checkFilename(false, filename);
LogEntry.setTarget(filename); LogEntry.setTarget(filename);
return TempFileProvider.createTempFile("target_", "_" + filename); return TempFileProvider.createTempFile("target_", "_" + filename);
} }
@ -98,12 +101,13 @@ public class FileManager
*/ */
private static String checkFilename(boolean source, String filename) private static String checkFilename(boolean source, String filename)
{ {
filename = StringUtils.getFilename(filename); filename = getFilename(filename);
if (filename == null || filename.isEmpty()) if (filename == null || filename.isEmpty())
{ {
String sourceOrTarget = source ? "source" : "target"; String sourceOrTarget = source ? "source" : "target";
int statusCode = source ? BAD_REQUEST.value() : INTERNAL_SERVER_ERROR.value(); int statusCode = source ? BAD_REQUEST.value() : INTERNAL_SERVER_ERROR.value();
throw new TransformException(statusCode, "The " + sourceOrTarget + " filename was not supplied"); throw new TransformException(statusCode,
"The " + sourceOrTarget + " filename was not supplied");
} }
return filename; return filename;
} }
@ -112,7 +116,8 @@ public class FileManager
{ {
try try
{ {
Files.copy(multipartFile.getInputStream(), file.toPath(), StandardCopyOption.REPLACE_EXISTING); Files.copy(multipartFile.getInputStream(), file.toPath(),
StandardCopyOption.REPLACE_EXISTING);
} }
catch (IOException e) catch (IOException e)
{ {
@ -129,7 +134,8 @@ public class FileManager
} }
catch (IOException e) catch (IOException e)
{ {
throw new TransformException(INSUFFICIENT_STORAGE.value(), "Failed to store the source file", e); throw new TransformException(INSUFFICIENT_STORAGE.value(),
"Failed to store the source file", e);
} }
} }
@ -158,7 +164,7 @@ public class FileManager
public static String getFilenameFromContentDisposition(HttpHeaders headers) public static String getFilenameFromContentDisposition(HttpHeaders headers)
{ {
String filename = ""; String filename = "";
String contentDisposition = headers.getFirst(HttpHeaders.CONTENT_DISPOSITION); String contentDisposition = headers.getFirst(CONTENT_DISPOSITION);
if (contentDisposition != null) if (contentDisposition != null)
{ {
String[] strings = contentDisposition.split("; *"); String[] strings = contentDisposition.split("; *");
@ -171,7 +177,6 @@ public class FileManager
return filename; return filename;
} }
/** /**
* Returns the file name for the target file * Returns the file name for the target file
* *
@ -179,20 +184,24 @@ public class FileManager
* @param targetExtension File extension * @param targetExtension File extension
* @return Target file name * @return Target file name
*/ */
public static String createTargetFileName(String fileName, String targetExtension) public static String createTargetFileName(final String fileName, final String targetExtension)
{ {
String targetFilename = null; final String sourceFilename = getFilename(fileName);
String sourceFilename = fileName;
sourceFilename = StringUtils.getFilename(sourceFilename); if (sourceFilename == null || sourceFilename.isEmpty())
if (sourceFilename != null && !sourceFilename.isEmpty())
{ {
String ext = StringUtils.getFilenameExtension(sourceFilename); return null;
targetFilename = (ext != null && !ext.isEmpty()
? sourceFilename.substring(0, sourceFilename.length()-ext.length()-1)
: sourceFilename)+
'.'+targetExtension;
} }
return targetFilename;
final String ext = getFilenameExtension(sourceFilename);
if (ext == null || ext.isEmpty())
{
return sourceFilename + '.' + targetExtension;
}
return sourceFilename.substring(0, sourceFilename.length() - ext.length() - 1) +
'.' + targetExtension;
} }
/** /**
@ -207,7 +216,7 @@ public class FileManager
{ {
String filename = multipartFile.getOriginalFilename(); String filename = multipartFile.getOriginalFilename();
long size = multipartFile.getSize(); long size = multipartFile.getSize();
filename = checkFilename( true, filename); filename = checkFilename(true, filename);
File file = TempFileProvider.createTempFile("source_", "_" + filename); File file = TempFileProvider.createTempFile("source_", "_" + filename);
request.setAttribute(SOURCE_FILE, file); request.setAttribute(SOURCE_FILE, file);
save(multipartFile, file); save(multipartFile, file);
@ -228,9 +237,8 @@ public class FileManager
targetFile) targetFile)
{ {
Resource targetResource = load(targetFile); Resource targetResource = load(targetFile);
targetFilename = UriUtils.encodePath(StringUtils.getFilename(targetFilename), "UTF-8"); targetFilename = UriUtils.encodePath(getFilename(targetFilename), "UTF-8");
return ResponseEntity.ok().header(HttpHeaders return ResponseEntity.ok().header(CONTENT_DISPOSITION,
.CONTENT_DISPOSITION,
"attachment; filename*= UTF-8''" + targetFilename).body(targetResource); "attachment; filename*= UTF-8''" + targetFilename).body(targetResource);
} }
} }

View File

@ -135,7 +135,7 @@ public final class LogEntry
int i = filename.lastIndexOf('.'); int i = filename.lastIndexOf('.');
if (i != -1) if (i != -1)
{ {
filename = filename.substring(i+1); filename = filename.substring(i + 1);
} }
return filename; return filename;
} }
@ -201,7 +201,8 @@ public final class LogEntry
if (logEntry.statusCode == OK.value()) if (logEntry.statusCode == OK.value())
{ {
logEntry.durationStreamOut = System.currentTimeMillis() - logEntry.start - logEntry.durationStreamOut = System.currentTimeMillis() - logEntry.start -
logEntry.durationStreamIn - max(logEntry.durationTransform, 0) - max(logEntry.durationDelay, 0); logEntry.durationStreamIn - max(logEntry.durationTransform,
0) - max(logEntry.durationDelay, 0);
} }
currentLogEntry.remove(); currentLogEntry.remove();
@ -228,16 +229,18 @@ public final class LogEntry
public String getDuration() public String getDuration()
{ {
long duration = durationStreamIn + max(durationTransform, 0) + max(durationDelay, 0) + max(durationStreamOut, 0); long duration = durationStreamIn + max(durationTransform, 0) + max(durationDelay, 0) + max(
durationStreamOut, 0);
return duration <= 5 return duration <= 5
? "" ? ""
: time(duration)+ : time(duration) +
" ("+ " (" +
(time(durationStreamIn)+' '+ (time(durationStreamIn) + ' ' +
time(durationTransform)+' '+ time(durationTransform) + ' ' +
(durationDelay > 0 (durationDelay > 0
? time(durationDelay)+' '+(durationStreamOut < 0 ? "-" : time(durationStreamOut)) ? time(durationDelay) + ' ' + (durationStreamOut < 0 ? "-" : time(
: time(durationStreamOut))).trim()+ durationStreamOut))
: time(durationStreamOut))).trim() +
")"; ")";
} }
@ -274,16 +277,16 @@ public final class LogEntry
private String time(long ms) private String time(long ms)
{ {
return ms == -1 ? "" : size(ms, "1ms", return ms == -1 ? "" : size(ms, "1ms",
new String[] { "ms", "s", "min", "hr" }, new String[]{"ms", "s", "min", "hr"},
new long[] { 1000, 60*1000, 60*60*1000, Long.MAX_VALUE}); new long[]{1000, 60 * 1000, 60 * 60 * 1000, Long.MAX_VALUE});
} }
private String size(long size) private String size(long size)
{ {
// TODO fix numeric overflow in TB expression // TODO fix numeric overflow in TB expression
return size == -1 ? "" : size(size, "1 byte", return size == -1 ? "" : size(size, "1 byte",
new String[] { "bytes", " KB", " MB", " GB", " TB" }, new String[]{"bytes", " KB", " MB", " GB", " TB"},
new long[] { 1024, 1024*1024, 1024*1024*1024, 1024*1024*1024*1024, Long.MAX_VALUE }); new long[]{1024, 1024 * 1024, 1024 * 1024 * 1024, 1024 * 1024 * 1024 * 1024, Long.MAX_VALUE});
} }
private String size(long size, String singleValue, String[] units, long[] dividers) private String size(long size, String singleValue, String[] units, long[] dividers)
@ -293,16 +296,16 @@ public final class LogEntry
return singleValue; return singleValue;
} }
long divider = 1; long divider = 1;
for(int i = 0; i < units.length-1; i++) for (int i = 0; i < units.length - 1; i++)
{ {
long nextDivider = dividers[i]; long nextDivider = dividers[i];
if(size < nextDivider) if (size < nextDivider)
{ {
return unitFormat(size, divider, units[i]); return unitFormat(size, divider, units[i]);
} }
divider = nextDivider; divider = nextDivider;
} }
return unitFormat(size, divider, units[units.length-1]); return unitFormat(size, divider, units[units.length - 1]);
} }
private String unitFormat(long size, long divider, String unit) private String unitFormat(long size, long divider, String unit)
@ -311,7 +314,7 @@ public final class LogEntry
int decimalPoint = (int) size % 10; int decimalPoint = (int) size % 10;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(size/10); sb.append(size / 10);
if (decimalPoint != 0) if (decimalPoint != 0)
{ {
sb.append("."); sb.append(".");

View File

@ -31,5 +31,5 @@ public interface StandardMessages
String LICENCE = String LICENCE =
"License rights for this program may be obtained from Alfresco Software, Ltd. pursuant to a written agreement\n" + "License rights for this program may be obtained from Alfresco Software, Ltd. pursuant to a written agreement\n" +
"and any use of this program without such an agreement is prohibited.\n" + "and any use of this program without such an agreement is prohibited.\n" +
"\n" ; "\n";
} }

View File

@ -98,7 +98,8 @@ public class MessagingConfig implements JmsListenerConfigurer
@Bean @Bean
@ConditionalOnProperty(name = "activemq.url") @ConditionalOnProperty(name = "activemq.url")
public Queue engineRequestQueue(@Value("${queue.engineRequestQueue}") String engineRequestQueueValue) public Queue engineRequestQueue(
@Value("${queue.engineRequestQueue}") String engineRequestQueueValue)
{ {
return new ActiveMQQueue(engineRequestQueueValue); return new ActiveMQQueue(engineRequestQueueValue);
} }

View File

@ -56,7 +56,8 @@ public class TransformReplySender
send(destination, reply, reply.getRequestId()); send(destination, reply, reply.getRequestId());
} }
public void send(final Destination destination, final TransformReply reply, final String correlationId) public void send(final Destination destination, final TransformReply reply,
final String correlationId)
{ {
try try
{ {

View File

@ -37,25 +37,19 @@ public class FileRefEntity
{ {
private String fileRef; private String fileRef;
public FileRefEntity() public FileRefEntity() {}
{
}
public FileRefEntity(String fileRef) public FileRefEntity(String fileRef)
{ {
this.fileRef = fileRef; this.fileRef = fileRef;
} }
public void setFileRef(String fileRef){ public void setFileRef(String fileRef)
{
this.fileRef = fileRef; this.fileRef = fileRef;
} }
public String getFileRef()
{
return fileRef;
}
@Override public String getFileRef()
public String toString()
{ {
return fileRef; return fileRef;
} }
@ -63,16 +57,10 @@ public class FileRefEntity
@Override @Override
public boolean equals(Object o) public boolean equals(Object o)
{ {
if (this == o) if (this == o) return true;
{ if (o == null || getClass() != o.getClass()) return false;
return true; FileRefEntity that = (FileRefEntity) o;
} return Objects.equals(fileRef, that.fileRef);
if (o == null || getClass() != o.getClass())
{
return false;
}
FileRefEntity fileRef = (FileRefEntity) o;
return Objects.equals(this.fileRef, fileRef.fileRef);
} }
@Override @Override
@ -80,4 +68,10 @@ public class FileRefEntity
{ {
return Objects.hash(fileRef); return Objects.hash(fileRef);
} }
@Override
public String toString()
{
return fileRef;
}
} }

View File

@ -35,9 +35,7 @@ public class FileRefResponse
{ {
private FileRefEntity entry; private FileRefEntity entry;
public FileRefResponse() public FileRefResponse() {}
{
}
public FileRefResponse(FileRefEntity entry) public FileRefResponse(FileRefEntity entry)
{ {

View File

@ -43,8 +43,8 @@ import java.util.concurrent.atomic.AtomicLong;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.alfresco.transformer.AbstractTransformerController;
import org.alfresco.transform.exceptions.TransformException; import org.alfresco.transform.exceptions.TransformException;
import org.alfresco.transformer.AbstractTransformerController;
import org.alfresco.transformer.logging.LogEntry; import org.alfresco.transformer.logging.LogEntry;
import org.alfresco.util.TempFileProvider; import org.alfresco.util.TempFileProvider;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -111,6 +111,7 @@ public abstract class ProbeTestTransform
/** /**
* See Probes.md for more info. * See Probes.md for more info.
*
* @param expectedLength was the length of the target file during testing * @param expectedLength was the length of the target file during testing
* @param plusOrMinus simply allows for some variation in the transformed size caused by new versions of dates * @param plusOrMinus simply allows for some variation in the transformed size caused by new versions of dates
* @param livenessPercent indicates that for this type of transform a variation up to 2 and a half times is not * @param livenessPercent indicates that for this type of transform a variation up to 2 and a half times is not
@ -126,13 +127,14 @@ public abstract class ProbeTestTransform
{ {
this.sourceFilename = sourceFilename; this.sourceFilename = sourceFilename;
this.targetFilename = targetFilename; this.targetFilename = targetFilename;
minExpectedLength = Math.max(0, expectedLength-plusOrMinus); minExpectedLength = Math.max(0, expectedLength - plusOrMinus);
maxExpectedLength = expectedLength+plusOrMinus; maxExpectedLength = expectedLength + plusOrMinus;
this.livenessPercent = (int) getPositiveLongEnv("livenessPercent", livenessPercent); this.livenessPercent = (int) getPositiveLongEnv("livenessPercent", livenessPercent);
maxTransformCount = getPositiveLongEnv("maxTransforms", maxTransforms); maxTransformCount = getPositiveLongEnv("maxTransforms", maxTransforms);
maxTransformTime = getPositiveLongEnv("maxTransformSeconds", maxTransformSeconds)*1000; maxTransformTime = getPositiveLongEnv("maxTransformSeconds", maxTransformSeconds) * 1000;
livenessTransformPeriod = getPositiveLongEnv("livenessTransformPeriodSeconds", livenessTransformPeriodSeconds)*1000; livenessTransformPeriod = getPositiveLongEnv("livenessTransformPeriodSeconds",
livenessTransformPeriodSeconds) * 1000;
livenessTransformEnabled = getBooleanEnvVar("livenessTransformEnabled", false); livenessTransformEnabled = getBooleanEnvVar("livenessTransformEnabled", false);
} }
@ -238,39 +240,39 @@ public abstract class ProbeTestTransform
checkMaxTransformTimeAndCount(isLiveProbe); checkMaxTransformTimeAndCount(isLiveProbe);
return getProbeMessage(isLiveProbe)+message; return getProbeMessage(isLiveProbe) + message;
} }
private void checkMaxTransformTimeAndCount(boolean isLiveProbe) private void checkMaxTransformTimeAndCount(boolean isLiveProbe)
{ {
if (die.get()) if (die.get())
{ {
throw new TransformException(TOO_MANY_REQUESTS.value(), getMessagePrefix(isLiveProbe) + throw new TransformException(TOO_MANY_REQUESTS.value(),
"Transformer requested to die. A transform took longer than "+ getMessagePrefix(isLiveProbe) + "Transformer requested to die. A transform took " +
(maxTransformTime *1000)+" seconds"); "longer than " + (maxTransformTime * 1000) + " seconds");
} }
if (maxTransformCount > 0 && transformCount.get() > maxTransformCount) if (maxTransformCount > 0 && transformCount.get() > maxTransformCount)
{ {
throw new TransformException(TOO_MANY_REQUESTS.value(), getMessagePrefix(isLiveProbe) + throw new TransformException(TOO_MANY_REQUESTS.value(),
"Transformer requested to die. It has performed more than "+ getMessagePrefix(isLiveProbe) + "Transformer requested to die. It has performed " +
maxTransformCount+" transformations"); "more than " + maxTransformCount + " transformations");
} }
} }
private File getSourceFile(HttpServletRequest request, boolean isLiveProbe) private File getSourceFile(HttpServletRequest request, boolean isLiveProbe)
{ {
incrementTransformerCount(); incrementTransformerCount();
File sourceFile = TempFileProvider.createTempFile("source_", "_"+ sourceFilename); File sourceFile = TempFileProvider.createTempFile("source_", "_" + sourceFilename);
request.setAttribute(SOURCE_FILE, sourceFile); request.setAttribute(SOURCE_FILE, sourceFile);
try (InputStream inputStream = this.getClass().getResourceAsStream('/'+sourceFilename)) try (InputStream inputStream = this.getClass().getResourceAsStream('/' + sourceFilename))
{ {
Files.copy(inputStream, sourceFile.toPath(), StandardCopyOption.REPLACE_EXISTING); Files.copy(inputStream, sourceFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
} }
catch (IOException e) catch (IOException e)
{ {
throw new TransformException(INSUFFICIENT_STORAGE.value(), getMessagePrefix(isLiveProbe)+ throw new TransformException(INSUFFICIENT_STORAGE.value(),
"Failed to store the source file", e); getMessagePrefix(isLiveProbe) + "Failed to store the source file", e);
} }
long length = sourceFile.length(); long length = sourceFile.length();
LogEntry.setSource(sourceFilename, length); LogEntry.setSource(sourceFilename, length);
@ -279,7 +281,7 @@ public abstract class ProbeTestTransform
private File getTargetFile(HttpServletRequest request) private File getTargetFile(HttpServletRequest request)
{ {
File targetFile = TempFileProvider.createTempFile("target_", "_"+targetFilename); File targetFile = TempFileProvider.createTempFile("target_", "_" + targetFilename);
request.setAttribute(TARGET_FILE, targetFile); request.setAttribute(TARGET_FILE, targetFile);
LogEntry.setTarget(targetFilename); LogEntry.setTarget(targetFilename);
return targetFile; return targetFile;
@ -302,13 +304,15 @@ public abstract class ProbeTestTransform
String message = getMessagePrefix(isLiveProbe) + "Success - Transform " + time + "ms"; String message = getMessagePrefix(isLiveProbe) + "Success - Transform " + time + "ms";
if (++transCount > 1) if (++transCount > 1)
{ {
normalTime = (normalTime * (transCount-2) + time) / (transCount-1); normalTime = (normalTime * (transCount - 2) + time) / (transCount - 1);
maxTime = (normalTime * (livenessPercent + 100)) / 100; maxTime = (normalTime * (livenessPercent + 100)) / 100;
if ((!isLiveProbe && !readySent.getAndSet(true)) || transCount > AVERAGE_OVER_TRANSFORMS) if ((!isLiveProbe && !readySent.getAndSet(
true)) || transCount > AVERAGE_OVER_TRANSFORMS)
{ {
nextTransformTime = System.currentTimeMillis() + livenessTransformPeriod; nextTransformTime = System.currentTimeMillis() + livenessTransformPeriod;
logger.trace("{} - {}ms+{}%={}ms", message, normalTime, livenessPercent, maxTime); logger.trace("{} - {}ms+{}%={}ms", message, normalTime, livenessPercent,
maxTime);
} }
} }
else if (!isLiveProbe && !readySent.getAndSet(true)) else if (!isLiveProbe && !readySent.getAndSet(true))
@ -362,7 +366,6 @@ public abstract class ProbeTestTransform
public long getNormalTime() public long getNormalTime()
{ {
return normalTime; return normalTime;
} }
} }

View File

@ -27,6 +27,7 @@
package org.alfresco.transformer.util; package org.alfresco.transformer.util;
/** /**
*
*/ */
public class Util public class Util
{ {
@ -49,6 +50,6 @@ public class Util
*/ */
public static Boolean stringToBoolean(String param) public static Boolean stringToBoolean(String param)
{ {
return param == null? null : Boolean.parseBoolean(param); return param == null ? null : Boolean.parseBoolean(param);
} }
} }

View File

@ -26,16 +26,20 @@
*/ */
package org.alfresco.transformer; package org.alfresco.transformer;
import static org.junit.Assert.assertEquals;
import static org.springframework.http.HttpMethod.POST;
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA;
import static org.springframework.test.util.AssertionErrors.assertTrue;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.*; import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import static org.junit.Assert.assertEquals;
import static org.springframework.test.util.AssertionErrors.assertTrue;
/** /**
* Super class for testing controllers with a server. Includes tests for the AbstractTransformerController itself. * Super class for testing controllers with a server. Includes tests for the AbstractTransformerController itself.
* Note: Currently uses json rather than HTML as json is returned by this spring boot test harness. * Note: Currently uses json rather than HTML as json is returned by this spring boot test harness.
@ -64,7 +68,8 @@ public abstract class AbstractHttpRequestTest
@Test @Test
public void logPageExists() public void logPageExists()
{ {
String result = restTemplate.getForObject("http://localhost:" + port + "/log", String.class); String result = restTemplate.getForObject("http://localhost:" + port + "/log",
String.class);
String title = getTransformerName() + ' ' + "Log"; String title = getTransformerName() + ' ' + "Log";
assertTrue("\"" + title + "\" should be part of the page title", result.contains(title)); assertTrue("\"" + title + "\" should be part of the page title", result.contains(title));
@ -73,10 +78,12 @@ public abstract class AbstractHttpRequestTest
@Test @Test
public void errorPageExists() public void errorPageExists()
{ {
String result = restTemplate.getForObject("http://localhost:" + port + "/error", String.class); String result = restTemplate.getForObject("http://localhost:" + port + "/error",
String.class);
String title = getTransformerName() + ' ' + "Error Page"; String title = getTransformerName() + ' ' + "Error Page";
assertTrue("\"" + title + "\" should be part of the page title", result.contains("Error Page")); assertTrue("\"" + title + "\" should be part of the page title",
result.contains("Error Page"));
} }
@Test @Test
@ -104,12 +111,15 @@ public abstract class AbstractHttpRequestTest
LinkedMultiValueMap<String, Object> parameters = new LinkedMultiValueMap<>(); LinkedMultiValueMap<String, Object> parameters = new LinkedMultiValueMap<>();
if (addFile) if (addFile)
{ {
parameters.add("file", new org.springframework.core.io.ClassPathResource("quick."+getSourceExtension())); parameters.add("file",
new org.springframework.core.io.ClassPathResource("quick." + getSourceExtension()));
} }
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA); headers.setContentType(MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> entity = new HttpEntity<>(parameters, headers); HttpEntity<LinkedMultiValueMap<String, Object>> entity = new HttpEntity<>(parameters,
ResponseEntity<String> response = restTemplate.exchange("/transform", HttpMethod.POST, entity, String.class, ""); headers);
ResponseEntity<String> response = restTemplate.exchange("/transform", POST, entity,
String.class, "");
assertEquals(errorMessage, getErrorMessage(response.getBody())); assertEquals(errorMessage, getErrorMessage(response.getBody()));
} }
@ -125,7 +135,7 @@ public abstract class AbstractHttpRequestTest
int j = content.indexOf("\",\"path\":", i); int j = content.indexOf("\",\"path\":", i);
if (j != -1) if (j != -1)
{ {
message = content.substring(i+11, j); message = content.substring(i + 11, j);
} }
} }
return message; return message;

View File

@ -54,11 +54,12 @@ public abstract class AbstractQueueTransformServiceIT
@Autowired @Autowired
private JmsTemplate jmsTemplate; private JmsTemplate jmsTemplate;
private final ActiveMQQueue testingQueue = new ActiveMQQueue("org.alfresco.transform.engine.IT"); private final ActiveMQQueue testingQueue = new ActiveMQQueue(
"org.alfresco.transform.engine.IT");
@Test @Test
public void queueTransformServiceIT() { public void queueTransformServiceIT()
{
TransformRequest request = buildRequest(); TransformRequest request = buildRequest();
jmsTemplate.convertAndSend(engineRequestQueue, request, m -> { jmsTemplate.convertAndSend(engineRequestQueue, request, m -> {

View File

@ -30,9 +30,13 @@ import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.springframework.http.HttpHeaders.ACCEPT;
import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.OK; import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 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.header;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ -62,8 +66,6 @@ import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile; import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
@ -107,7 +109,8 @@ public abstract class AbstractTransformerControllerTest
protected abstract AbstractTransformerController getController(); protected abstract AbstractTransformerController getController();
protected abstract void updateTransformRequestWithSpecificOptions(TransformRequest transformRequest); protected abstract void updateTransformRequestWithSpecificOptions(
TransformRequest transformRequest);
/** /**
* This method ends up being the core of the mock. * This method ends up being the core of the mock.
@ -151,14 +154,17 @@ public abstract class AbstractTransformerControllerTest
URL testFileUrl = classLoader.getResource(testFilename); URL testFileUrl = classLoader.getResource(testFilename);
if (required && testFileUrl == null) if (required && testFileUrl == null)
{ {
throw new IOException("The test file " + testFilename + " does not exist in the resources directory"); throw new IOException("The test file " + testFilename +
" does not exist in the resources directory");
} }
return testFileUrl == null ? null : new File(testFileUrl.getFile()); return testFileUrl == null ? null : new File(testFileUrl.getFile());
} }
protected MockHttpServletRequestBuilder mockMvcRequest(String url, MockMultipartFile sourceFile, String... params) protected MockHttpServletRequestBuilder mockMvcRequest(String url, MockMultipartFile sourceFile,
String... params)
{ {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.multipart("/transform").file(sourceFile); MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.multipart("/transform").file(
sourceFile);
if (params.length % 2 != 0) if (params.length % 2 != 0)
{ {
@ -175,20 +181,24 @@ public abstract class AbstractTransformerControllerTest
@Test @Test
public void simpleTransformTest() throws Exception public void simpleTransformTest() throws Exception
{ {
mockMvc.perform(mockMvcRequest("/transform", sourceFile, "targetExtension", targetExtension)) mockMvc.perform(
mockMvcRequest("/transform", sourceFile, "targetExtension", targetExtension))
.andExpect(status().is(OK.value())) .andExpect(status().is(OK.value()))
.andExpect(content().bytes(expectedTargetFileBytes)) .andExpect(content().bytes(expectedTargetFileBytes))
.andExpect(header().string("Content-Disposition", "attachment; filename*= UTF-8''quick." + targetExtension)); .andExpect(header().string("Content-Disposition",
"attachment; filename*= UTF-8''quick." + targetExtension));
} }
@Test @Test
public void testDelayTest() throws Exception public void testDelayTest() throws Exception
{ {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
mockMvc.perform(mockMvcRequest("/transform", sourceFile, "targetExtension", targetExtension, "testDelay", "400")) mockMvc.perform(mockMvcRequest("/transform", sourceFile, "targetExtension", targetExtension,
"testDelay", "400"))
.andExpect(status().is(OK.value())) .andExpect(status().is(OK.value()))
.andExpect(content().bytes(expectedTargetFileBytes)) .andExpect(content().bytes(expectedTargetFileBytes))
.andExpect(header().string("Content-Disposition", "attachment; filename*= UTF-8''quick." + targetExtension)); .andExpect(header().string("Content-Disposition",
"attachment; filename*= UTF-8''quick." + targetExtension));
long ms = System.currentTimeMillis() - start; long ms = System.currentTimeMillis() - start;
System.out.println("Transform incluing test delay was " + ms); System.out.println("Transform incluing test delay was " + ms);
assertTrue("Delay sending the result back was too small " + ms, ms >= 400); assertTrue("Delay sending the result back was too small " + ms, ms >= 400);
@ -206,24 +216,30 @@ public abstract class AbstractTransformerControllerTest
// Looks dangerous but is okay as we only use the final filename // Looks dangerous but is okay as we only use the final filename
public void dotDotSourceFilenameTest() throws Exception public void dotDotSourceFilenameTest() throws Exception
{ {
sourceFile = new MockMultipartFile("file", "../quick." + sourceExtension, sourceMimetype, expectedSourceFileBytes); sourceFile = new MockMultipartFile("file", "../quick." + sourceExtension, sourceMimetype,
expectedSourceFileBytes);
mockMvc.perform(mockMvcRequest("/transform", sourceFile, "targetExtension", targetExtension)) mockMvc.perform(
mockMvcRequest("/transform", sourceFile, "targetExtension", targetExtension))
.andExpect(status().is(OK.value())) .andExpect(status().is(OK.value()))
.andExpect(content().bytes(expectedTargetFileBytes)) .andExpect(content().bytes(expectedTargetFileBytes))
.andExpect(header().string("Content-Disposition", "attachment; filename*= UTF-8''quick." + targetExtension)); .andExpect(header().string("Content-Disposition",
"attachment; filename*= UTF-8''quick." + targetExtension));
} }
@Test @Test
// Is okay, as the target filename is built up from the whole source filename and the targetExtenstion // Is okay, as the target filename is built up from the whole source filename and the targetExtenstion
public void noExtensionSourceFilenameTest() throws Exception public void noExtensionSourceFilenameTest() throws Exception
{ {
sourceFile = new MockMultipartFile("file", "../quick", sourceMimetype, expectedSourceFileBytes); sourceFile = new MockMultipartFile("file", "../quick", sourceMimetype,
expectedSourceFileBytes);
mockMvc.perform(mockMvcRequest("/transform", sourceFile, "targetExtension", targetExtension)) mockMvc.perform(
mockMvcRequest("/transform", sourceFile, "targetExtension", targetExtension))
.andExpect(status().is(OK.value())) .andExpect(status().is(OK.value()))
.andExpect(content().bytes(expectedTargetFileBytes)) .andExpect(content().bytes(expectedTargetFileBytes))
.andExpect(header().string("Content-Disposition", "attachment; filename*= UTF-8''quick." + targetExtension)); .andExpect(header().string("Content-Disposition",
"attachment; filename*= UTF-8''quick." + targetExtension));
} }
@Test @Test
@ -232,7 +248,8 @@ public abstract class AbstractTransformerControllerTest
{ {
sourceFile = new MockMultipartFile("file", "abc/", sourceMimetype, expectedSourceFileBytes); sourceFile = new MockMultipartFile("file", "abc/", sourceMimetype, expectedSourceFileBytes);
mockMvc.perform(mockMvcRequest("/transform", sourceFile, "targetExtension", targetExtension)) mockMvc.perform(
mockMvcRequest("/transform", sourceFile, "targetExtension", targetExtension))
.andExpect(status().is(BAD_REQUEST.value())) .andExpect(status().is(BAD_REQUEST.value()))
.andExpect(status().reason(containsString("The source filename was not supplied"))); .andExpect(status().reason(containsString("The source filename was not supplied")));
} }
@ -242,7 +259,8 @@ public abstract class AbstractTransformerControllerTest
{ {
sourceFile = new MockMultipartFile("file", "", sourceMimetype, expectedSourceFileBytes); sourceFile = new MockMultipartFile("file", "", sourceMimetype, expectedSourceFileBytes);
mockMvc.perform(mockMvcRequest("/transform", sourceFile, "targetExtension", targetExtension)) mockMvc.perform(
mockMvcRequest("/transform", sourceFile, "targetExtension", targetExtension))
.andExpect(status().is(BAD_REQUEST.value())) .andExpect(status().is(BAD_REQUEST.value()))
.andExpect(status().reason(containsString("The source filename was not supplied"))); .andExpect(status().reason(containsString("The source filename was not supplied")));
} }
@ -252,7 +270,8 @@ public abstract class AbstractTransformerControllerTest
{ {
mockMvc.perform(mockMvcRequest("/transform", sourceFile)) mockMvc.perform(mockMvcRequest("/transform", sourceFile))
.andExpect(status().is(BAD_REQUEST.value())) .andExpect(status().is(BAD_REQUEST.value()))
.andExpect(status().reason(containsString("Request parameter 'targetExtension' is missing"))); .andExpect(status().reason(
containsString("Request parameter 'targetExtension' is missing")));
} }
@Test @Test
@ -295,13 +314,14 @@ public abstract class AbstractTransformerControllerTest
String transformationReplyAsString = mockMvc String transformationReplyAsString = mockMvc
.perform(MockMvcRequestBuilders .perform(MockMvcRequestBuilders
.post("/transform") .post("/transform")
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .header(ACCEPT, APPLICATION_JSON_VALUE)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .header(CONTENT_TYPE, APPLICATION_JSON_VALUE)
.content(tr)) .content(tr))
.andExpect(status().is(BAD_REQUEST.value())) .andExpect(status().is(BAD_REQUEST.value()))
.andReturn().getResponse().getContentAsString(); .andReturn().getResponse().getContentAsString();
TransformReply transformReply = objectMapper.readValue(transformationReplyAsString, TransformReply.class); TransformReply transformReply = objectMapper.readValue(transformationReplyAsString,
TransformReply.class);
// Assert the reply // Assert the reply
assertEquals(BAD_REQUEST.value(), transformReply.getStatus()); assertEquals(BAD_REQUEST.value(), transformReply.getStatus());
@ -317,9 +337,10 @@ public abstract class AbstractTransformerControllerTest
ReflectionTestUtils ReflectionTestUtils
.setField(AbstractTransformerController.class, "ENGINE_CONFIG", "engine_config.json"); .setField(AbstractTransformerController.class, "ENGINE_CONFIG", "engine_config.json");
String response = mockMvc.perform(MockMvcRequestBuilders.get("/transform/config")) String response = mockMvc
.andExpect(status().is(OK.value())).andExpect( .perform(MockMvcRequestBuilders.get("/transform/config"))
header().string(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(status().is(OK.value()))
.andExpect(header().string(CONTENT_TYPE, APPLICATION_JSON_UTF8_VALUE))
.andReturn().getResponse().getContentAsString(); .andReturn().getResponse().getContentAsString();
TransformConfig transformConfig = objectMapper.readValue(response, TransformConfig.class); TransformConfig transformConfig = objectMapper.readValue(response, TransformConfig.class);
@ -335,9 +356,10 @@ public abstract class AbstractTransformerControllerTest
ReflectionTestUtils.setField(AbstractTransformerController.class, "ENGINE_CONFIG", ReflectionTestUtils.setField(AbstractTransformerController.class, "ENGINE_CONFIG",
"engine_config_with_duplicates.json"); "engine_config_with_duplicates.json");
String response = mockMvc.perform(MockMvcRequestBuilders.get("/transform/config")) String response = mockMvc
.andExpect(status().is(OK.value())).andExpect( .perform(MockMvcRequestBuilders.get("/transform/config"))
header().string(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(status().is(OK.value()))
.andExpect(header().string(CONTENT_TYPE, APPLICATION_JSON_UTF8_VALUE))
.andReturn().getResponse().getContentAsString(); .andReturn().getResponse().getContentAsString();
TransformConfig transformConfig = objectMapper.readValue(response, TransformConfig.class); TransformConfig transformConfig = objectMapper.readValue(response, TransformConfig.class);
@ -349,7 +371,6 @@ public abstract class AbstractTransformerControllerTest
transformConfig.getTransformers().get(0).getSupportedSourceAndTargetList().size()); transformConfig.getTransformers().get(0).getSupportedSourceAndTargetList().size());
assertEquals(1, assertEquals(1,
transformConfig.getTransformers().get(0).getTransformOptions().size()); transformConfig.getTransformers().get(0).getTransformOptions().size());
} }
@Test @Test
@ -362,9 +383,10 @@ public abstract class AbstractTransformerControllerTest
ReflectionTestUtils.setField(AbstractTransformerController.class, "ENGINE_CONFIG", ReflectionTestUtils.setField(AbstractTransformerController.class, "ENGINE_CONFIG",
"engine_config_incomplete.json"); "engine_config_incomplete.json");
String response = mockMvc.perform(MockMvcRequestBuilders.get("/transform/config")) String response = mockMvc
.andExpect(status().is(OK.value())).andExpect( .perform(MockMvcRequestBuilders.get("/transform/config"))
header().string(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(status().is(OK.value()))
.andExpect(header().string(CONTENT_TYPE, APPLICATION_JSON_UTF8_VALUE))
.andReturn().getResponse().getContentAsString(); .andReturn().getResponse().getContentAsString();
TransformConfig transformConfig = objectMapper.readValue(response, TransformConfig.class); TransformConfig transformConfig = objectMapper.readValue(response, TransformConfig.class);
@ -384,9 +406,10 @@ public abstract class AbstractTransformerControllerTest
ReflectionTestUtils.setField(AbstractTransformerController.class, "ENGINE_CONFIG", ReflectionTestUtils.setField(AbstractTransformerController.class, "ENGINE_CONFIG",
"engine_config_no_transform_options.json"); "engine_config_no_transform_options.json");
String response = mockMvc.perform(MockMvcRequestBuilders.get("/transform/config")) String response = mockMvc
.andExpect(status().is(OK.value())).andExpect( .perform(MockMvcRequestBuilders.get("/transform/config"))
header().string(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)) .andExpect(status().is(OK.value()))
.andExpect(header().string(CONTENT_TYPE, APPLICATION_JSON_UTF8_VALUE))
.andReturn().getResponse().getContentAsString(); .andReturn().getResponse().getContentAsString();
TransformConfig transformConfig = objectMapper.readValue(response, TransformConfig.class); TransformConfig transformConfig = objectMapper.readValue(response, TransformConfig.class);
@ -405,7 +428,8 @@ public abstract class AbstractTransformerControllerTest
new TransformOptionValue(false, "page"), new TransformOptionValue(false, "page"),
new TransformOptionValue(false, "width"), new TransformOptionValue(false, "width"),
new TransformOptionGroup(false, transformOptionGroup)); new TransformOptionGroup(false, transformOptionGroup));
Map<String, Set<TransformOption>> transformOptionsMap = ImmutableMap.of("engineXOptions", transformOptions); Map<String, Set<TransformOption>> transformOptionsMap = ImmutableMap.of("engineXOptions",
transformOptions);
Transformer transformer = buildTransformer("application/pdf", "image/png", "engineXOptions", Transformer transformer = buildTransformer("application/pdf", "image/png", "engineXOptions",
"engineX"); "engineX");

View File

@ -27,11 +27,18 @@
package org.alfresco.transformer; package org.alfresco.transformer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import org.alfresco.transform.client.model.TransformReply; import org.alfresco.transform.client.model.TransformReply;
import org.alfresco.transform.client.model.TransformRequest; import org.alfresco.transform.client.model.TransformRequest;
@ -48,10 +55,6 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.jms.support.converter.MessageConversionException; import org.springframework.jms.support.converter.MessageConversionException;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
public class QueueTransformServiceTest public class QueueTransformServiceTest
{ {
@Mock @Mock
@ -98,10 +101,13 @@ public class QueueTransformServiceTest
ActiveMQQueue destination = new ActiveMQQueue(); ActiveMQQueue destination = new ActiveMQQueue();
msg.setJMSReplyTo(destination); msg.setJMSReplyTo(destination);
TransformReply reply = TransformReply.builder() TransformReply reply = TransformReply
.withStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()).withErrorDetails( .builder()
.withStatus(INTERNAL_SERVER_ERROR.value())
.withErrorDetails(
"JMS exception during T-Request deserialization of message with correlationID " "JMS exception during T-Request deserialization of message with correlationID "
+ msg.getCorrelationId() + ": null").build(); + msg.getCorrelationId() + ": null")
.build();
doReturn(null).when(transformMessageConverter).fromMessage(msg); doReturn(null).when(transformMessageConverter).fromMessage(msg);
@ -122,10 +128,13 @@ public class QueueTransformServiceTest
ActiveMQQueue destination = new ActiveMQQueue(); ActiveMQQueue destination = new ActiveMQQueue();
msg.setJMSReplyTo(destination); msg.setJMSReplyTo(destination);
TransformReply reply = TransformReply.builder().withStatus(HttpStatus.BAD_REQUEST.value()) TransformReply reply = TransformReply
.builder()
.withStatus(BAD_REQUEST.value())
.withErrorDetails( .withErrorDetails(
"Message conversion exception during T-Request deserialization of message with correlationID" "Message conversion exception during T-Request deserialization of message with correlationID"
+ msg.getCorrelationId() + ": null").build(); + msg.getCorrelationId() + ": null")
.build();
doThrow(MessageConversionException.class).when(transformMessageConverter).fromMessage(msg); doThrow(MessageConversionException.class).when(transformMessageConverter).fromMessage(msg);
@ -146,10 +155,13 @@ public class QueueTransformServiceTest
ActiveMQQueue destination = new ActiveMQQueue(); ActiveMQQueue destination = new ActiveMQQueue();
msg.setJMSReplyTo(destination); msg.setJMSReplyTo(destination);
TransformReply reply = TransformReply.builder() TransformReply reply = TransformReply
.withStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()).withErrorDetails( .builder()
"JMSException during T-Request deserialization of message with correlationID " + msg .withStatus(INTERNAL_SERVER_ERROR.value())
.getCorrelationId() + ": null").build(); .withErrorDetails(
"JMSException during T-Request deserialization of message with correlationID " +
msg.getCorrelationId() + ": null")
.build();
doThrow(JMSException.class).when(transformMessageConverter).fromMessage(msg); doThrow(JMSException.class).when(transformMessageConverter).fromMessage(msg);
@ -169,7 +181,9 @@ public class QueueTransformServiceTest
msg.setJMSReplyTo(destination); msg.setJMSReplyTo(destination);
TransformRequest request = new TransformRequest(); TransformRequest request = new TransformRequest();
TransformReply reply = TransformReply.builder().withStatus(HttpStatus.CREATED.value()) TransformReply reply = TransformReply
.builder()
.withStatus(CREATED.value())
.build(); .build();
doReturn(request).when(transformMessageConverter).fromMessage(msg); doReturn(request).when(transformMessageConverter).fromMessage(msg);
@ -208,7 +222,9 @@ public class QueueTransformServiceTest
doReturn(destination).when(msg).getJMSReplyTo(); doReturn(destination).when(msg).getJMSReplyTo();
TransformRequest request = new TransformRequest(); TransformRequest request = new TransformRequest();
TransformReply reply = TransformReply.builder().withStatus(HttpStatus.CREATED.value()) TransformReply reply = TransformReply
.builder()
.withStatus(CREATED.value())
.build(); .build();
doReturn(request).when(transformMessageConverter).fromMessage(msg); doReturn(request).when(transformMessageConverter).fromMessage(msg);

15
pom.xml
View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version> <version>2.1.7.RELEASE</version>
<relativePath /> <relativePath />
</parent> </parent>
@ -14,9 +14,11 @@
<version>2.1.0-EA5-SNAPSHOT</version> <version>2.1.0-EA5-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<properties> <properties>
<java.version>1.8</java.version> <java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<image.tag>latest</image.tag> <image.tag>latest</image.tag>
<dependency.pdfbox.version>2.0.16</dependency.pdfbox.version> <dependency.pdfbox.version>2.0.16</dependency.pdfbox.version>
<dependency.alfresco-core.version>7.17</dependency.alfresco-core.version> <dependency.alfresco-core.version>7.17</dependency.alfresco-core.version>
@ -26,6 +28,7 @@
<dependency.alfresco-transform-model.version>1.0.2.3</dependency.alfresco-transform-model.version> <dependency.alfresco-transform-model.version>1.0.2.3</dependency.alfresco-transform-model.version>
<dependency.activemq.version>5.15.9</dependency.activemq.version> <dependency.activemq.version>5.15.9</dependency.activemq.version>
<dependency.jackson.version>2.9.9</dependency.jackson.version> <dependency.jackson.version>2.9.9</dependency.jackson.version>
<dependency.jackson-databind.version>2.9.9.2</dependency.jackson-databind.version>
<dependency.cxf.version>3.2.9</dependency.cxf.version> <dependency.cxf.version>3.2.9</dependency.cxf.version>
</properties> </properties>
@ -46,7 +49,6 @@
</scm> </scm>
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
@ -68,7 +70,6 @@
<artifactId>dom4j</artifactId> <artifactId>dom4j</artifactId>
<version>2.1.1</version> <version>2.1.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.alfresco</groupId> <groupId>org.alfresco</groupId>
<artifactId>alfresco-data-model</artifactId> <artifactId>alfresco-data-model</artifactId>
@ -129,7 +130,7 @@
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
<version>${dependency.jackson.version}</version> <version>${dependency.jackson-databind.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
@ -307,7 +308,7 @@
<plugin> <plugin>
<groupId>io.fabric8</groupId> <groupId>io.fabric8</groupId>
<artifactId>fabric8-maven-plugin</artifactId> <artifactId>fabric8-maven-plugin</artifactId>
<version>4.1.0</version> <version>4.2.0</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>io.fabric8</groupId> <groupId>io.fabric8</groupId>