Allow T-Router to be a T-Engine

This commit is contained in:
alandavis
2022-08-13 18:38:08 +01:00
parent 29fa2086af
commit 13ba2534ea
48 changed files with 1425 additions and 172 deletions

View File

@@ -37,6 +37,10 @@
<artifactId>jackson-annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>

View File

@@ -50,7 +50,7 @@ public class TransformerDebug
private static int MAX_OPTION_END_CHARS = 5;
private static String MAX_OPTION_DOTS = "...";
private boolean isTEngine = false;
private boolean isTRouter = false;
public void pushTransform(TransformRequest request)
{
@@ -64,7 +64,7 @@ public class TransformerDebug
String message = getPaddedReference(reference) +
getMimetypeExt(step.getSourceMediaType()) +
getTargetMimetypeExt(step.getTargetMediaType(), step.getSourceMediaType()) + ' ' +
(isTopLevel || isTEngine()
(isTopLevel || !isTRouter()
? fileSize(request.getSourceSize()) + ' ' +
getRenditionName(new RepositoryClientData(request.getClientData()).getRenditionName())
: "") +
@@ -117,7 +117,7 @@ public class TransformerDebug
if (logger.isDebugEnabled())
{
String message = getPaddedReference(reference) + "Finished in " + ms(elapsedTime);
if (isTopLevel(reference) || isTEngine())
if (isTopLevel(reference) || !isTRouter())
{
logger.debug(message);
}
@@ -221,9 +221,9 @@ public class TransformerDebug
}
// T-Engines call this method, as the T-Router will appended the same debug messages
public TransformerDebug setIsTEngine(boolean isTEngine)
public TransformerDebug setIsTRouter(boolean isTRouter)
{
this.isTEngine = isTEngine;
this.isTRouter = isTRouter;
return this;
}
@@ -234,12 +234,12 @@ public class TransformerDebug
private boolean isDebugToBeReturned(RepositoryClientData repositoryClientData)
{
return !isTEngine() && repositoryClientData.isDebugRequested();
return isTRouter() && repositoryClientData.isDebugRequested();
}
private boolean isTEngine()
private boolean isTRouter()
{
return isTEngine;
return isTRouter;
}
private boolean isTopLevel(String reference)

View File

@@ -56,7 +56,32 @@ public class TransformConfig
public void setTransformOptions(Map<String, Set<TransformOption>> transformOptions)
{
this.transformOptions = new HashMap<>(transformOptions);
this.transformOptions = transformOptions == null ? new HashMap<>() : new HashMap<>(transformOptions);
}
public void setRemoveTransformers(Set<String> removeTransformers)
{
this.removeTransformers = removeTransformers == null ? new HashSet<>() : removeTransformers;
}
public void setAddSupported(Set<AddSupported> addSupported)
{
this.addSupported = addSupported == null ? new HashSet<>() : addSupported;
}
public void setRemoveSupported(Set<RemoveSupported> removeSupported)
{
this.removeSupported = removeSupported == null ? new HashSet<>() : removeSupported;
}
public void setOverrideSupported(Set<OverrideSupported> overrideSupported)
{
this.overrideSupported = overrideSupported == null ? new HashSet<>() : overrideSupported;
}
public void setSupportedDefaults(Set<SupportedDefaults> supportedDefaults)
{
this.supportedDefaults = supportedDefaults == null ? new HashSet<>() : supportedDefaults;
}
public List<Transformer> getTransformers()
@@ -91,7 +116,7 @@ public class TransformConfig
public void setTransformers(List<Transformer> transformers)
{
this.transformers = transformers;
this.transformers = transformers == null ? new ArrayList<>() : transformers;
}
@Override

View File

@@ -53,7 +53,7 @@ public class TransformOptionGroup extends AbstractTransformOption
public void setTransformOptions(Set<TransformOption> transformOptions)
{
this.transformOptions = transformOptions;
this.transformOptions = transformOptions == null ? new HashSet<>() : transformOptions;
}
@Override

View File

@@ -119,7 +119,7 @@ public class Transformer
public void setTransformerPipeline(List<TransformStep> transformerPipeline)
{
this.transformerPipeline = transformerPipeline;
this.transformerPipeline = transformerPipeline == null ? new ArrayList<>() : transformerPipeline;
}
public List<String> getTransformerFailover()
@@ -129,7 +129,7 @@ public class Transformer
public void setTransformerFailover(List<String> transformerFailover)
{
this.transformerFailover = transformerFailover;
this.transformerFailover = transformerFailover == null ? new ArrayList<>() : transformerFailover;
}
public Set<String> getTransformOptions()
@@ -139,7 +139,7 @@ public class Transformer
public void setTransformOptions(Set<String> transformOptions)
{
this.transformOptions = transformOptions;
this.transformOptions = transformOptions == null ? new HashSet<>() : transformOptions;
}
public Set<SupportedSourceAndTarget> getSupportedSourceAndTargetList()
@@ -150,7 +150,7 @@ public class Transformer
public void setSupportedSourceAndTargetList(
Set<SupportedSourceAndTarget> supportedSourceAndTargetList)
{
this.supportedSourceAndTargetList = supportedSourceAndTargetList;
this.supportedSourceAndTargetList = supportedSourceAndTargetList == null ? new HashSet<>() : supportedSourceAndTargetList;
}
@Override

View File

@@ -0,0 +1,31 @@
/*
* #%L
* Alfresco Transform Model
* %%
* Copyright (C) 2015 - 2022 Alfresco Software Limited
* %%
* This program 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.
*
* This program 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>.
* #L%
*/
package org.alfresco.transform.config.reader;
import org.alfresco.transform.config.TransformConfig;
import java.io.IOException;
public interface TransformConfigReader
{
TransformConfig load() throws IOException;
}

View File

@@ -0,0 +1,53 @@
/*
* #%L
* Alfresco Transform Model
* %%
* Copyright (C) 2015 - 2022 Alfresco Software Limited
* %%
* This program 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.
*
* This program 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>.
* #L%
*/
package org.alfresco.transform.config.reader;
import static java.util.Objects.isNull;
import org.springframework.core.io.Resource;
public class TransformConfigReaderFactory
{
public static TransformConfigReader create(final Resource resource)
{
final String fileName = resource.getFilename();
if (isNull(fileName) || !fileName.contains("."))
{
throw new RuntimeException("Invalid configuration file: " + fileName);
}
final String extension = fileName.substring(fileName.lastIndexOf('.') + 1);
switch (extension)
{
case "properties":
throw new UnsupportedOperationException(".properties configuration files are no longer " +
"supported: " + fileName);
case "yaml":
case "yml":
return new TransformConfigReaderYaml(resource);
case "json":
return new TransformConfigReaderJson(resource);
default:
throw new RuntimeException("Unknown configuration file type: " + fileName);
}
}
}

View File

@@ -0,0 +1,47 @@
/*
* #%L
* Alfresco Transform Model
* %%
* Copyright (C) 2015 - 2022 Alfresco Software Limited
* %%
* This program 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.
*
* This program 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>.
* #L%
*/
package org.alfresco.transform.config.reader;
import java.io.IOException;
import org.alfresco.transform.config.TransformConfig;
import org.springframework.core.io.Resource;
import com.fasterxml.jackson.databind.ObjectMapper;
public class TransformConfigReaderJson implements TransformConfigReader
{
private static final ObjectMapper MAPPER= new ObjectMapper();
private final Resource resource;
TransformConfigReaderJson(final Resource resource)
{
this.resource = resource;
}
@Override
public TransformConfig load() throws IOException
{
return MAPPER.readValue(resource.getInputStream(), TransformConfig.class);
}
}

View File

@@ -0,0 +1,48 @@
/*
* #%L
* Alfresco Transform Model
* %%
* Copyright (C) 2015 - 2022 Alfresco Software Limited
* %%
* This program 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.
*
* This program 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>.
* #L%
*/
package org.alfresco.transform.config.reader;
import java.io.IOException;
import org.alfresco.transform.config.TransformConfig;
import org.springframework.core.io.Resource;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
public class TransformConfigReaderYaml implements TransformConfigReader
{
private static final ObjectMapper MAPPER = new ObjectMapper(new YAMLFactory());
private final Resource resource;
TransformConfigReaderYaml(final Resource resource)
{
this.resource = resource;
}
@Override
public TransformConfig load() throws IOException
{
return MAPPER.readValue(resource.getInputStream(), TransformConfig.class);
}
}

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* Copyright (C) 2022 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
@@ -24,9 +24,9 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.transform.common;
package org.alfresco.transform.config.reader;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.alfresco.transform.common.TransformException;
import org.alfresco.transform.config.TransformConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
@@ -41,7 +41,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
/**
* Reads {@link TransformConfig} from a {@json} file. Typically used by {@code TransformEngine.getTransformConfig()}.
* Reads {@link TransformConfig} from json or yaml files. Typically used by {@code TransformEngine.getTransformConfig()}.
* <pre>
* transformConfigResourceReader.read("classpath:pdfrenderer_engine_config.json");
* </pre>
@@ -51,20 +51,16 @@ public class TransformConfigResourceReader
{
@Autowired ResourceLoader resourceLoader;
private ObjectMapper jsonObjectMapper = new ObjectMapper();
public TransformConfig read(String engineConfigLocation)
public TransformConfig read(String resourcePath)
{
Resource engineConfig = resourceLoader.getResource(engineConfigLocation);
return read(engineConfig);
return read(resourceLoader.getResource(resourcePath));
}
public TransformConfig read(Resource resource)
{
try (Reader reader = new InputStreamReader(resource.getInputStream(), UTF_8))
try
{
TransformConfig transformConfig = jsonObjectMapper.readValue(reader, TransformConfig.class);
return transformConfig;
return TransformConfigReaderFactory.create(resource).load();
}
catch (IOException e)
{

View File

@@ -32,6 +32,7 @@ import org.alfresco.transform.config.TransformStep;
import org.alfresco.transform.config.Transformer;
import org.alfresco.transform.config.TransformerAndTypes;
import org.alfresco.transform.config.Types;
import org.apache.commons.lang3.tuple.Triple;
import java.util.ArrayList;
import java.util.HashMap;
@@ -827,4 +828,9 @@ public class CombinedTransformConfig
{
return combinedTransformers.size();
}
public Map<String,Origin<Transformer>> getTransformerByNameMap()
{
return combinedTransformers.stream().collect(Collectors.toMap(origin -> origin.get().getTransformerName(), origin -> origin));
}
}

View File

@@ -39,6 +39,7 @@ import static java.util.Collections.emptyMap;
import static java.util.Collections.emptySet;
import static java.util.Map.Entry;
import static java.util.stream.Collectors.toMap;
import static org.alfresco.transform.common.RequestParamMap.SOURCE_ENCODING;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
class TransformRegistryHelper
@@ -95,17 +96,36 @@ class TransformRegistryHelper
return cachedTransformList;
}
final List<SupportedTransform> builtTransformList = buildTransformList(data,
sourceMimetype,
targetMimetype,
filterTimeout(actualOptions));
if (renditionName != null)
// The transformOptions always contains sourceEncoding and possibly timeout when sent to a T-Engine, even though
// they should not be used to select a transformer. Would like to change this, but cannot as we need to support
// older ACS repo versions.
String sourceEncoding = actualOptions.remove(SOURCE_ENCODING);
String timeout = actualOptions.remove(TIMEOUT);
try
{
data.cache(renditionName, sourceMimetype, builtTransformList);
}
final List<SupportedTransform> builtTransformList = buildTransformList(data,
sourceMimetype,
targetMimetype,
actualOptions);
return builtTransformList;
if (renditionName != null)
{
data.cache(renditionName, sourceMimetype, builtTransformList);
}
return builtTransformList;
}
finally
{
if (sourceEncoding != null)
{
actualOptions.put(SOURCE_ENCODING, sourceEncoding);
}
if (timeout != null)
{
actualOptions.put(TIMEOUT, timeout);
}
}
}
private static List<SupportedTransform> buildTransformList(
@@ -349,18 +369,4 @@ class TransformRegistryHelper
.stream()
.allMatch(transformOptions::containsKey);
}
private static Map<String, String> filterTimeout(final Map<String, String> options)
{
// Remove the "timeout" property from the actualOptions as it is not used to select a transformer.
if (!options.containsKey(TIMEOUT))
{
return options;
}
return options
.entrySet()
.stream()
.filter(e -> !TIMEOUT.equals(e.getKey()))
.collect(toMap(Entry::getKey, Entry::getValue));
}
}

View File

@@ -63,10 +63,10 @@ class TransformerDebugTest
.replaceAll(" [\\d,]+ ms", " -- ms");
}
private void twoStepTransform(boolean isTEngine, boolean fail, Level logLevel, String renditionName,
private void twoStepTransform(boolean isTRouter, boolean fail, Level logLevel, String renditionName,
long sourceSize)
{
transformerDebug.setIsTEngine(isTEngine);
transformerDebug.setIsTRouter(isTRouter);
monitorLogs(logLevel);
TransformRequest request = TransformRequest.builder()
@@ -144,7 +144,7 @@ class TransformerDebugTest
@Test
void testRouterTwoStepTransform()
{
twoStepTransform(false, false, Level.DEBUG, "", 1234L);
twoStepTransform(true, false, Level.DEBUG, "", 1234L);
Assertions.assertEquals("" +
"1 txt pdf 1.2 KB wrapper\n" +
@@ -159,7 +159,7 @@ class TransformerDebugTest
@Test
void testRouterTwoStepTransformWithTrace()
{
twoStepTransform(false, false, Level.TRACE, "", 1234L);
twoStepTransform(true, false, Level.TRACE, "", 1234L);
// With trace there are "Finished" lines for nested transforms, like a T-Engine's debug but still without
// the size and rendition name
@@ -178,7 +178,7 @@ class TransformerDebugTest
@Test
void testEngineTwoStepTransform()
{
twoStepTransform(true, false, Level.DEBUG, "", 1234L);
twoStepTransform(false, false, Level.DEBUG, "", 1234L);
// Note the first and last lines would only ever be logged on the router, but the expected data includes
// the extra "Finished" lines, sizes and renditions (if set in client data).
@@ -197,7 +197,7 @@ class TransformerDebugTest
@Test
void testRouterTwoStepTransformWithFailure()
{
twoStepTransform(false, true, Level.DEBUG, "", 1234L);
twoStepTransform(true, true, Level.DEBUG, "", 1234L);
Assertions.assertEquals("" +
"1 txt pdf 1.2 KB wrapper\n" +
@@ -212,7 +212,7 @@ class TransformerDebugTest
@Test
void testRenditionName()
{
twoStepTransform(false, false, Level.DEBUG, "renditionName", 1234L);
twoStepTransform(true, false, Level.DEBUG, "renditionName", 1234L);
Assertions.assertEquals("" +
"1 txt pdf 1.2 KB -- renditionName -- wrapper\n" +
@@ -227,7 +227,7 @@ class TransformerDebugTest
@Test
void testMetadataExtract()
{
twoStepTransform(false, false, Level.DEBUG, "transform:alfresco-metadata-extract", 1234L);
twoStepTransform(true, false, Level.DEBUG, "transform:alfresco-metadata-extract", 1234L);
Assertions.assertEquals("" +
"1 txt pdf 1.2 KB -- metadataExtract -- wrapper\n" +
@@ -242,7 +242,7 @@ class TransformerDebugTest
@Test
void testMetadataEmbed()
{
twoStepTransform(false, false, Level.DEBUG, "transform:alfresco-metadata-embed", 1234L);
twoStepTransform(true, false, Level.DEBUG, "transform:alfresco-metadata-embed", 1234L);
Assertions.assertEquals("" +
"1 txt pdf 1.2 KB -- metadataEmbed -- wrapper\n" +
@@ -257,7 +257,7 @@ class TransformerDebugTest
@Test
void testSourceSize1Byte()
{
twoStepTransform(false, false, Level.DEBUG, "", 1);
twoStepTransform(true, false, Level.DEBUG, "", 1);
Assertions.assertEquals("" +
"1 txt pdf 1 byte wrapper\n" +
@@ -272,7 +272,7 @@ class TransformerDebugTest
@Test
void testSourceSize23TB()
{
twoStepTransform(false, false, Level.DEBUG, "", 23L*1024*1024*1024*1024);
twoStepTransform(true, false, Level.DEBUG, "", 23L*1024*1024*1024*1024);
Assertions.assertEquals("" +
"1 txt pdf 23 TB wrapper\n" +
@@ -285,7 +285,7 @@ class TransformerDebugTest
}
@Test
void testLogFailure()
void testLogFailureOnTEngine()
{
monitorLogs(Level.TRACE);
@@ -296,11 +296,33 @@ class TransformerDebugTest
.withClientData(origClientData)
.build();
transformerDebug.setIsTRouter(false);
transformerDebug.logFailure(reply);
String expectedDebug = " T-Request was null - a major error";
Assertions.assertEquals(expectedDebug, getTransformerDebugOutput());
assertEquals(origClientData+DEBUG_SEPARATOR+expectedDebug, reply.getClientData());
assertEquals(origClientData, reply.getClientData());
}
@Test
void testLogFailureOnTRouter()
{
monitorLogs(Level.TRACE);
String origClientData = clientDataWithDebugRequest("");
TransformReply reply = TransformReply.builder()
.withInternalContext(InternalContext.initialise(null))
.withErrorDetails("T-Request was null - a major error")
.withClientData(origClientData)
.build();
transformerDebug.setIsTRouter(true);
transformerDebug.logFailure(reply);
String expectedDebug = " T-Request was null - a major error";
String expectedClientData = origClientData+DEBUG_SEPARATOR+expectedDebug;
Assertions.assertEquals(expectedDebug, getTransformerDebugOutput());
assertEquals(expectedClientData, reply.getClientData());
}
@Test

View File

@@ -0,0 +1,300 @@
/*
* #%L
* Alfresco Transform Model
* %%
* Copyright (C) 2015 - 2022 Alfresco Software Limited
* %%
* This program 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.
*
* This program 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>.
* #L%
*/
package org.alfresco.transform.config.reader;
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 java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.ImmutableMap;
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.config.SupportedSourceAndTarget;
import org.alfresco.transform.config.TransformStep;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
public class TransformConfigReaderJsonTest
{
@Test
public void testEmptyRoutesFile() throws Exception
{
final Resource resource = new ClassPathResource("config/sample1.json");
final TransformConfigReader loader = TransformConfigReaderFactory.create(resource);
TransformConfig transformConfig = loader.load();
final List<Transformer> transformers = transformConfig.getTransformers();
assertNotNull(transformers);
assertEquals(Collections.emptyList(), transformers);
}
@Test
public void testMixedRoutesFile() throws Exception
{
final List<Transformer> expected = prepareSample2();
final Resource resource = new ClassPathResource("config/sample2.json");
final TransformConfigReader loader = TransformConfigReaderFactory.create(resource);
TransformConfig transformConfig = loader.load();
final List<Transformer> transformers = transformConfig.getTransformers();
assertNotNull(transformers);
assertEquals(expected.size(), transformers.size());
assertTrue(expected.containsAll(transformers));
}
private List<Transformer> prepareSample2()
{
return List.of(
Transformer.builder()
.withTransformerName("CORE_AIO")
.withSupportedSourceAndTargetList(ImmutableSet.of(
SupportedSourceAndTarget.builder()
.withSourceMediaType("image/gif")
.withTargetMediaType("image/gif")
.build()
))
.withTransformOptions(ImmutableSet.of("imageMagickOptions"))
.build(),
Transformer.builder()
.withTransformerName("IMAGEMAGICK")
.withSupportedSourceAndTargetList(ImmutableSet.of(
SupportedSourceAndTarget.builder()
.withSourceMediaType("image/gif")
.withTargetMediaType("image/gif")
.build()
))
.withTransformOptions(ImmutableSet.of("imageMagickOptions"))
.build(),
Transformer.builder()
.withTransformerName("CORE_AIO")
.withSupportedSourceAndTargetList(ImmutableSet.of(
SupportedSourceAndTarget.builder()
.withSourceMediaType("application/msword")
.withTargetMediaType("application/pdf")
.withMaxSourceSizeBytes(18874368L)
.build()
))
.build(),
Transformer.builder()
.withTransformerName("PDF_RENDERER")
.withSupportedSourceAndTargetList(ImmutableSet.of(
SupportedSourceAndTarget.builder()
.withSourceMediaType("application/vnd.ms-powerpoint")
.withTargetMediaType("application/pdf")
.withPriority(55)
.withMaxSourceSizeBytes(50331648L)
.build()
))
.build(),
Transformer.builder()
.withTransformerName("CORE_AIO")
.withSupportedSourceAndTargetList(ImmutableSet.of(
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/plain")
.withTargetMediaType("text/plain")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/mediawiki")
.withTargetMediaType("text/plain")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/css")
.withTargetMediaType("text/plain")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/csv")
.withTargetMediaType("text/plain")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/xml")
.withTargetMediaType("text/plain")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/html")
.withTargetMediaType("text/plain")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("application/x-javascript")
.withTargetMediaType("text/plain")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("application/dita+xml")
.withTargetMediaType("text/plain")
.build()
))
.withTransformOptions(ImmutableSet.of("stringOptions"))
.build(),
Transformer.builder()
.withTransformerName("officeToImageViaPdf")
.withTransformerPipeline(ImmutableList.of(
new TransformStep("libreoffice", "application/pdf"),
new TransformStep("pdfToImageViaPng", null)
))
.withTransformOptions(ImmutableSet.of(
"pdfRendererOptions",
"imageMagickOptions"
))
.build(),
Transformer.builder()
.withTransformerName("textToImageViaPdf")
.withTransformerPipeline(ImmutableList.of(
new TransformStep("libreoffice", "application/pdf"),
new TransformStep("pdfToImageViaPng", null)
))
.withTransformOptions(ImmutableSet.of(
"pdfRendererOptions",
"imageMagickOptions"
))
.withSupportedSourceAndTargetList(ImmutableSet.of(
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/plain")
.withTargetMediaType("image/gif")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/plain")
.withTargetMediaType("image/jpeg")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/plain")
.withTargetMediaType("image/tiff")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/plain")
.withTargetMediaType("image/png")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/csv")
.withTargetMediaType("image/gif")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/csv")
.withTargetMediaType("image/jpeg")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/csv")
.withTargetMediaType("image/tiff")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/csv")
.withTargetMediaType("image/png")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/xml")
.withTargetMediaType("image/gif")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/xml")
.withTargetMediaType("image/jpeg")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/xml")
.withTargetMediaType("image/tiff")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/xml")
.withTargetMediaType("image/png")
.build()
))
.withTransformOptions(ImmutableSet.of(
"pdfRendererOptions",
"imageMagickOptions"
))
.build()
);
}
@Test
public void testRouteFileWithTransformOptions() throws Exception
{
final List<Transformer> expected = prepareSample5Transformers();
Map<String, Set<TransformOption>> expectedOptions = prepareSample5Options();
final Resource resource = new ClassPathResource("config/sample5.json");
final TransformConfigReader loader = TransformConfigReaderFactory.create(resource);
TransformConfig transformConfig = loader.load();
final List<Transformer> transformers = transformConfig.getTransformers();
Map<String, Set<TransformOption>> transformOptions = transformConfig.getTransformOptions();
assertNotNull(transformers);
assertEquals(expected.size(), transformers.size());
assertTrue(expected.containsAll(transformers));
assertEquals(expectedOptions, transformOptions);
}
private List<Transformer> prepareSample5Transformers()
{
return List.of(
Transformer.builder()
.withTransformerName("CORE_AIO")
.withSupportedSourceAndTargetList(ImmutableSet.of(
SupportedSourceAndTarget.builder()
.withSourceMediaType("image/gif")
.withTargetMediaType("image/gif")
.build()
))
.withTransformOptions(ImmutableSet.of("imageMagickOptions"))
.build()
);
}
public static Map<String, Set<TransformOption>> prepareSample5Options()
{
return ImmutableMap.of(
"imageMagickOptions", ImmutableSet.of(
new TransformOptionValue(false, "alphaRemove"),
new TransformOptionValue(false, "autoOrient"),
new TransformOptionValue(false, "startPage"),
new TransformOptionValue(false, "endPage"),
new TransformOptionGroup(false, ImmutableSet.of(
new TransformOptionValue(false, "cropGravity"),
new TransformOptionValue(false, "cropWidth"),
new TransformOptionValue(false, "cropHeight"),
new TransformOptionValue(false, "cropPercentage"),
new TransformOptionValue(false, "cropXOffset"),
new TransformOptionValue(false, "cropYOffset")
)),
new TransformOptionGroup(false, ImmutableSet.of(
new TransformOptionValue(false, "thumbnail"),
new TransformOptionValue(false, "resizeHeight"),
new TransformOptionValue(false, "resizeWidth"),
new TransformOptionValue(false, "resizePercentage"),
new TransformOptionValue(false, "allowEnlargement"),
new TransformOptionValue(false, "maintainAspectRatio")
)))
);
}
}

View File

@@ -0,0 +1,245 @@
/*
* #%L
* Alfresco Transform Model
* %%
* Copyright (C) 2015 - 2022 Alfresco Software Limited
* %%
* This program 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.
*
* This program 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>.
* #L%
*/
package org.alfresco.transform.config.reader;
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 java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.transform.config.TransformConfig;
import org.alfresco.transform.config.TransformOption;
import org.alfresco.transform.config.Transformer;
import org.alfresco.transform.config.SupportedSourceAndTarget;
import org.alfresco.transform.config.TransformStep;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
public class TransformConfigReaderYamlTest
{
@Test
public void testEmptyRoutesFile() throws Exception
{
final Resource resource = new ClassPathResource("config/sample3.yaml");
final TransformConfigReader loader = TransformConfigReaderFactory.create(resource);
TransformConfig transformConfig = loader.load();
final List<Transformer> transformers = transformConfig.getTransformers();
assertNotNull(transformers);
assertEquals(Collections.emptyList(), transformers);
}
@Test
public void testMixedRoutesFile() throws Exception
{
final List<Transformer> expected = prepareSample4();
Map<String, Set<TransformOption>> expectedOptions = TransformConfigReaderJsonTest.prepareSample5Options();
final Resource resource = new ClassPathResource("config/sample4.yaml");
final TransformConfigReader loader = TransformConfigReaderFactory.create(resource);
TransformConfig transformConfig = loader.load();
final List<Transformer> transformers = transformConfig.getTransformers();
Map<String, Set<TransformOption>> transformOptions = transformConfig.getTransformOptions();
assertNotNull(transformers);
assertEquals(expected.size(), transformers.size());
assertTrue(expected.containsAll(transformers));
assertEquals(expectedOptions, transformOptions);
}
private List<Transformer> prepareSample4()
{
var result = new ArrayList<Transformer>();
result.add(Transformer.builder()
.withTransformerName("CORE_AIO")
.withSupportedSourceAndTargetList(ImmutableSet.of(
SupportedSourceAndTarget.builder()
.withSourceMediaType("image/gif")
.withTargetMediaType("image/gif")
.build()
))
.withTransformOptions(ImmutableSet.of("imageMagickOptions"))
.build());
result.add(Transformer.builder()
.withTransformerName("IMAGEMAGICK")
.withSupportedSourceAndTargetList(ImmutableSet.of(
SupportedSourceAndTarget.builder()
.withSourceMediaType("image/gif")
.withTargetMediaType("image/gif")
.build()
))
.withTransformOptions(ImmutableSet.of("imageMagickOptions"))
.build());
result.add(Transformer.builder()
.withTransformerName("CORE_AIO")
.withSupportedSourceAndTargetList(ImmutableSet.of(
SupportedSourceAndTarget.builder()
.withSourceMediaType("application/msword")
.withTargetMediaType("application/pdf")
.withMaxSourceSizeBytes(18874368L)
.build()
))
.build());
result.add(Transformer.builder()
.withTransformerName("PDF_RENDERER")
.withSupportedSourceAndTargetList(ImmutableSet.of(
SupportedSourceAndTarget.builder()
.withSourceMediaType("application/vnd.ms-powerpoint")
.withTargetMediaType("application/pdf")
.withPriority(55)
.withMaxSourceSizeBytes(50331648L)
.build()
))
.build());
result.add(Transformer.builder()
.withTransformerName("CORE_AIO")
.withSupportedSourceAndTargetList(ImmutableSet.of(
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/plain")
.withTargetMediaType("text/plain")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/mediawiki")
.withTargetMediaType("text/plain")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/css")
.withTargetMediaType("text/plain")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/csv")
.withTargetMediaType("text/plain")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/xml")
.withTargetMediaType("text/plain")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/html")
.withTargetMediaType("text/plain")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("application/x-javascript")
.withTargetMediaType("text/plain")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("application/dita+xml")
.withTargetMediaType("text/plain")
.build()
))
.withTransformOptions(ImmutableSet.of("stringOptions"))
.build());
result.add(Transformer.builder()
.withTransformerName("officeToImageViaPdf")
.withTransformerPipeline(ImmutableList.of(
new TransformStep("libreoffice", "application/pdf"),
new TransformStep("pdfToImageViaPng", null)
))
.withTransformOptions(ImmutableSet.of(
"pdfRendererOptions",
"imageMagickOptions"
))
.build());
result.add(Transformer.builder()
.withTransformerName("textToImageViaPdf")
.withTransformerPipeline(ImmutableList.of(
new TransformStep("libreoffice", "application/pdf"),
new TransformStep("pdfToImageViaPng", null)
))
.withTransformOptions(ImmutableSet.of(
"pdfRendererOptions",
"imageMagickOptions"
))
.withSupportedSourceAndTargetList(ImmutableSet.of(
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/plain")
.withTargetMediaType("image/gif")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/plain")
.withTargetMediaType("image/jpeg")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/plain")
.withTargetMediaType("image/tiff")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/plain")
.withTargetMediaType("image/png")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/csv")
.withTargetMediaType("image/gif")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/csv")
.withTargetMediaType("image/jpeg")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/csv")
.withTargetMediaType("image/tiff")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/csv")
.withTargetMediaType("image/png")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/xml")
.withTargetMediaType("image/gif")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/xml")
.withTargetMediaType("image/jpeg")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/xml")
.withTargetMediaType("image/tiff")
.build(),
SupportedSourceAndTarget.builder()
.withSourceMediaType("text/xml")
.withTargetMediaType("image/png")
.build()
))
.withTransformOptions(ImmutableSet.of(
"pdfRendererOptions",
"imageMagickOptions"
))
.build());
return result;
}
}

View File

@@ -30,11 +30,13 @@ import com.google.common.collect.ImmutableMap;
import org.alfresco.transform.common.TransformException;
import org.junit.jupiter.api.Test;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import static java.util.Arrays.asList;
import static java.util.Collections.emptySet;
import static org.alfresco.transform.common.RequestParamMap.SOURCE_ENCODING;
import static org.alfresco.transform.common.RequestParamMap.TIMEOUT;
import static org.alfresco.transform.registry.TransformRegistryHelper.retrieveTransformListBySize;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -192,7 +194,21 @@ public class TransformRegistryHelperTest
assertThrows(TransformException.class, () ->
{
retrieveTransformListBySize(data, "text/plain", null, ImmutableMap.of(TIMEOUT, "1234"), null);
retrieveTransformListBySize(data, "text/plain", null,
new HashMap<>(ImmutableMap.of(TIMEOUT, "1234")), null);
});
}
@Test
public void filterSourceEncodingTest()
{
// Almost identical to buildTransformListTargetMimeTypeNullErrorTest
TransformCache data = new TransformCache();
assertThrows(TransformException.class, () ->
{
retrieveTransformListBySize(data, "text/plain", null,
new HashMap<>(ImmutableMap.of(SOURCE_ENCODING, "UTF-8")), null);
});
}
}

