mirror of
https://github.com/Alfresco/alfresco-transform-core.git
synced 2025-09-17 14:21:18 +00:00
HXENG-64 refactor ATS (#657)
Refactor to clean up packages in the t-model and to introduce a simpler to implement t-engine base. The new t-engines (tika, imagemagick, libreoffice, pdfrenderer, misc, aio, aspose) and t-router may be used in combination with older components as the API between the content Repo and between components has not changed. As far as possible the same artifacts are created (the -boot projects no longer exist). They may be used with older ACS repo versions. The main changes to look for are: * The introduction of TransformEngine and CustomTransformer interfaces to be implemented. * The removal in t-engines and t-router of the Controller, Application, test template page, Controller tests and application config, as this is all now done by the t-engine base package. * The t-router now extends the t-engine base, which also reduced the amount of duplicate code. * The t-engine base provides the test page, which includes drop downs of known transform options. The t-router is able to use pipeline and failover transformers. This was not possible to do previously as the router had no test UI. * Resources including licenses are automatically included in the all-in-one t-engine, from the individual t-engines. They just need to be added as dependencies in the pom. * The ugly code in the all-in-one t-engine and misc t-engine to pick transformers has gone, as they are now just selected by the transformRegistry. * The way t-engines respond to http or message queue transform requests has been combined (eliminates the similar but different code that existed before). * The t-engine base now uses InputStream and OutputStream rather than Files by default. As a result it will be simpler to avoid writing content to a temporary location. * A number of the Tika and Misc CustomTransforms no longer use Files. * The original t-engine base still exists so customers can continue to create custom t-engines the way they have done previously. the project has just been moved into a folder called deprecated. * The folder structure has changed. The long "alfresco-transform-..." names have given way to shorter easier to read and type names. * The t-engine project structure now has a single project rather than two. * The previous config values still exist, but there are now a new set for config values for in files with names that don't misleadingly imply they only contain pipeline of routing information. * The concept of 'routing' has much less emphasis in class names as the code just uses the transformRegistry. * TransformerConfig may now be read as json or yaml. The restrictions about what could be specified in yaml has gone. * T-engines and t-router may use transform config from files. Previously it was just the t-router. * The POC code to do with graphs of possible routes has been removed. * All master branch changes have been merged in. * The concept of a single transform request which results in multiple responses (e.g. images from a video) has been added to the core processing of requests in the t-engine base. * Many SonarCloud linter fixes.
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer;
|
||||
|
||||
import static org.alfresco.transform.common.RequestParamMap.DIRECT_ACCESS_URL;
|
||||
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM;
|
||||
import static org.junit.jupiter.api.Assertions.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.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class AbstractHttpRequestTest
|
||||
{
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
|
||||
@Autowired
|
||||
private TestRestTemplate restTemplate;
|
||||
|
||||
protected abstract String getTransformerName();
|
||||
|
||||
protected abstract String getSourceExtension();
|
||||
|
||||
@Test
|
||||
public void testPageExists()
|
||||
{
|
||||
String result = restTemplate.getForObject("http://localhost:" + port + "/", String.class);
|
||||
|
||||
String title = getTransformerName() + ' ' + "Test Transformation";
|
||||
assertTrue("\"" + title + "\" should be part of the page title", result.contains(title));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logPageExists()
|
||||
{
|
||||
String result = restTemplate.getForObject("http://localhost:" + port + "/log",
|
||||
String.class);
|
||||
|
||||
String title = getTransformerName() + ' ' + "Log";
|
||||
assertTrue("\"" + title + "\" should be part of the page title", result.contains(title));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void errorPageExists()
|
||||
{
|
||||
String result = restTemplate.getForObject("http://localhost:" + port + "/error",
|
||||
String.class);
|
||||
|
||||
String title = getTransformerName() + ' ' + "Error Page";
|
||||
assertTrue("\"" + title + "\" should be part of the page title",
|
||||
result.contains("Error Page"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noFileError()
|
||||
{
|
||||
LinkedMultiValueMap<String, Object> parameters = new LinkedMultiValueMap<>();
|
||||
parameters.add("targetExtension", ".tmp");
|
||||
|
||||
assertTransformError(false,
|
||||
getTransformerName() + " - Required request part 'file' is not present",
|
||||
parameters);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noTargetExtensionError()
|
||||
{
|
||||
assertMissingParameter("targetExtension");
|
||||
}
|
||||
|
||||
private void assertMissingParameter(String name)
|
||||
{
|
||||
assertTransformError(true,
|
||||
getTransformerName() + " - Request parameter '" + name + "' is missing", null);
|
||||
}
|
||||
|
||||
protected void assertTransformError(boolean addFile,
|
||||
String errorMessage,
|
||||
LinkedMultiValueMap<String, Object> additionalParams)
|
||||
{
|
||||
LinkedMultiValueMap<String, Object> parameters = new LinkedMultiValueMap<>();
|
||||
if (addFile)
|
||||
{
|
||||
parameters.add("file",
|
||||
new org.springframework.core.io.ClassPathResource("quick." + getSourceExtension()));
|
||||
}
|
||||
if (additionalParams != null)
|
||||
{
|
||||
parameters.addAll(additionalParams);
|
||||
}
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MULTIPART_FORM_DATA);
|
||||
HttpEntity<LinkedMultiValueMap<String, Object>> entity = new HttpEntity<>(parameters,
|
||||
headers);
|
||||
|
||||
sendTranformationRequest(entity, errorMessage);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void httpTransformRequestDirectAccessUrlNotFoundTest()
|
||||
{
|
||||
String directUrl = "https://expired/direct/access/url";
|
||||
|
||||
LinkedMultiValueMap<String, Object> parameters = new LinkedMultiValueMap<>();
|
||||
parameters.add("targetExtension", ".tmp");
|
||||
parameters.add(DIRECT_ACCESS_URL, directUrl);
|
||||
|
||||
assertTransformError(false,
|
||||
getTransformerName() + " - Direct Access Url not found.",
|
||||
parameters);
|
||||
|
||||
}
|
||||
|
||||
protected void sendTranformationRequest(
|
||||
final HttpEntity<LinkedMultiValueMap<String, Object>> entity, final String errorMessage)
|
||||
{
|
||||
final ResponseEntity<String> response = restTemplate.exchange(ENDPOINT_TRANSFORM, POST, entity,
|
||||
String.class, "");
|
||||
assertEquals(errorMessage, getErrorMessage(response.getBody()));
|
||||
}
|
||||
|
||||
// Strip out just the error message from the returned json content body
|
||||
// Had been expecting the Error page to be returned, but we end up with the json in this test harness.
|
||||
// Is correct if run manually, so not worrying too much about this.
|
||||
private String getErrorMessage(String content)
|
||||
{
|
||||
String message = "";
|
||||
int i = content.indexOf("\"message\":\"");
|
||||
if (i != -1)
|
||||
{
|
||||
int j = content.indexOf("\",\"path\":", i);
|
||||
if (j != -1)
|
||||
{
|
||||
message = content.substring(i + 11, j);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
}
|
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer;
|
||||
|
||||
import static java.text.MessageFormat.format;
|
||||
import static org.alfresco.transformer.EngineClient.sendTRequest;
|
||||
import static org.alfresco.transform.common.Mimetype.MIMETYPE_METADATA_EXTRACT;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
/**
|
||||
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
|
||||
*
|
||||
* Super class of metadata integration tests. Sub classes should provide the following:
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>A method providing a
|
||||
* Stream of test files: {@code public static Stream<TestFileInfo> engineTransformations()}; </li>
|
||||
* <li> Provide expected json files (<sourceFilename>"_metadata.json") as resources on the classpath.</li>
|
||||
* <li> Override the method {@code testTransformation(TestFileInfo testFileInfo)} such that it calls
|
||||
* the super method as a {@code @ParameterizedTest} for example:</li> </ul>
|
||||
* <pre>
|
||||
* @ParameterizedTest
|
||||
*
|
||||
* @MethodSource("engineTransformations")
|
||||
*
|
||||
* @Override
|
||||
|
||||
* public void testTransformation(TestFileInfo testFileInfo)
|
||||
*
|
||||
* {
|
||||
* super.testTransformation(TestFileInfo testFileInfo)
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author adavis
|
||||
* @author dedwards
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class AbstractMetadataExtractsIT
|
||||
{
|
||||
private static final String ENGINE_URL = "http://localhost:8090";
|
||||
// These are normally variable, hence the lowercase.
|
||||
private static final String targetMimetype = MIMETYPE_METADATA_EXTRACT;
|
||||
private static final String targetExtension = "json";
|
||||
|
||||
private final ObjectMapper jsonObjectMapper = new ObjectMapper();
|
||||
|
||||
|
||||
public void testTransformation(TestFileInfo testFileInfo)
|
||||
{
|
||||
final String sourceMimetype = testFileInfo.getMimeType();
|
||||
final String sourceFile = testFileInfo.getPath();
|
||||
|
||||
final String descriptor = format("Transform ({0}, {1} -> {2}, {3})",
|
||||
sourceFile, sourceMimetype, targetMimetype, targetExtension);
|
||||
|
||||
try
|
||||
{
|
||||
final ResponseEntity<Resource> response = sendTRequest(ENGINE_URL, sourceFile,
|
||||
sourceMimetype, targetMimetype, targetExtension);
|
||||
assertEquals(OK, response.getStatusCode(), descriptor);
|
||||
|
||||
String metadataFilename = sourceFile + "_metadata.json";
|
||||
Map<String, Serializable> actualMetadata = readMetadata(response.getBody().getInputStream());
|
||||
File actualMetadataFile = new File(metadataFilename);
|
||||
jsonObjectMapper.writerWithDefaultPrettyPrinter().writeValue(actualMetadataFile, actualMetadata);
|
||||
|
||||
Map<String, Serializable> expectedMetadata = readExpectedMetadata(metadataFilename, actualMetadataFile);
|
||||
assertEquals(expectedMetadata, actualMetadata,
|
||||
sourceFile+": The metadata did not match the expected value. It has been saved in "+actualMetadataFile.getAbsolutePath());
|
||||
actualMetadataFile.delete();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
fail(descriptor + " exception: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Serializable> readExpectedMetadata(String filename, File actualMetadataFile) throws IOException
|
||||
{
|
||||
try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(filename))
|
||||
{
|
||||
if (inputStream == null)
|
||||
{
|
||||
fail("The expected metadata file "+filename+" did not exist.\n"+
|
||||
"The actual metadata has been saved in "+actualMetadataFile.getAbsoluteFile());
|
||||
}
|
||||
return readMetadata(inputStream);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Serializable> readMetadata(InputStream inputStream) throws IOException
|
||||
{
|
||||
TypeReference<HashMap<String, Serializable>> typeRef = new TypeReference<HashMap<String, Serializable>>() {};
|
||||
return jsonObjectMapper.readValue(inputStream, typeRef);
|
||||
}
|
||||
}
|
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import javax.jms.Queue;
|
||||
|
||||
import org.alfresco.transform.client.model.TransformReply;
|
||||
import org.alfresco.transform.client.model.TransformRequest;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.jms.core.JmsTemplate;
|
||||
|
||||
/**
|
||||
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
|
||||
*
|
||||
* @author Lucian Tuca
|
||||
* created on 15/01/2019
|
||||
*/
|
||||
@Deprecated
|
||||
@SpringBootTest(properties = {"activemq.url=nio://localhost:61616"})
|
||||
public abstract class AbstractQueueTransformServiceIT
|
||||
{
|
||||
@Autowired
|
||||
private Queue engineRequestQueue;
|
||||
|
||||
@Autowired
|
||||
private JmsTemplate jmsTemplate;
|
||||
|
||||
private final ActiveMQQueue testingQueue = new ActiveMQQueue(
|
||||
"org.alfresco.transform.engine.IT");
|
||||
|
||||
@Test
|
||||
public void queueTransformServiceIT()
|
||||
{
|
||||
TransformRequest request = buildRequest();
|
||||
|
||||
jmsTemplate.convertAndSend(engineRequestQueue, request, m -> {
|
||||
m.setJMSCorrelationID(request.getRequestId());
|
||||
m.setJMSReplyTo(testingQueue);
|
||||
return m;
|
||||
});
|
||||
|
||||
this.jmsTemplate.setReceiveTimeout(1_000);
|
||||
TransformReply reply = (TransformReply) this.jmsTemplate.receiveAndConvert(testingQueue);
|
||||
assertEquals(request.getRequestId(), reply.getRequestId());
|
||||
}
|
||||
|
||||
protected abstract TransformRequest buildRequest();
|
||||
}
|
@@ -0,0 +1,615 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.alfresco.transform.client.model.InternalContext;
|
||||
import org.alfresco.transform.client.model.TransformReply;
|
||||
import org.alfresco.transform.client.model.TransformRequest;
|
||||
import org.alfresco.transform.config.SupportedSourceAndTarget;
|
||||
import org.alfresco.transform.config.TransformConfig;
|
||||
import org.alfresco.transform.config.TransformOption;
|
||||
import org.alfresco.transform.config.TransformOptionGroup;
|
||||
import org.alfresco.transform.config.TransformOptionValue;
|
||||
import org.alfresco.transform.config.Transformer;
|
||||
import org.alfresco.transform.messages.TransformStack;
|
||||
import org.alfresco.transform.registry.TransformServiceRegistry;
|
||||
import org.alfresco.transformer.clients.AlfrescoSharedFileStoreClient;
|
||||
import org.alfresco.transformer.model.FileRefEntity;
|
||||
import org.alfresco.transformer.model.FileRefResponse;
|
||||
import org.alfresco.transformer.probes.ProbeTestTransform;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.ResultActions;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.Files;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
|
||||
import static org.alfresco.transform.common.RequestParamMap.DIRECT_ACCESS_URL;
|
||||
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM;
|
||||
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM_CONFIG;
|
||||
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM_CONFIG_LATEST;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
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.CREATED;
|
||||
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
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.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
|
||||
*
|
||||
* Super class for testing controllers without a server. Includes tests for the AbstractTransformerController itself.
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class AbstractTransformerControllerTest
|
||||
{
|
||||
@TempDir // added as part of ATS-702 to allow test resources to be read from the imported jar files to prevent test resource duplication
|
||||
public File tempDir;
|
||||
|
||||
@Autowired
|
||||
protected MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
protected ObjectMapper objectMapper;
|
||||
|
||||
@MockBean
|
||||
protected AlfrescoSharedFileStoreClient alfrescoSharedFileStoreClient;
|
||||
|
||||
@SpyBean
|
||||
protected TransformServiceRegistry transformRegistry;
|
||||
|
||||
@Value("${transform.core.version}")
|
||||
private String coreVersion;
|
||||
|
||||
protected String sourceExtension;
|
||||
protected String targetExtension;
|
||||
protected String sourceMimetype;
|
||||
protected String targetMimetype;
|
||||
protected HashMap<String, String> options = new HashMap<>();
|
||||
|
||||
protected MockMultipartFile sourceFile;
|
||||
protected String expectedOptions;
|
||||
protected String expectedSourceSuffix;
|
||||
protected Long expectedTimeout = 0L;
|
||||
protected byte[] expectedSourceFileBytes;
|
||||
|
||||
/**
|
||||
* The expected result. Taken resting target quick file's bytes.
|
||||
*
|
||||
* Note: These checks generally don't work on Windows (Mac and Linux are okay). Possibly to do with byte order
|
||||
* loading.
|
||||
*/
|
||||
protected byte[] expectedTargetFileBytes;
|
||||
|
||||
// Called by sub class
|
||||
protected abstract void mockTransformCommand(String sourceExtension,
|
||||
String targetExtension, String sourceMimetype,
|
||||
boolean readTargetFileBytes) throws IOException;
|
||||
|
||||
protected abstract AbstractTransformerController getController();
|
||||
|
||||
protected abstract void updateTransformRequestWithSpecificOptions(
|
||||
TransformRequest transformRequest);
|
||||
|
||||
/**
|
||||
* This method ends up being the core of the mock.
|
||||
* It copies content from an existing file in the resources folder to the desired location
|
||||
* in order to simulate a successful transformation.
|
||||
*
|
||||
* @param actualTargetExtension Requested extension.
|
||||
* @param testFile The test file (transformed) - basically the result.
|
||||
* @param targetFile The location where the content from the testFile should be copied
|
||||
* @throws IOException in case of any errors.
|
||||
*/
|
||||
void generateTargetFileFromResourceFile(String actualTargetExtension, File testFile,
|
||||
File targetFile) throws IOException
|
||||
{
|
||||
if (testFile != null)
|
||||
{
|
||||
try (var inputStream = new FileInputStream(testFile);
|
||||
var outputStream = new FileOutputStream(targetFile))
|
||||
{
|
||||
FileChannel source = inputStream.getChannel();
|
||||
FileChannel target = outputStream.getChannel();
|
||||
target.transferFrom(source, 0, source.size());
|
||||
|
||||
} catch (Exception e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
testFile = getTestFile("quick." + actualTargetExtension, false);
|
||||
if (testFile != null)
|
||||
{
|
||||
try (var inputStream = new FileInputStream(testFile);
|
||||
var outputStream = new FileOutputStream(targetFile))
|
||||
{
|
||||
FileChannel source = inputStream.getChannel();
|
||||
FileChannel target = outputStream.getChannel();
|
||||
target.transferFrom(source, 0, source.size());
|
||||
|
||||
} catch (Exception e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected byte[] readTestFile(String extension) throws IOException
|
||||
{
|
||||
return Files.readAllBytes(getTestFile("quick." + extension, true).toPath());
|
||||
}
|
||||
|
||||
protected File getTestFile(String testFilename, boolean required) throws IOException
|
||||
{
|
||||
File testFile = null;
|
||||
ClassLoader classLoader = getClass().getClassLoader();
|
||||
URL testFileUrl = classLoader.getResource(testFilename);
|
||||
if (required && testFileUrl == null)
|
||||
{
|
||||
throw new IOException("The test file " + testFilename +
|
||||
" does not exist in the resources directory");
|
||||
}
|
||||
// added as part of ATS-702 to allow test resources to be read from the imported jar files to prevent test resource duplication
|
||||
if (testFileUrl!=null)
|
||||
{
|
||||
// Each use of the tempDir should result in a unique directory being used
|
||||
testFile = new File(tempDir, testFilename);
|
||||
Files.copy(classLoader.getResourceAsStream(testFilename), testFile.toPath(),REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
return testFileUrl == null ? null : testFile;
|
||||
}
|
||||
|
||||
protected MockHttpServletRequestBuilder mockMvcRequest(String url, MockMultipartFile sourceFile, String... params)
|
||||
{
|
||||
if (sourceFile == null)
|
||||
{
|
||||
return mockMvcRequestWithoutMockMultipartFile(url, params);
|
||||
}
|
||||
else
|
||||
{
|
||||
return mockMvcRequestWithMockMultipartFile(url, sourceFile, params);
|
||||
}
|
||||
}
|
||||
|
||||
private MockHttpServletRequestBuilder mockMvcRequestWithoutMockMultipartFile(String url,
|
||||
String... params)
|
||||
{
|
||||
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.multipart(ENDPOINT_TRANSFORM);
|
||||
|
||||
if (params.length % 2 != 0)
|
||||
{
|
||||
throw new IllegalArgumentException("each param should have a name and value.");
|
||||
}
|
||||
for (int i = 0; i < params.length; i += 2)
|
||||
{
|
||||
builder = builder.param(params[i], params[i + 1]);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
private MockHttpServletRequestBuilder mockMvcRequestWithMockMultipartFile(String url, MockMultipartFile sourceFile,
|
||||
String... params)
|
||||
{
|
||||
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.multipart(ENDPOINT_TRANSFORM).file(
|
||||
sourceFile);
|
||||
|
||||
if (params.length % 2 != 0)
|
||||
{
|
||||
throw new IllegalArgumentException("each param should have a name and value.");
|
||||
}
|
||||
for (int i = 0; i < params.length; i += 2)
|
||||
{
|
||||
builder = builder.param(params[i], params[i + 1]);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
protected TransformRequest createTransformRequest(String sourceFileRef, File sourceFile)
|
||||
{
|
||||
TransformRequest transformRequest = new TransformRequest();
|
||||
transformRequest.setRequestId("1");
|
||||
transformRequest.setSchema(1);
|
||||
transformRequest.setClientData("Alfresco Digital Business Platform");
|
||||
transformRequest.setTransformRequestOptions(options);
|
||||
transformRequest.setSourceReference(sourceFileRef);
|
||||
transformRequest.setSourceExtension(sourceExtension);
|
||||
transformRequest.setSourceMediaType(sourceMimetype);
|
||||
transformRequest.setSourceSize(sourceFile.length());
|
||||
transformRequest.setTargetExtension(targetExtension);
|
||||
transformRequest.setTargetMediaType(targetMimetype);
|
||||
transformRequest.setInternalContext(InternalContext.initialise(null));
|
||||
transformRequest.getInternalContext().getMultiStep().setInitialRequestId("123");
|
||||
transformRequest.getInternalContext().getMultiStep().setInitialSourceMediaType(sourceMimetype);
|
||||
TransformStack.setInitialTransformRequestOptions(transformRequest.getInternalContext(), options);
|
||||
TransformStack.setInitialSourceReference(transformRequest.getInternalContext(), sourceFileRef);
|
||||
TransformStack.addTransformLevel(transformRequest.getInternalContext(),
|
||||
TransformStack.levelBuilder(TransformStack.PIPELINE_FLAG)
|
||||
.withStep("transformerName", sourceMimetype, targetMimetype));
|
||||
return transformRequest;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleTransformTest() throws Exception
|
||||
{
|
||||
mockMvc.perform(
|
||||
mockMvcRequest(ENDPOINT_TRANSFORM, sourceFile, "targetExtension", targetExtension))
|
||||
.andExpect(status().is(OK.value()))
|
||||
.andExpect(content().bytes(expectedTargetFileBytes))
|
||||
.andExpect(header().string("Content-Disposition",
|
||||
"attachment; filename*= UTF-8''quick." + targetExtension));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelayTest() throws Exception
|
||||
{
|
||||
long start = System.currentTimeMillis();
|
||||
mockMvc.perform(mockMvcRequest(ENDPOINT_TRANSFORM, sourceFile, "targetExtension", targetExtension,
|
||||
"testDelay", "400"))
|
||||
.andExpect(status().is(OK.value()))
|
||||
.andExpect(content().bytes(expectedTargetFileBytes))
|
||||
.andExpect(header().string("Content-Disposition",
|
||||
"attachment; filename*= UTF-8''quick." + targetExtension));
|
||||
long ms = System.currentTimeMillis() - start;
|
||||
System.out.println("Transform incluing test delay was " + ms);
|
||||
assertTrue(ms >= 400, "Delay sending the result back was too small " + ms);
|
||||
assertTrue(ms <= 500,"Delay sending the result back was too big " + ms);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noTargetFileTest() throws Exception
|
||||
{
|
||||
mockMvc.perform(mockMvcRequest(ENDPOINT_TRANSFORM, sourceFile, "targetExtension", "xxx"))
|
||||
.andExpect(status().is(INTERNAL_SERVER_ERROR.value()));
|
||||
}
|
||||
|
||||
@Test
|
||||
// Looks dangerous but is okay as we only use the final filename
|
||||
public void dotDotSourceFilenameTest() throws Exception
|
||||
{
|
||||
sourceFile = new MockMultipartFile("file", "../quick." + sourceExtension, sourceMimetype,
|
||||
expectedSourceFileBytes);
|
||||
|
||||
mockMvc.perform(
|
||||
mockMvcRequest(ENDPOINT_TRANSFORM, sourceFile, "targetExtension", targetExtension))
|
||||
.andExpect(status().is(OK.value()))
|
||||
.andExpect(content().bytes(expectedTargetFileBytes))
|
||||
.andExpect(header().string("Content-Disposition",
|
||||
"attachment; filename*= UTF-8''quick." + targetExtension));
|
||||
}
|
||||
|
||||
@Test
|
||||
// Is okay, as the target filename is built up from the whole source filename and the targetExtension
|
||||
public void noExtensionSourceFilenameTest() throws Exception
|
||||
{
|
||||
sourceFile = new MockMultipartFile("file", "../quick", sourceMimetype,
|
||||
expectedSourceFileBytes);
|
||||
|
||||
mockMvc.perform(
|
||||
mockMvcRequest(ENDPOINT_TRANSFORM, sourceFile, "targetExtension", targetExtension))
|
||||
.andExpect(status().is(OK.value()))
|
||||
.andExpect(content().bytes(expectedTargetFileBytes))
|
||||
.andExpect(header().string("Content-Disposition",
|
||||
"attachment; filename*= UTF-8''quick." + targetExtension));
|
||||
}
|
||||
|
||||
@Test
|
||||
// Invalid file name that ends in /
|
||||
public void badSourceFilenameTest() throws Exception
|
||||
{
|
||||
sourceFile = new MockMultipartFile("file", "abc/", sourceMimetype, expectedSourceFileBytes);
|
||||
|
||||
mockMvc.perform(
|
||||
mockMvcRequest(ENDPOINT_TRANSFORM, sourceFile, "targetExtension", targetExtension))
|
||||
.andExpect(status().is(BAD_REQUEST.value()))
|
||||
.andExpect(status().reason(containsString("The source filename was not supplied")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void blankSourceFilenameTest() throws Exception
|
||||
{
|
||||
sourceFile = new MockMultipartFile("file", "", sourceMimetype, expectedSourceFileBytes);
|
||||
|
||||
mockMvc.perform(
|
||||
mockMvcRequest(ENDPOINT_TRANSFORM, sourceFile, "targetExtension", targetExtension))
|
||||
.andExpect(status().is(BAD_REQUEST.value()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noTargetExtensionTest() throws Exception
|
||||
{
|
||||
mockMvc.perform(mockMvcRequest(ENDPOINT_TRANSFORM, sourceFile))
|
||||
.andExpect(status().is(BAD_REQUEST.value()))
|
||||
.andExpect(status().reason(
|
||||
containsString("Request parameter 'targetExtension' is missing")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void calculateMaxTime() throws Exception
|
||||
{
|
||||
ProbeTestTransform probeTestTransform = getController().getProbeTestTransform();
|
||||
probeTestTransform.setLivenessPercent(110);
|
||||
|
||||
long[][] values = new long[][]{
|
||||
{5000, 0, Long.MAX_VALUE}, // 1st transform is ignored
|
||||
{1000, 1000, 2100}, // 1000 + 1000*1.1
|
||||
{3000, 2000, 4200}, // 2000 + 2000*1.1
|
||||
{2000, 2000, 4200},
|
||||
{6000, 3000, 6300},
|
||||
{8000, 4000, 8400},
|
||||
{4444, 4000, 8400}, // no longer in the first few, so normal and max times don't change
|
||||
{5555, 4000, 8400}
|
||||
};
|
||||
|
||||
for (long[] v : values)
|
||||
{
|
||||
long time = v[0];
|
||||
long expectedNormalTime = v[1];
|
||||
long expectedMaxTime = v[2];
|
||||
|
||||
probeTestTransform.calculateMaxTime(time, true);
|
||||
assertEquals(expectedNormalTime, probeTestTransform.getNormalTime());
|
||||
assertEquals(expectedMaxTime, probeTestTransform.getMaxTime());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyPojoTransform() throws Exception
|
||||
{
|
||||
// Transformation Request POJO
|
||||
TransformRequest transformRequest = new TransformRequest();
|
||||
|
||||
// Serialize and call the transformer
|
||||
String tr = objectMapper.writeValueAsString(transformRequest);
|
||||
String transformationReplyAsString = mockMvc
|
||||
.perform(MockMvcRequestBuilders
|
||||
.post(ENDPOINT_TRANSFORM)
|
||||
.header(ACCEPT, APPLICATION_JSON_VALUE)
|
||||
.header(CONTENT_TYPE, APPLICATION_JSON_VALUE)
|
||||
.content(tr))
|
||||
.andExpect(status().is(BAD_REQUEST.value()))
|
||||
.andReturn().getResponse().getContentAsString();
|
||||
|
||||
TransformReply transformReply = objectMapper.readValue(transformationReplyAsString,
|
||||
TransformReply.class);
|
||||
|
||||
// Assert the reply
|
||||
assertEquals(BAD_REQUEST.value(), transformReply.getStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return transformer specific engine config name
|
||||
*/
|
||||
public String getEngineConfigName()
|
||||
{
|
||||
return "engine_config.json";
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTransformConfigInfo() throws Exception
|
||||
{
|
||||
TransformConfig expectedTransformConfig = objectMapper
|
||||
.readValue(getTestFile(getEngineConfigName(), true),
|
||||
TransformConfig.class);
|
||||
expectedTransformConfig.getTransformers().forEach(transformer -> {
|
||||
transformer.setCoreVersion(coreVersion);
|
||||
transformer.getTransformOptions().add(DIRECT_ACCESS_URL);
|
||||
});
|
||||
expectedTransformConfig.getTransformOptions().put(DIRECT_ACCESS_URL, Set.of(new TransformOptionValue(false, DIRECT_ACCESS_URL)));
|
||||
|
||||
ReflectionTestUtils.setField(transformRegistry, "engineConfig",
|
||||
new ClassPathResource(getEngineConfigName()));
|
||||
|
||||
String response = mockMvc
|
||||
.perform(MockMvcRequestBuilders.get(ENDPOINT_TRANSFORM_CONFIG_LATEST))
|
||||
.andExpect(status().is(OK.value()))
|
||||
.andExpect(header().string(CONTENT_TYPE, APPLICATION_JSON_VALUE))
|
||||
.andReturn().getResponse().getContentAsString();
|
||||
|
||||
TransformConfig transformConfig = objectMapper.readValue(response, TransformConfig.class);
|
||||
assertEquals(expectedTransformConfig, transformConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
// Test for case when T-Router or Repository is a version that does not expect it
|
||||
public void testGetTransformConfigInfoExcludingCoreVersion() throws Exception
|
||||
{
|
||||
TransformConfig expectedTransformConfig = objectMapper
|
||||
.readValue(getTestFile(getEngineConfigName(), true),
|
||||
TransformConfig.class);
|
||||
|
||||
ReflectionTestUtils.setField(transformRegistry, "engineConfig",
|
||||
new ClassPathResource(getEngineConfigName()));
|
||||
|
||||
String response = mockMvc
|
||||
.perform(MockMvcRequestBuilders.get(ENDPOINT_TRANSFORM_CONFIG))
|
||||
.andExpect(status().is(OK.value()))
|
||||
.andExpect(header().string(CONTENT_TYPE, APPLICATION_JSON_VALUE))
|
||||
.andReturn().getResponse().getContentAsString();
|
||||
|
||||
TransformConfig transformConfig = objectMapper.readValue(response, TransformConfig.class);
|
||||
assertEquals(expectedTransformConfig, transformConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetInfoFromConfigWithDuplicates() throws Exception
|
||||
{
|
||||
TransformConfig expectedResult = buildCompleteTransformConfig();
|
||||
|
||||
ReflectionTestUtils.setField(transformRegistry, "engineConfig",
|
||||
new ClassPathResource("engine_config_with_duplicates.json"));
|
||||
|
||||
String response = mockMvc
|
||||
.perform(MockMvcRequestBuilders.get(ENDPOINT_TRANSFORM_CONFIG))
|
||||
.andExpect(status().is(OK.value()))
|
||||
.andExpect(header().string(CONTENT_TYPE, APPLICATION_JSON_VALUE))
|
||||
.andReturn().getResponse().getContentAsString();
|
||||
|
||||
TransformConfig transformConfig = objectMapper.readValue(response, TransformConfig.class);
|
||||
|
||||
assertNotNull(transformConfig);
|
||||
assertEquals(expectedResult, transformConfig);
|
||||
assertEquals(3, transformConfig.getTransformOptions().get("engineXOptions").size());
|
||||
assertEquals(1,
|
||||
transformConfig.getTransformers().get(0).getSupportedSourceAndTargetList().size());
|
||||
assertEquals(1,
|
||||
transformConfig.getTransformers().get(0).getTransformOptions().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetInfoFromConfigWithEmptyTransformOptions() throws Exception
|
||||
{
|
||||
Transformer transformer = buildTransformer("application/pdf", "image/png");
|
||||
TransformConfig expectedResult = new TransformConfig();
|
||||
expectedResult.setTransformers(ImmutableList.of(transformer));
|
||||
|
||||
ReflectionTestUtils.setField(transformRegistry, "engineConfig",
|
||||
new ClassPathResource("engine_config_incomplete.json"));
|
||||
|
||||
String response = mockMvc
|
||||
.perform(MockMvcRequestBuilders.get(ENDPOINT_TRANSFORM_CONFIG))
|
||||
.andExpect(status().is(OK.value()))
|
||||
.andExpect(header().string(CONTENT_TYPE, APPLICATION_JSON_VALUE))
|
||||
.andReturn().getResponse().getContentAsString();
|
||||
|
||||
TransformConfig transformConfig = objectMapper.readValue(response, TransformConfig.class);
|
||||
|
||||
assertNotNull(transformConfig);
|
||||
assertEquals(expectedResult, transformConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetInfoFromConfigWithNoTransformOptions() throws Exception
|
||||
{
|
||||
Transformer transformer = buildTransformer("application/pdf", "image/png");
|
||||
transformer.setTransformerName("engineX");
|
||||
TransformConfig expectedResult = new TransformConfig();
|
||||
expectedResult.setTransformers(ImmutableList.of(transformer));
|
||||
|
||||
ReflectionTestUtils.setField(transformRegistry, "engineConfig",
|
||||
new ClassPathResource("engine_config_no_transform_options.json"));
|
||||
|
||||
String response = mockMvc
|
||||
.perform(MockMvcRequestBuilders.get(ENDPOINT_TRANSFORM_CONFIG))
|
||||
.andExpect(status().is(OK.value()))
|
||||
.andExpect(header().string(CONTENT_TYPE, APPLICATION_JSON_VALUE))
|
||||
.andReturn().getResponse().getContentAsString();
|
||||
|
||||
TransformConfig transformConfig = objectMapper.readValue(response, TransformConfig.class);
|
||||
|
||||
assertNotNull(transformConfig);
|
||||
assertEquals(expectedResult, transformConfig);
|
||||
}
|
||||
|
||||
private TransformConfig buildCompleteTransformConfig()
|
||||
{
|
||||
TransformConfig expectedResult = new TransformConfig();
|
||||
|
||||
Set<TransformOption> transformOptionGroup = ImmutableSet.of(
|
||||
new TransformOptionValue(false, "cropGravity"));
|
||||
Set<TransformOption> transformOptions = ImmutableSet.of(
|
||||
new TransformOptionValue(false, "page"),
|
||||
new TransformOptionValue(false, "width"),
|
||||
new TransformOptionGroup(false, transformOptionGroup));
|
||||
Map<String, Set<TransformOption>> transformOptionsMap = ImmutableMap.of("engineXOptions",
|
||||
transformOptions);
|
||||
|
||||
Transformer transformer = buildTransformer("application/pdf", "image/png", "engineXOptions",
|
||||
"engineX");
|
||||
List<Transformer> transformers = ImmutableList.of(transformer);
|
||||
|
||||
expectedResult.setTransformOptions(transformOptionsMap);
|
||||
expectedResult.setTransformers(transformers);
|
||||
|
||||
return expectedResult;
|
||||
}
|
||||
|
||||
private Transformer buildTransformer(String sourceMediaType, String targetMediaType,
|
||||
String transformOptions, String transformerName)
|
||||
{
|
||||
Transformer transformer = buildTransformer(sourceMediaType, targetMediaType);
|
||||
transformer.setTransformerName(transformerName);
|
||||
transformer.setTransformOptions(ImmutableSet.of(transformOptions));
|
||||
|
||||
return transformer;
|
||||
}
|
||||
|
||||
private Transformer buildTransformer(String sourceMediaType, String targetMediaType)
|
||||
{
|
||||
Set<SupportedSourceAndTarget> supportedSourceAndTargetList = ImmutableSet.of(
|
||||
SupportedSourceAndTarget.builder()
|
||||
.withSourceMediaType(sourceMediaType)
|
||||
.withTargetMediaType(targetMediaType)
|
||||
.build());
|
||||
|
||||
Transformer transformer = new Transformer();
|
||||
transformer.setSupportedSourceAndTargetList(supportedSourceAndTargetList);
|
||||
return transformer;
|
||||
}
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2015-2022 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
package org.alfresco.transformer;
|
||||
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static org.alfresco.transform.common.RequestParamMap.ENDPOINT_TRANSFORM;
|
||||
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
|
||||
*
|
||||
* @author Cezar Leahu
|
||||
*/
|
||||
@Deprecated
|
||||
public class EngineClient
|
||||
{
|
||||
private static final RestTemplate REST_TEMPLATE = new RestTemplate();
|
||||
|
||||
public static ResponseEntity<Resource> sendTRequest(
|
||||
final String engineUrl, final String sourceFile,
|
||||
final String sourceMimetype, final String targetMimetype, final String targetExtension)
|
||||
{
|
||||
return sendTRequest(engineUrl, sourceFile, sourceMimetype, targetMimetype, targetExtension,
|
||||
emptyMap());
|
||||
}
|
||||
|
||||
public static ResponseEntity<Resource> sendTRequest(
|
||||
final String engineUrl, final String sourceFile,
|
||||
final String sourceMimetype, final String targetMimetype, final String targetExtension,
|
||||
final Map<String, String> transformOptions)
|
||||
{
|
||||
final HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MULTIPART_FORM_DATA);
|
||||
//headers.setAccept(ImmutableList.of(MULTIPART_FORM_DATA));
|
||||
|
||||
final MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
|
||||
body.add("file", new ClassPathResource(sourceFile));
|
||||
if (sourceMimetype != null && !sourceMimetype.trim().isEmpty())
|
||||
{
|
||||
body.add("sourceMimetype", sourceMimetype);
|
||||
}
|
||||
if (targetMimetype != null && !targetMimetype.trim().isEmpty())
|
||||
{
|
||||
body.add("targetMimetype", targetMimetype);
|
||||
}
|
||||
if (targetExtension != null && !targetExtension.trim().isEmpty())
|
||||
{
|
||||
body.add("targetExtension", targetExtension);
|
||||
}
|
||||
transformOptions.forEach(body::add);
|
||||
|
||||
final HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(body, headers);
|
||||
|
||||
return REST_TEMPLATE.postForEntity(engineUrl + ENDPOINT_TRANSFORM, entity, Resource.class);
|
||||
}
|
||||
}
|
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
package org.alfresco.transformer;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
import static org.springframework.http.HttpStatus.CREATED;
|
||||
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
|
||||
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
|
||||
import org.alfresco.transform.client.model.TransformReply;
|
||||
import org.alfresco.transform.client.model.TransformRequest;
|
||||
import org.alfresco.transformer.messaging.TransformMessageConverter;
|
||||
import org.alfresco.transformer.messaging.TransformReplySender;
|
||||
import org.apache.activemq.command.ActiveMQObjectMessage;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.jms.support.converter.MessageConversionException;
|
||||
|
||||
/**
|
||||
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
|
||||
*/
|
||||
@Deprecated
|
||||
public class QueueTransformServiceTest
|
||||
{
|
||||
@Mock
|
||||
private TransformController transformController;
|
||||
@Mock
|
||||
private TransformMessageConverter transformMessageConverter;
|
||||
@Mock
|
||||
private TransformReplySender transformReplySender;
|
||||
|
||||
@InjectMocks
|
||||
private QueueTransformService queueTransformService;
|
||||
|
||||
@BeforeEach
|
||||
public void setup()
|
||||
{
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhenReceiveNullMessageThenStopFlow()
|
||||
{
|
||||
queueTransformService.receive(null);
|
||||
|
||||
verifyNoMoreInteractions(transformController);
|
||||
verifyNoMoreInteractions(transformMessageConverter);
|
||||
verifyNoMoreInteractions(transformReplySender);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhenReceiveMessageWithNoReplyToQueueThenStopFlow()
|
||||
{
|
||||
queueTransformService.receive(new ActiveMQObjectMessage());
|
||||
|
||||
verifyNoMoreInteractions(transformController);
|
||||
verifyNoMoreInteractions(transformMessageConverter);
|
||||
verifyNoMoreInteractions(transformReplySender);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertMessageReturnsNullThenReplyWithInternalServerError() throws JMSException
|
||||
{
|
||||
ActiveMQObjectMessage msg = new ActiveMQObjectMessage();
|
||||
msg.setCorrelationId("1234");
|
||||
ActiveMQQueue destination = new ActiveMQQueue();
|
||||
msg.setJMSReplyTo(destination);
|
||||
|
||||
TransformReply reply = TransformReply
|
||||
.builder()
|
||||
.withStatus(INTERNAL_SERVER_ERROR.value())
|
||||
.withErrorDetails(
|
||||
"JMS exception during T-Request deserialization of message with correlationID "
|
||||
+ msg.getCorrelationId() + ": null")
|
||||
.build();
|
||||
|
||||
doReturn(null).when(transformMessageConverter).fromMessage(msg);
|
||||
|
||||
queueTransformService.receive(msg);
|
||||
|
||||
verify(transformMessageConverter).fromMessage(msg);
|
||||
verify(transformReplySender).send(destination, reply, msg.getCorrelationId());
|
||||
|
||||
verifyNoMoreInteractions(transformController);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertMessageThrowsMessageConversionExceptionThenReplyWithBadRequest()
|
||||
throws JMSException
|
||||
{
|
||||
ActiveMQObjectMessage msg = new ActiveMQObjectMessage();
|
||||
msg.setCorrelationId("1234");
|
||||
ActiveMQQueue destination = new ActiveMQQueue();
|
||||
msg.setJMSReplyTo(destination);
|
||||
|
||||
TransformReply reply = TransformReply
|
||||
.builder()
|
||||
.withStatus(BAD_REQUEST.value())
|
||||
.withErrorDetails(
|
||||
"Message conversion exception during T-Request deserialization of message with correlationID"
|
||||
+ msg.getCorrelationId() + ": null")
|
||||
.build();
|
||||
|
||||
doThrow(MessageConversionException.class).when(transformMessageConverter).fromMessage(msg);
|
||||
|
||||
queueTransformService.receive(msg);
|
||||
|
||||
verify(transformMessageConverter).fromMessage(msg);
|
||||
verify(transformReplySender).send(destination, reply, msg.getCorrelationId());
|
||||
|
||||
verifyNoMoreInteractions(transformController);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertMessageThrowsJMSExceptionThenReplyWithInternalServerError()
|
||||
throws JMSException
|
||||
{
|
||||
ActiveMQObjectMessage msg = new ActiveMQObjectMessage();
|
||||
msg.setCorrelationId("1234");
|
||||
ActiveMQQueue destination = new ActiveMQQueue();
|
||||
msg.setJMSReplyTo(destination);
|
||||
|
||||
TransformReply reply = TransformReply
|
||||
.builder()
|
||||
.withStatus(INTERNAL_SERVER_ERROR.value())
|
||||
.withErrorDetails(
|
||||
"JMSException during T-Request deserialization of message with correlationID " +
|
||||
msg.getCorrelationId() + ": null")
|
||||
.build();
|
||||
|
||||
doThrow(JMSException.class).when(transformMessageConverter).fromMessage(msg);
|
||||
|
||||
queueTransformService.receive(msg);
|
||||
|
||||
verify(transformMessageConverter).fromMessage(msg);
|
||||
verify(transformReplySender).send(destination, reply, msg.getCorrelationId());
|
||||
|
||||
verifyNoMoreInteractions(transformController);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhenReceiveValidTransformRequestThenReplyWithSuccess() throws JMSException
|
||||
{
|
||||
ActiveMQObjectMessage msg = new ActiveMQObjectMessage();
|
||||
ActiveMQQueue destination = new ActiveMQQueue();
|
||||
msg.setJMSReplyTo(destination);
|
||||
|
||||
TransformRequest request = new TransformRequest();
|
||||
TransformReply reply = TransformReply
|
||||
.builder()
|
||||
.withStatus(CREATED.value())
|
||||
.build();
|
||||
|
||||
doReturn(request).when(transformMessageConverter).fromMessage(msg);
|
||||
doReturn(new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus())))
|
||||
.when(transformController).transform(request, null);
|
||||
|
||||
queueTransformService.receive(msg);
|
||||
|
||||
verify(transformMessageConverter).fromMessage(msg);
|
||||
verify(transformController).transform(request, null);
|
||||
verify(transformReplySender).send(destination, reply);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhenJMSExceptionOnMessageIsThrownThenStopFlow() throws JMSException
|
||||
{
|
||||
Message msg = mock(Message.class);
|
||||
|
||||
doThrow(JMSException.class).when(msg).getJMSReplyTo();
|
||||
|
||||
queueTransformService.receive(msg);
|
||||
|
||||
verifyNoMoreInteractions(transformController);
|
||||
verifyNoMoreInteractions(transformMessageConverter);
|
||||
verifyNoMoreInteractions(transformReplySender);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhenExceptionOnCorrelationIdIsThrownThenContinueFlowWithNullCorrelationId()
|
||||
throws JMSException
|
||||
{
|
||||
Message msg = mock(Message.class);
|
||||
Destination destination = mock(Destination.class);
|
||||
|
||||
doThrow(JMSException.class).when(msg).getJMSCorrelationID();
|
||||
doReturn(destination).when(msg).getJMSReplyTo();
|
||||
|
||||
TransformRequest request = new TransformRequest();
|
||||
TransformReply reply = TransformReply
|
||||
.builder()
|
||||
.withStatus(CREATED.value())
|
||||
.build();
|
||||
|
||||
doReturn(request).when(transformMessageConverter).fromMessage(msg);
|
||||
doReturn(new ResponseEntity<>(reply, HttpStatus.valueOf(reply.getStatus())))
|
||||
.when(transformController).transform(request, null);
|
||||
|
||||
queueTransformService.receive(msg);
|
||||
|
||||
verify(transformMessageConverter).fromMessage(msg);
|
||||
verify(transformController).transform(request, null);
|
||||
verify(transformReplySender).send(destination, reply);
|
||||
}
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
|
||||
*
|
||||
* Source & Target media type pair
|
||||
*
|
||||
* @author Cezar Leahu
|
||||
*/
|
||||
@Deprecated
|
||||
public class SourceTarget
|
||||
{
|
||||
public final String source;
|
||||
public final String target;
|
||||
|
||||
private SourceTarget(final String source, final String target)
|
||||
{
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
SourceTarget that = (SourceTarget) o;
|
||||
return Objects.equals(source, that.source) &&
|
||||
Objects.equals(target, that.target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(source, target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return source + '|' + target;
|
||||
}
|
||||
|
||||
public static SourceTarget of(final String source, final String target)
|
||||
{
|
||||
return new SourceTarget(source, target);
|
||||
}
|
||||
}
|
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Transform Core
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* -
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
* -
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.transformer;
|
||||
|
||||
/**
|
||||
* @deprecated will be removed in a future release. Replaced by alfresco-base-t-engine.
|
||||
* @author Cezar Leahu
|
||||
*/
|
||||
@Deprecated
|
||||
public class TestFileInfo
|
||||
{
|
||||
private final String mimeType;
|
||||
private final String extension;
|
||||
private final String path;
|
||||
private final boolean exactMimeType;
|
||||
|
||||
public TestFileInfo(final String mimeType, final String extension, final String path,
|
||||
final boolean exactMimeType)
|
||||
{
|
||||
this.mimeType = mimeType;
|
||||
this.extension = extension;
|
||||
this.path = path;
|
||||
this.exactMimeType = exactMimeType;
|
||||
}
|
||||
|
||||
public String getMimeType()
|
||||
{
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
public String getExtension()
|
||||
{
|
||||
return extension;
|
||||
}
|
||||
|
||||
public String getPath()
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
public boolean isExactMimeType()
|
||||
{
|
||||
return exactMimeType;
|
||||
}
|
||||
|
||||
public static TestFileInfo testFile(final String mimeType, final String extension,
|
||||
final String path, final boolean exactMimeType)
|
||||
{
|
||||
return new TestFileInfo(mimeType, extension, path, exactMimeType);
|
||||
}
|
||||
|
||||
public static TestFileInfo testFile(final String mimeType, final String extension,
|
||||
final String path)
|
||||
{
|
||||
return new TestFileInfo(mimeType, extension, path, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"transformOptions": {
|
||||
"engineXOptions": [
|
||||
{"value": {"name": "page"}},
|
||||
{"value": {"name": "width"}},
|
||||
{"group": {"transformOptions": [
|
||||
{"value": {"name": "cropGravity"}}
|
||||
]}}
|
||||
]
|
||||
},
|
||||
"transformers": [
|
||||
{
|
||||
"transformerName": "engineX",
|
||||
"supportedSourceAndTargetList": [
|
||||
{"sourceMediaType": "application/pdf", "targetMediaType": "image/png" }
|
||||
],
|
||||
"transformOptions": [
|
||||
"engineXOptions"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"transformOptions": {},
|
||||
"transformers": [
|
||||
{
|
||||
"supportedSourceAndTargetList": [
|
||||
{"sourceMediaType": "application/pdf", "targetMediaType": "image/png" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"transformers": [
|
||||
{
|
||||
"transformerName": "engineX",
|
||||
"supportedSourceAndTargetList": [
|
||||
{"sourceMediaType": "application/pdf", "targetMediaType": "image/png" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"transformOptions": {
|
||||
"engineXOptions": [
|
||||
{"value": {"name": "page"}},
|
||||
{"value": {"name": "page"}},
|
||||
{"value": {"name": "width"}},
|
||||
{"group": {"transformOptions": [
|
||||
{"value": {"name": "cropGravity"}}
|
||||
]}}
|
||||
]
|
||||
},
|
||||
"transformers": [
|
||||
{
|
||||
"transformerName": "engineX",
|
||||
"supportedSourceAndTargetList": [
|
||||
{"sourceMediaType": "application/pdf", "targetMediaType": "image/png" },
|
||||
{"sourceMediaType": "application/pdf", "targetMediaType": "image/png" },
|
||||
{"sourceMediaType": "application/pdf", "targetMediaType": "image/png" }
|
||||
],
|
||||
"transformOptions": [
|
||||
"engineXOptions",
|
||||
"engineXOptions"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
Reference in New Issue
Block a user