View File

@@ -0,0 +1,3 @@
{
"transformers":[]
}

View File

@@ -0,0 +1,92 @@
{
"transformers": [
{
"transformerName": "CORE_AIO",
"supportedSourceAndTargetList": [
{"sourceMediaType": "image/gif", "targetMediaType": "image/gif" }
],
"transformOptions": [
"imageMagickOptions"
]
},
{
"transformerName": "IMAGEMAGICK",
"supportedSourceAndTargetList": [
{"sourceMediaType": "image/gif", "targetMediaType": "image/gif" }
],
"transformOptions": [
"imageMagickOptions"
]
},
{
"transformerName": "CORE_AIO",
"supportedSourceAndTargetList": [
{"sourceMediaType": "application/msword", "maxSourceSizeBytes": 18874368, "targetMediaType": "application/pdf" }
]
},
{
"transformerName": "PDF_RENDERER",
"supportedSourceAndTargetList": [
{"sourceMediaType": "application/vnd.ms-powerpoint", "maxSourceSizeBytes": 50331648, "priority": 55, "targetMediaType": "application/pdf" }
],
"transformOptions": [
]
},
{
"transformerName": "CORE_AIO",
"supportedSourceAndTargetList": [
{"sourceMediaType": "text/plain", "targetMediaType": "text/plain" },
{"sourceMediaType": "text/mediawiki", "targetMediaType": "text/plain" },
{"sourceMediaType": "text/css", "targetMediaType": "text/plain" },
{"sourceMediaType": "text/csv", "targetMediaType": "text/plain" },
{"sourceMediaType": "text/xml", "targetMediaType": "text/plain" },
{"sourceMediaType": "text/html", "targetMediaType": "text/plain" },
{"sourceMediaType": "application/x-javascript", "targetMediaType": "text/plain" },
{"sourceMediaType": "application/dita+xml", "targetMediaType": "text/plain" }
],
"transformOptions": [
"stringOptions"
]
},
{
"transformerName": "officeToImageViaPdf",
"transformerPipeline" : [
{"transformerName": "libreoffice", "targetMediaType": "application/pdf"},
{"transformerName": "pdfToImageViaPng"}
],
"supportedSourceAndTargetList": [
],
"transformOptions": [
"pdfRendererOptions",
"imageMagickOptions"
]
},
{
"transformerName": "textToImageViaPdf",
"transformerPipeline" : [
{"transformerName": "libreoffice", "targetMediaType": "application/pdf"},
{"transformerName": "pdfToImageViaPng"}
],
"supportedSourceAndTargetList": [
{"sourceMediaType": "text/plain", "targetMediaType": "image/gif" },
{"sourceMediaType": "text/plain", "targetMediaType": "image/jpeg"},
{"sourceMediaType": "text/plain", "targetMediaType": "image/tiff"},
{"sourceMediaType": "text/plain", "targetMediaType": "image/png" },
{"sourceMediaType": "text/csv", "targetMediaType": "image/gif" },
{"sourceMediaType": "text/csv", "targetMediaType": "image/jpeg"},
{"sourceMediaType": "text/csv", "targetMediaType": "image/tiff"},
{"sourceMediaType": "text/csv", "targetMediaType": "image/png" },
{"sourceMediaType": "text/xml", "targetMediaType": "image/gif" },
{"sourceMediaType": "text/xml", "targetMediaType": "image/jpeg"},
{"sourceMediaType": "text/xml", "targetMediaType": "image/tiff"},
{"sourceMediaType": "text/xml", "targetMediaType": "image/png" }
],
"transformOptions": [
"pdfRendererOptions",
"imageMagickOptions"
]
}
]
}

View File

@@ -0,0 +1,2 @@
---
transformers:

View File

@@ -0,0 +1,130 @@
---
transformOptions:
imageMagickOptions:
- value:
name: alphaRemove
- value:
name: autoOrient
- value:
name: startPage
- value:
name: endPage
- group:
transformOptions:
- value:
name: cropGravity
- value:
name: cropWidth
- value:
name: cropHeight
- value:
name: cropPercentage
- value:
name: cropXOffset
- value:
name: cropYOffset
- group:
transformOptions:
- value:
name: thumbnail
- value:
name: resizeHeight
- value:
name: resizeWidth
- value:
name: resizePercentage
- value:
name: allowEnlargement
- value:
name: maintainAspectRatio
transformers:
- transformerName: CORE_AIO
supportedSourceAndTargetList:
- sourceMediaType: image/gif
targetMediaType: image/gif
transformOptions:
- imageMagickOptions
- transformerName: IMAGEMAGICK
supportedSourceAndTargetList:
- sourceMediaType: image/gif
targetMediaType: image/gif
transformOptions:
- imageMagickOptions
- transformerName: PDF_RENDERER
supportedSourceAndTargetList:
- sourceMediaType: application/vnd.ms-powerpoint
targetMediaType: application/pdf
priority: 55
maxSourceSizeBytes: 50331648
transformOptions: []
- transformerName: CORE_AIO
supportedSourceAndTargetList:
- sourceMediaType: application/msword
targetMediaType: application/pdf
maxSourceSizeBytes: 18874368
- transformerName: CORE_AIO
supportedSourceAndTargetList:
- sourceMediaType: text/plain
targetMediaType: text/plain
- sourceMediaType: text/mediawiki
targetMediaType: text/plain
- sourceMediaType: text/css
targetMediaType: text/plain
- sourceMediaType: text/csv
targetMediaType: text/plain
- sourceMediaType: text/xml
targetMediaType: text/plain
- sourceMediaType: text/html
targetMediaType: text/plain
- sourceMediaType: application/x-javascript
targetMediaType: text/plain
- sourceMediaType: application/dita+xml
targetMediaType: text/plain
transformOptions:
- stringOptions
- transformerName: officeToImageViaPdf
transformerPipeline:
- transformerName: libreoffice
targetMediaType: application/pdf
- transformerName: pdfToImageViaPng
transformOptions:
- pdfRendererOptions
- imageMagickOptions
- transformerName: textToImageViaPdf
transformerPipeline:
- transformerName: libreoffice
targetMediaType: application/pdf
- transformerName: pdfToImageViaPng
supportedSourceAndTargetList:
- sourceMediaType: text/plain
targetMediaType: image/gif
- sourceMediaType: text/plain
targetMediaType: image/jpeg
- sourceMediaType: text/plain
targetMediaType: image/tiff
- sourceMediaType: text/plain
targetMediaType: image/png
- sourceMediaType: text/csv
targetMediaType: image/gif
- sourceMediaType: text/csv
targetMediaType: image/jpeg
- sourceMediaType: text/csv
targetMediaType: image/tiff
- sourceMediaType: text/csv
targetMediaType: image/png
- sourceMediaType: text/xml
targetMediaType: image/gif
- sourceMediaType: text/xml
targetMediaType: image/jpeg
- sourceMediaType: text/xml
targetMediaType: image/tiff
- sourceMediaType: text/xml
targetMediaType: image/png
transformOptions:
- pdfRendererOptions
- imageMagickOptions

View File

@@ -0,0 +1,37 @@
{
"transformOptions": {
"imageMagickOptions": [
{"value": {"name": "alphaRemove"}},
{"value": {"name": "autoOrient"}},
{"value": {"name": "startPage"}},
{"value": {"name": "endPage"}},
{"group": {"transformOptions": [
{"value": {"name": "cropGravity"}},
{"value": {"name": "cropWidth"}},
{"value": {"name": "cropHeight"}},
{"value": {"name": "cropPercentage"}},
{"value": {"name": "cropXOffset"}},
{"value": {"name": "cropYOffset"}}
]}},
{"group": {"transformOptions": [
{"value": {"name": "thumbnail"}},
{"value": {"name": "resizeHeight"}},
{"value": {"name": "resizeWidth"}},
{"value": {"name": "resizePercentage"}},
{"value": {"name": "allowEnlargement"}},
{"value": {"name": "maintainAspectRatio"}}
]}}
]
},
"transformers": [
{
"transformerName": "CORE_AIO",
"supportedSourceAndTargetList": [
{"sourceMediaType": "image/gif", "targetMediaType": "image/gif" }
],
"transformOptions": [
"imageMagickOptions"
]
}
]
}