From 3225f63f9415f6165c5f7b3dcf08e70ef1498cfb Mon Sep 17 00:00:00 2001 From: CezarLeahu <35226487+CezarLeahu@users.noreply.github.com> Date: Thu, 12 Sep 2019 23:49:17 +0300 Subject: [PATCH] REPO-4639 Content conversion failed using Tika (#587) The Tika T-Engine was not being called by the Transform Service or Local transforms, because the sub-transform name was required. Moved common classes (with repo) to alfresco-transform-model so that it can be used by the T-Engines to work out which sub transformer to use. InT also performed a refactor on these classes (alfresco-transform-model 1.0.2.7). Also includes changes to legacy transformers so that they don't pass the sub transformer name any more. --- .travis.yml | 20 +- pom.xml | 14 +- .../transform/ArchiveContentTransformer.java | 14 +- .../content/transform/LocalTransformImpl.java | 8 +- .../LocalTransformServiceRegistry.java | 40 +- .../transform/MailContentTransformer.java | 6 - .../transform/PdfBoxContentTransformer.java | 13 +- .../transform/PoiContentTransformer.java | 6 - .../transform/PoiHssfContentTransformer.java | 6 - .../transform/PoiOOXMLContentTransformer.java | 6 - .../TextMiningContentTransformer.java | 6 - .../transform/TikaAutoContentTransformer.java | 6 - .../TikaPoweredContentTransformer.java | 9 +- ...ikaSpringConfiguredContentTransformer.java | 6 - .../AbstractTransformServiceRegistry.java | 9 +- .../LegacyTransformServiceRegistry.java | 4 +- .../RenditionDefinitionRegistry2Impl.java | 4 +- .../SwitchingTransformServiceRegistry.java | 8 +- .../repo/thumbnail/ThumbnailRegistry.java | 4 +- .../client/model/config/ChildTransformer.java | 66 -- .../client/model/config/CombinedConfig.java | 440 --------- .../config/TransformServiceRegistry.java | 67 -- .../config/TransformServiceRegistryImpl.java | 459 --------- .../client/registry/CombinedConfig.java | 241 +++++ .../TransformServiceRegistryImpl.java | 169 ++++ .../java/org/alfresco/AllUnitTestsSuite.java | 2 +- .../org/alfresco/AppContext06TestSuite.java | 2 +- .../AbstractRenditionIntegrationTest.java | 2 +- .../repo/rendition2/LocalRenditionTest.java | 2 +- ...ansformServiceRegistryIntegrationTest.java | 4 +- .../rendition2/RenditionService2Test.java | 2 +- .../client/model/config/TransformBuilder.java | 54 -- .../TransformServiceRegistryConfigTest.java | 896 ------------------ ...calTransformServiceRegistryConfigTest.java | 126 ++- .../TransformServiceRegistryConfigTest.java | 287 ++++++ 35 files changed, 848 insertions(+), 2160 deletions(-) delete mode 100644 src/main/java/org/alfresco/transform/client/model/config/ChildTransformer.java delete mode 100644 src/main/java/org/alfresco/transform/client/model/config/CombinedConfig.java delete mode 100644 src/main/java/org/alfresco/transform/client/model/config/TransformServiceRegistry.java delete mode 100644 src/main/java/org/alfresco/transform/client/model/config/TransformServiceRegistryImpl.java create mode 100644 src/main/java/org/alfresco/transform/client/registry/CombinedConfig.java create mode 100644 src/main/java/org/alfresco/transform/client/registry/TransformServiceRegistryImpl.java delete mode 100644 src/test/java/org/alfresco/transform/client/model/config/TransformBuilder.java delete mode 100644 src/test/java/org/alfresco/transform/client/model/config/TransformServiceRegistryConfigTest.java rename src/test/java/org/alfresco/transform/client/{model/config => registry}/LocalTransformServiceRegistryConfigTest.java (77%) create mode 100644 src/test/java/org/alfresco/transform/client/registry/TransformServiceRegistryConfigTest.java diff --git a/.travis.yml b/.travis.yml index 6b540f3676..4ef6ab6afe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -64,11 +64,11 @@ jobs: before_install: - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.4 postgres -c 'max_connections=300' - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8 - - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-pdf-renderer:2.1.0-EA4 - - docker run -d -p 8091:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-imagemagick:2.1.0-EA4 - - docker run -d -p 8092:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-libreoffice:2.1.0-EA4 - - docker run -d -p 8093:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-tika:2.1.0-EA4 - - docker run -d -p 8094:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-misc:2.1.0-EA4 + - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-pdf-renderer:2.1.0-DEV1 + - docker run -d -p 8091:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-imagemagick:2.1.0-DEV1 + - docker run -d -p 8092:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-libreoffice:2.1.0-DEV1 + - docker run -d -p 8093:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-tika:2.1.0-DEV1 + - docker run -d -p 8094:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-misc:2.1.0-DEV1 script: travis_wait 20 mvn test -B -Dtest=AppContext06TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco -Dalfresco-pdf-renderer.url=http://localhost:8090/ -Djodconverter.url=http://localhost:8092/ -Dimg.url=http://localhost:8091/ -Dtika.url=http://localhost:8093/ -Dtransform.misc.url=http://localhost:8094/ - name: "AppContextExtraTestSuite" before_install: @@ -79,11 +79,11 @@ jobs: before_install: - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.4 postgres -c 'max_connections=300' - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8 - - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-pdf-renderer:2.1.0-EA4 - - docker run -d -p 8091:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-imagemagick:2.1.0-EA4 - - docker run -d -p 8092:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-libreoffice:2.1.0-EA4 - - docker run -d -p 8093:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-tika:2.1.0-EA4 - - docker run -d -p 8094:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-misc:2.1.0-EA4 + - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-pdf-renderer:2.1.0-DEV1 + - docker run -d -p 8091:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-imagemagick:2.1.0-DEV1 + - docker run -d -p 8092:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-libreoffice:2.1.0-DEV1 + - docker run -d -p 8093:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-tika:2.1.0-DEV1 + - docker run -d -p 8094:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-misc:2.1.0-DEV1 script: travis_wait 20 mvn test -B -Dtest=MiscContextTestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco -Dalfresco-pdf-renderer.url=http://localhost:8090/ -Djodconverter.url=http://localhost:8092/ -Dimg.url=http://localhost:8091/ -Dtika.url=http://localhost:8093/ -Dtransform.misc.url=http://localhost:8094/ - name: "MySQL tests" before_install: diff --git a/pom.xml b/pom.xml index ef32a4b694..55b49fea82 100644 --- a/pom.xml +++ b/pom.xml @@ -40,11 +40,11 @@ 6.2 7.21 6.1 - 8.48 + 8.49 7.1 1.1 1.0.11 - + 1.0.2.7 5.1.8.RELEASE 4.5.9 @@ -66,7 +66,6 @@ 3.3.2 2.9.9 2.9.9.3 - 1.0.2.5 @@ -194,7 +193,7 @@ org.apache.commons commons-compress - 1.18 + 1.19 org.apache.commons @@ -1052,6 +1051,13 @@ 4.12 test + + org.alfresco + alfresco-transform-model + ${dependency.transform.model.version} + tests + test + org.alfresco alfresco-core diff --git a/src/main/java/org/alfresco/repo/content/transform/ArchiveContentTransformer.java b/src/main/java/org/alfresco/repo/content/transform/ArchiveContentTransformer.java index cfa5c27fc3..044fba82a2 100644 --- a/src/main/java/org/alfresco/repo/content/transform/ArchiveContentTransformer.java +++ b/src/main/java/org/alfresco/repo/content/transform/ArchiveContentTransformer.java @@ -141,12 +141,6 @@ public class ArchiveContentTransformer extends TikaPoweredContentTransformer return context; } - @Override - protected String getTransform() - { - return "Archive"; - } - @Override protected void transformRemote(RemoteTransformerClient remoteTransformerClient, ContentReader reader, ContentWriter writer, TransformationOptions options, @@ -154,7 +148,6 @@ public class ArchiveContentTransformer extends TikaPoweredContentTransformer String sourceExtension, String targetExtension, String targetEncoding) throws Exception { - String transform = getTransform(); long timeoutMs = options.getTimeoutMs(); boolean recurse = includeContents; if(options.getIncludeEmbedded() != null) @@ -162,7 +155,10 @@ public class ArchiveContentTransformer extends TikaPoweredContentTransformer recurse = options.getIncludeEmbedded(); } remoteTransformerClient.request(reader, writer, sourceMimetype, sourceExtension, targetExtension, - timeoutMs, logger, "transform", transform, "includeContents", Boolean.toString(recurse), - "targetMimetype", targetMimetype, "targetEncoding", targetEncoding); + timeoutMs, logger, + "includeContents", Boolean.toString(recurse), + "sourceMimetype", sourceMimetype, + "targetMimetype", targetMimetype, + "targetEncoding", targetEncoding); } } diff --git a/src/main/java/org/alfresco/repo/content/transform/LocalTransformImpl.java b/src/main/java/org/alfresco/repo/content/transform/LocalTransformImpl.java index 3611fe860b..26a75d7c5e 100644 --- a/src/main/java/org/alfresco/repo/content/transform/LocalTransformImpl.java +++ b/src/main/java/org/alfresco/repo/content/transform/LocalTransformImpl.java @@ -143,11 +143,11 @@ public class LocalTransformImpl extends AbstractLocalTransform String sourceExtension, String targetExtension, String renditionName, NodeRef sourceNodeRef) throws Exception { - // At some point in the future, we may decide to only pass the sourceEncoding and other dynamic values like - // it if they were supplied in the rendition definition without a value. The sourceEncoding value is also - // supplied in the TransformRequest (message to the T-Router). + // Only pass the sourceEncoding and other dynamic values like it if they were supplied in the rendition + // definition without a value. The sourceEncoding value is also supplied in the RenditionEventProducer in + // the message to the T-Router. transformOptions = new HashMap<>(transformOptions); - if (transformOptions.get(SOURCE_ENCODING) == null) + if (transformOptions.containsKey(SOURCE_ENCODING) && transformOptions.get(SOURCE_ENCODING) == null) { String sourceEncoding = reader.getEncoding(); transformOptions.put(SOURCE_ENCODING, sourceEncoding); diff --git a/src/main/java/org/alfresco/repo/content/transform/LocalTransformServiceRegistry.java b/src/main/java/org/alfresco/repo/content/transform/LocalTransformServiceRegistry.java index e0fd49a52e..4f36af7255 100644 --- a/src/main/java/org/alfresco/repo/content/transform/LocalTransformServiceRegistry.java +++ b/src/main/java/org/alfresco/repo/content/transform/LocalTransformServiceRegistry.java @@ -25,20 +25,6 @@ */ package org.alfresco.repo.content.transform; -import org.alfresco.service.cmr.repository.ContentReader; -import org.alfresco.service.cmr.repository.ContentWriter; -import org.alfresco.service.cmr.repository.MimetypeService; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.transform.client.model.config.CombinedConfig; -import org.alfresco.transform.client.model.config.InlineTransformer; -import org.alfresco.transform.client.model.config.TransformServiceRegistry; -import org.alfresco.transform.client.model.config.TransformServiceRegistryImpl; -import org.alfresco.transform.client.model.config.TransformStep; -import org.alfresco.util.PropertyCheck; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.InitializingBean; - import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -48,6 +34,21 @@ import java.util.Map; import java.util.Properties; import java.util.Set; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.MimetypeService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.transform.client.registry.CombinedConfig; +import org.alfresco.transform.client.model.config.TransformOption; +import org.alfresco.transform.client.registry.TransformServiceRegistryImpl; +import org.alfresco.transform.client.model.config.TransformStep; +import org.alfresco.transform.client.model.config.Transformer; +import org.alfresco.transform.client.registry.TransformServiceRegistry; +import org.alfresco.util.PropertyCheck; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; + /** * Implements {@link TransformServiceRegistry} providing a mechanism of validating if a local transformation * (based on {@link LocalTransform} request is supported. It also extends this interface to provide a @@ -156,7 +157,8 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl } @Override - protected void register(InlineTransformer transformer, String baseUrl, String readFrom) + public void register(Transformer transformer, Map> transformOptions, + String baseUrl, String readFrom) { try { @@ -242,7 +244,7 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl } } localTransforms.put(name, localTransform); - super.register(transformer, baseUrl, readFrom); + super.register(transformer, transformOptions, baseUrl, readFrom); } catch (IllegalArgumentException e) { @@ -394,7 +396,7 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl } @Override - public long getMaxSize(String sourceMimetype, String targetMimetype, Map options, String renditionName) + public long findMaxSize(String sourceMimetype, String targetMimetype, Map options, String renditionName) { // This message is not logged if placed in afterPropertiesSet if (getFirstTime()) @@ -404,7 +406,7 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl } return enabled - ? super.getMaxSize(sourceMimetype, targetMimetype, options, renditionName) + ? super.findMaxSize(sourceMimetype, targetMimetype, options, renditionName) : 0; } @@ -422,7 +424,7 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl public LocalTransform getLocalTransform(Map actualOptions, String renditionName, String sourceMimetype, String targetMimetype, long sourceSizeInBytes) { - String name = getTransformerName(sourceMimetype, sourceSizeInBytes, targetMimetype, actualOptions, renditionName); + String name = findTransformerName(sourceMimetype, sourceSizeInBytes, targetMimetype, actualOptions, renditionName); LocalData data = getData(); Map localTransforms = data.localTransforms; return localTransforms.get(name); diff --git a/src/main/java/org/alfresco/repo/content/transform/MailContentTransformer.java b/src/main/java/org/alfresco/repo/content/transform/MailContentTransformer.java index 9caffe2a5c..2e28422367 100644 --- a/src/main/java/org/alfresco/repo/content/transform/MailContentTransformer.java +++ b/src/main/java/org/alfresco/repo/content/transform/MailContentTransformer.java @@ -51,10 +51,4 @@ public class MailContentTransformer extends TikaPoweredContentTransformer protected Parser getParser() { return new OfficeParser(); } - - @Override - protected String getTransform() - { - return "OutlookMsg"; - } } diff --git a/src/main/java/org/alfresco/repo/content/transform/PdfBoxContentTransformer.java b/src/main/java/org/alfresco/repo/content/transform/PdfBoxContentTransformer.java index 25158a36d7..239884290c 100644 --- a/src/main/java/org/alfresco/repo/content/transform/PdfBoxContentTransformer.java +++ b/src/main/java/org/alfresco/repo/content/transform/PdfBoxContentTransformer.java @@ -98,13 +98,6 @@ public class PdfBoxContentTransformer extends TikaPoweredContentTransformer return context; } - @Override - protected String getTransform() - { - return "PdfBox"; - } - - @Override protected void transformRemote(RemoteTransformerClient remoteTransformerClient, ContentReader reader, ContentWriter writer, TransformationOptions options, @@ -112,8 +105,6 @@ public class PdfBoxContentTransformer extends TikaPoweredContentTransformer String sourceExtension, String targetExtension, String targetEncoding) throws Exception { - - String transform = getTransform(); long timeoutMs = options.getTimeoutMs(); String notExtractBookmarksText = null; @@ -124,9 +115,9 @@ public class PdfBoxContentTransformer extends TikaPoweredContentTransformer remoteTransformerClient.request(reader, writer, sourceMimetype, sourceExtension, targetExtension, timeoutMs, logger, - "transform", transform, "notExtractBookmarksText", notExtractBookmarksText, - "targetMimetype", targetMimetype, + "sourceMimetype", sourceMimetype, + "targetMimetype", targetMimetype, "targetEncoding", targetEncoding); } } diff --git a/src/main/java/org/alfresco/repo/content/transform/PoiContentTransformer.java b/src/main/java/org/alfresco/repo/content/transform/PoiContentTransformer.java index 9b4cc4897a..62e8d70e30 100644 --- a/src/main/java/org/alfresco/repo/content/transform/PoiContentTransformer.java +++ b/src/main/java/org/alfresco/repo/content/transform/PoiContentTransformer.java @@ -76,10 +76,4 @@ public class PoiContentTransformer extends TikaPoweredContentTransformer protected Parser getParser() { return new OfficeParser(); } - - @Override - protected String getTransform() - { - return "Office"; - } } diff --git a/src/main/java/org/alfresco/repo/content/transform/PoiHssfContentTransformer.java b/src/main/java/org/alfresco/repo/content/transform/PoiHssfContentTransformer.java index aefceef32a..f8ca2d0b88 100644 --- a/src/main/java/org/alfresco/repo/content/transform/PoiHssfContentTransformer.java +++ b/src/main/java/org/alfresco/repo/content/transform/PoiHssfContentTransformer.java @@ -211,10 +211,4 @@ public class PoiHssfContentTransformer extends TikaPoweredContentTransformer } } } - - @Override - protected String getTransform() - { - return "Poi"; - } } diff --git a/src/main/java/org/alfresco/repo/content/transform/PoiOOXMLContentTransformer.java b/src/main/java/org/alfresco/repo/content/transform/PoiOOXMLContentTransformer.java index fb1e076a9c..38f3a3e4c3 100644 --- a/src/main/java/org/alfresco/repo/content/transform/PoiOOXMLContentTransformer.java +++ b/src/main/java/org/alfresco/repo/content/transform/PoiOOXMLContentTransformer.java @@ -65,10 +65,4 @@ public class PoiOOXMLContentTransformer extends TikaPoweredContentTransformer protected Parser getParser() { return new OOXMLParser(); } - - @Override - protected String getTransform() - { - return "OOXML"; - } } diff --git a/src/main/java/org/alfresco/repo/content/transform/TextMiningContentTransformer.java b/src/main/java/org/alfresco/repo/content/transform/TextMiningContentTransformer.java index 0b40d1ec80..d2505fff14 100644 --- a/src/main/java/org/alfresco/repo/content/transform/TextMiningContentTransformer.java +++ b/src/main/java/org/alfresco/repo/content/transform/TextMiningContentTransformer.java @@ -51,10 +51,4 @@ public class TextMiningContentTransformer extends TikaPoweredContentTransformer protected Parser getParser() { return new OfficeParser(); } - - @Override - protected String getTransform() - { - return "TextMining"; - } } diff --git a/src/main/java/org/alfresco/repo/content/transform/TikaAutoContentTransformer.java b/src/main/java/org/alfresco/repo/content/transform/TikaAutoContentTransformer.java index 39370059b3..3b52f097bb 100644 --- a/src/main/java/org/alfresco/repo/content/transform/TikaAutoContentTransformer.java +++ b/src/main/java/org/alfresco/repo/content/transform/TikaAutoContentTransformer.java @@ -131,10 +131,4 @@ public class TikaAutoContentTransformer extends TikaPoweredContentTransformer { return parser; } - - @Override - protected String getTransform() - { - return "TikaAuto"; - } } diff --git a/src/main/java/org/alfresco/repo/content/transform/TikaPoweredContentTransformer.java b/src/main/java/org/alfresco/repo/content/transform/TikaPoweredContentTransformer.java index 20f80ad286..481a8297a9 100644 --- a/src/main/java/org/alfresco/repo/content/transform/TikaPoweredContentTransformer.java +++ b/src/main/java/org/alfresco/repo/content/transform/TikaPoweredContentTransformer.java @@ -292,18 +292,15 @@ public abstract class TikaPoweredContentTransformer extends AbstractRemoteConten String sourceExtension, String targetExtension, String targetEncoding) throws Exception { - String transform = getTransform(); long timeoutMs = options.getTimeoutMs(); remoteTransformerClient.request(reader, writer, sourceMimetype, sourceExtension, targetExtension, - timeoutMs, logger, - "transform", transform, - "targetMimetype", targetMimetype, + timeoutMs, logger, + "sourceMimetype", sourceMimetype, + "targetMimetype", targetMimetype, "targetEncoding", targetEncoding); } - protected abstract String getTransform(); - private String calculateMemoryAndTimeUsage(ContentReader reader, long startTime) { long endTime = System.currentTimeMillis(); diff --git a/src/main/java/org/alfresco/repo/content/transform/TikaSpringConfiguredContentTransformer.java b/src/main/java/org/alfresco/repo/content/transform/TikaSpringConfiguredContentTransformer.java index 5aded4859f..63f9bbee1c 100644 --- a/src/main/java/org/alfresco/repo/content/transform/TikaSpringConfiguredContentTransformer.java +++ b/src/main/java/org/alfresco/repo/content/transform/TikaSpringConfiguredContentTransformer.java @@ -107,10 +107,4 @@ public class TikaSpringConfiguredContentTransformer extends TikaPoweredContentTr throw new AlfrescoRuntimeException("Unable to create specified Parser", e); } } - - @Override - protected String getTransform() - { - return "tikaspring"; // This transformer is no longer created by Spring, so is not supported by the Tika transformer image - } } diff --git a/src/main/java/org/alfresco/repo/rendition2/AbstractTransformServiceRegistry.java b/src/main/java/org/alfresco/repo/rendition2/AbstractTransformServiceRegistry.java index 4a7ae5a5f4..6a092d82c9 100644 --- a/src/main/java/org/alfresco/repo/rendition2/AbstractTransformServiceRegistry.java +++ b/src/main/java/org/alfresco/repo/rendition2/AbstractTransformServiceRegistry.java @@ -25,10 +25,10 @@ */ package org.alfresco.repo.rendition2; -import org.alfresco.transform.client.model.config.TransformServiceRegistry; - import java.util.Map; +import org.alfresco.transform.client.registry.TransformServiceRegistry; + /** * Contains common code used in TransformServiceRegistries. * @@ -37,9 +37,8 @@ import java.util.Map; public abstract class AbstractTransformServiceRegistry implements TransformServiceRegistry { @Override - public boolean isSupported(String sourceMimetype, long size, String targetMimetype, Map options, String renditionName) + public String findTransformerName(String sourceMimetype, long sourceSizeInBytes, String targetMimetype, Map actualOptions, String renditionName) { - long maxSize = getMaxSize(sourceMimetype, targetMimetype, options, renditionName); - return maxSize != 0 && (maxSize == -1L || maxSize >= size); + throw new UnsupportedOperationException("AbstractTransformServiceRegistry.findTransformerName(...) is not supported. Only supported in "); } } diff --git a/src/main/java/org/alfresco/repo/rendition2/LegacyTransformServiceRegistry.java b/src/main/java/org/alfresco/repo/rendition2/LegacyTransformServiceRegistry.java index 4300f75eb1..5792e34ff9 100644 --- a/src/main/java/org/alfresco/repo/rendition2/LegacyTransformServiceRegistry.java +++ b/src/main/java/org/alfresco/repo/rendition2/LegacyTransformServiceRegistry.java @@ -28,7 +28,7 @@ package org.alfresco.repo.rendition2; import org.alfresco.repo.content.transform.TransformerDebug; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.TransformationOptions; -import org.alfresco.transform.client.model.config.TransformServiceRegistry; +import org.alfresco.transform.client.registry.TransformServiceRegistry; import org.alfresco.util.PropertyCheck; import org.springframework.beans.factory.InitializingBean; @@ -84,7 +84,7 @@ public class LegacyTransformServiceRegistry extends AbstractTransformServiceRegi } @Override - public long getMaxSize(String sourceMimetype, String targetMimetype, Map options, String renditionName) + public long findMaxSize(String sourceMimetype, String targetMimetype, Map options, String renditionName) { // This message is not logged if placed in afterPropertiesSet if (firstTime) diff --git a/src/main/java/org/alfresco/repo/rendition2/RenditionDefinitionRegistry2Impl.java b/src/main/java/org/alfresco/repo/rendition2/RenditionDefinitionRegistry2Impl.java index ddebd5a716..5e06567992 100644 --- a/src/main/java/org/alfresco/repo/rendition2/RenditionDefinitionRegistry2Impl.java +++ b/src/main/java/org/alfresco/repo/rendition2/RenditionDefinitionRegistry2Impl.java @@ -27,7 +27,7 @@ package org.alfresco.repo.rendition2; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import org.alfresco.transform.client.model.config.TransformServiceRegistry; +import org.alfresco.transform.client.registry.TransformServiceRegistry; import org.alfresco.util.ConfigFileFinder; import org.alfresco.util.ConfigScheduler; import org.alfresco.util.Pair; @@ -343,7 +343,7 @@ public class RenditionDefinitionRegistry2Impl implements RenditionDefinitionRegi String targetMimetype = renditionDefinition2.getTargetMimetype(); String renditionName = renditionDefinition2.getRenditionName(); Map options = renditionDefinition2.getTransformOptions(); - Long maxSize = transformServiceRegistry.getMaxSize(sourceMimetype, targetMimetype, options, renditionName); + Long maxSize = transformServiceRegistry.findMaxSize(sourceMimetype, targetMimetype, options, renditionName); if (maxSize != null) { String renditionNameMaxSizePair = entry.getKey(); diff --git a/src/main/java/org/alfresco/repo/rendition2/SwitchingTransformServiceRegistry.java b/src/main/java/org/alfresco/repo/rendition2/SwitchingTransformServiceRegistry.java index 66569a5d4c..96f935a992 100644 --- a/src/main/java/org/alfresco/repo/rendition2/SwitchingTransformServiceRegistry.java +++ b/src/main/java/org/alfresco/repo/rendition2/SwitchingTransformServiceRegistry.java @@ -25,7 +25,7 @@ */ package org.alfresco.repo.rendition2; -import org.alfresco.transform.client.model.config.TransformServiceRegistry; +import org.alfresco.transform.client.registry.TransformServiceRegistry; import java.util.Map; @@ -46,17 +46,17 @@ public class SwitchingTransformServiceRegistry extends AbstractTransformServiceR } @Override - public long getMaxSize(String sourceMimetype, String targetMimetype, Map options, String renditionName) + public long findMaxSize(String sourceMimetype, String targetMimetype, Map options, String renditionName) { long maxSize; - long primaryMaxSize = primary.getMaxSize(sourceMimetype, targetMimetype, options, renditionName); + long primaryMaxSize = primary.findMaxSize(sourceMimetype, targetMimetype, options, renditionName); if (primaryMaxSize == -1L) { maxSize = -1L; } else { - long secondaryMaxSize = secondary.getMaxSize(sourceMimetype, targetMimetype, options, renditionName); + long secondaryMaxSize = secondary.findMaxSize(sourceMimetype, targetMimetype, options, renditionName); maxSize = primaryMaxSize == 0 ? secondaryMaxSize : secondaryMaxSize == 0 diff --git a/src/main/java/org/alfresco/repo/thumbnail/ThumbnailRegistry.java b/src/main/java/org/alfresco/repo/thumbnail/ThumbnailRegistry.java index 1c712cf0ee..c21a65bb02 100644 --- a/src/main/java/org/alfresco/repo/thumbnail/ThumbnailRegistry.java +++ b/src/main/java/org/alfresco/repo/thumbnail/ThumbnailRegistry.java @@ -45,7 +45,7 @@ import org.alfresco.service.cmr.thumbnail.ThumbnailException; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.service.transaction.TransactionService; -import org.alfresco.transform.client.model.config.TransformServiceRegistry; +import org.alfresco.transform.client.registry.TransformServiceRegistry; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; @@ -457,7 +457,7 @@ public class ThumbnailRegistry implements ApplicationContextAware, ApplicationLi { Map options = renditionDefinition.getTransformOptions(); String renditionName = renditionDefinition.getRenditionName(); - maxSize = transformServiceRegistry.getMaxSize(sourceMimetype, targetMimetype, options, renditionName); + maxSize = transformServiceRegistry.findMaxSize(sourceMimetype, targetMimetype, options, renditionName); } else { diff --git a/src/main/java/org/alfresco/transform/client/model/config/ChildTransformer.java b/src/main/java/org/alfresco/transform/client/model/config/ChildTransformer.java deleted file mode 100644 index 382f7b3ddd..0000000000 --- a/src/main/java/org/alfresco/transform/client/model/config/ChildTransformer.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * #%L - * Alfresco Repository - * %% - * Copyright (C) 2005 - 2018 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 . - * #L% - */ -package org.alfresco.transform.client.model.config; - -/** - * Represents a single transformer in a pipeline of multiple transformers. A transformer's options may be optional or - * required in the containing transformer. Historically in ACS only options for the final transformer were provided. - */ -public class ChildTransformer -{ - private boolean required; - private InlineTransformer transformer; - - public ChildTransformer() - { - } - - public ChildTransformer(boolean required, InlineTransformer transformer) - { - this.required = required; - this.transformer = transformer; - } - - public boolean isRequired() - { - return required; - } - - public void setRequired(boolean required) - { - this.required = required; - } - - public InlineTransformer getTransformer() - { - return transformer; - } - - public void setTransformer(InlineTransformer transformer) - { - this.transformer = transformer; - } -} diff --git a/src/main/java/org/alfresco/transform/client/model/config/CombinedConfig.java b/src/main/java/org/alfresco/transform/client/model/config/CombinedConfig.java deleted file mode 100644 index dbeb3f5b79..0000000000 --- a/src/main/java/org/alfresco/transform/client/model/config/CombinedConfig.java +++ /dev/null @@ -1,440 +0,0 @@ -/* - * #%L - * Alfresco Repository - * %% - * Copyright (C) 2019 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 . - * #L% - */ -package org.alfresco.transform.client.model.config; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.util.ConfigFileFinder; -import org.apache.commons.logging.Log; -import org.apache.http.HttpEntity; -import org.apache.http.StatusLine; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.util.EntityUtils; - -import java.io.IOException; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * This class recreates the json format used in ACS 6.1 where we just had an array of transformers and each - * transformer has a list of node options. The idea of this code is that it replaces the references with the - * actual node options that have been separated out into their own section.

- * - * The T-Router and T-Engines return the format with the node option separated into their own section. Pipeline - * definitions used by the LocalTransformServiceRegistry may use node reference options defined in the json - * returned by T-Engines. with the actual definitions from the node options - * reference section. It also combines multiple json sources into a single jsonNode structure that can be parsed as - * before. - */ -public class CombinedConfig -{ - private static final String TRANSFORMER_NAME = "transformerName"; - private static final String TRANSFORM_CONFIG = "/transform/config"; - private static final String TRANSFORM_OPTIONS = "transformOptions"; - private static final String GROUP = "group"; - private static final String TRANSFORMERS = "transformers"; - - private final Log log; - private Map allTransformOptions = new HashMap<>(); - private List allTransforms = new ArrayList<>(); - private ObjectMapper jsonObjectMapper = new ObjectMapper(); - private ConfigFileFinder configFileFinder; - private int tEngineCount; - - static class TransformNodeAndItsOrigin - { - final ObjectNode node; - final String baseUrl; - final String readFrom; - - TransformNodeAndItsOrigin(ObjectNode node, String baseUrl, String readFrom) - { - this.node = node; - this.baseUrl = baseUrl; - this.readFrom = readFrom; - } - } - - static class TransformAndItsOrigin - { - final InlineTransformer transform; - final String baseUrl; - final String readFrom; - - TransformAndItsOrigin(InlineTransformer transform, String baseUrl, String readFrom) - { - this.transform = transform; - this.baseUrl = baseUrl; - this.readFrom = readFrom; - } - } - - public CombinedConfig(Log log) - { - this.log = log; - - configFileFinder = new ConfigFileFinder(jsonObjectMapper) - { - @Override - protected void readJson(JsonNode jsonNode, String readFromMessage, String baseUrl) throws IOException - { - JsonNode transformOptions = jsonNode.get(TRANSFORM_OPTIONS); - if (transformOptions != null && transformOptions.isObject()) - { - Iterator> iterator = transformOptions.fields(); - while (iterator.hasNext()) - { - Map.Entry entry = iterator.next(); - - JsonNode options = entry.getValue(); - if (options.isArray()) - { - String optionsName = entry.getKey(); - allTransformOptions.put(optionsName, (ArrayNode)options); - } - } - } - - JsonNode transformers = jsonNode.get(TRANSFORMERS); - if (transformers != null && transformers.isArray()) - { - for (JsonNode transformer : transformers) - { - if (transformer.isObject()) - { - allTransforms.add(new TransformNodeAndItsOrigin((ObjectNode)transformer, baseUrl, readFromMessage)); - } - } - } - } - }; - } - - public boolean addRemoteConfig(List urls, String remoteType) - { - boolean successReadingConfig = true; - for (String url : urls) - { - if (addRemoteConfig(url, remoteType)) - { - tEngineCount++ ; - } - else - { - successReadingConfig = false; - } - } - return successReadingConfig; - } - - private boolean addRemoteConfig(String baseUrl, String remoteType) - { - String url = baseUrl + TRANSFORM_CONFIG; - HttpGet httpGet = new HttpGet(url); - boolean successReadingConfig = true; - try - { - try (CloseableHttpClient httpclient = HttpClients.createDefault()) - { - try (CloseableHttpResponse response = execute(httpclient, httpGet)) - { - StatusLine statusLine = response.getStatusLine(); - if (statusLine == null) - { - throw new AlfrescoRuntimeException(remoteType+" on " + url+" returned no status "); - } - HttpEntity resEntity = response.getEntity(); - if (resEntity != null) - { - int statusCode = statusLine.getStatusCode(); - if (statusCode == 200) - { - try - { - String content = getContent(resEntity); - - try (StringReader reader = new StringReader(content)) - { - int transformCount = allTransforms.size(); - configFileFinder.readFile(reader, remoteType+" on "+baseUrl, "json", baseUrl, log); - if (transformCount == allTransforms.size()) - { - successReadingConfig = false; - } - } - - EntityUtils.consume(resEntity); - } - catch (IOException e) - { - throw new AlfrescoRuntimeException("Failed to read the returned content from "+ - remoteType+" on " + url, e); - } - } - else - { - String message = getErrorMessage(resEntity); - throw new AlfrescoRuntimeException(remoteType+" on " + url+" returned a " + statusCode + - " status " + message); - } - } - else - { - throw new AlfrescoRuntimeException(remoteType+" on " + url+" did not return an entity " + url); - } - } - catch (IOException e) - { - throw new AlfrescoRuntimeException("Failed to connect or to read the response from "+remoteType+ - " on " + url, e); - } - } - catch (IOException e) - { - throw new AlfrescoRuntimeException(remoteType+" on " + url+" failed to create an HttpClient", e); - } - } - catch (AlfrescoRuntimeException e) - { - log.error(e.getMessage()); - successReadingConfig = false; - } - return successReadingConfig; - } - - // Tests mock the return values - CloseableHttpResponse execute(CloseableHttpClient httpclient, HttpGet httpGet) throws IOException - { - return httpclient.execute(httpGet); - } - - // Tests mock the return values - String getContent(HttpEntity resEntity) throws IOException - { - return EntityUtils.toString(resEntity); - } - - // Strip out just the error message in the response - private String getErrorMessage(HttpEntity resEntity) throws IOException - { - String message = ""; - String content = getContent(resEntity); - 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; - } - - public boolean addLocalConfig(String path) throws IOException - { - return configFileFinder.readFiles(path, log); - } - - public void register(TransformServiceRegistryImpl registry) throws IOException - { - TransformServiceRegistryImpl.Data data = registry.getData(); - data.setTEngineCount(tEngineCount); - data.setFileCount(configFileFinder.getFileCount()); - List transformers = getTransforms(); - transformers.forEach(t->registry.register(t.transform, t.baseUrl, t.readFrom)); - } - - public List getTransforms() throws IOException - { - List transforms = new ArrayList<>(); - - // After all json input has been loaded build the output with the options in place. - ArrayNode transformersNode = jsonObjectMapper.createArrayNode(); - for (TransformNodeAndItsOrigin entity : allTransforms) - { - transformersNode.add(entity.node); - - try - { - ArrayNode transformOptions = (ArrayNode) entity.node.get(TRANSFORM_OPTIONS); - if (transformOptions != null) - { - - ArrayNode options; - int size = transformOptions.size(); - if (size == 1) - { - // If there is a single node option reference, we can just use it. - int i = 0; - options = getTransformOptions(transformOptions, i, entity.node); - } - else - { - // If there are many node option references (typically in a pipeline), then each element - // has a group for each set of node options. - options = jsonObjectMapper.createArrayNode(); - for (int i = size - 1; i >= 0; i--) - { - JsonNode referencedTransformOptions = getTransformOptions(transformOptions, i, entity.node); - if (referencedTransformOptions != null) - { - ObjectNode element = jsonObjectMapper.createObjectNode(); - options.add(element); - - ObjectNode group = jsonObjectMapper.createObjectNode(); - group.set(TRANSFORM_OPTIONS, referencedTransformOptions); - element.set(GROUP, group); - } - } - } - if (options == null || options.size() == 0) - { - entity.node.remove(TRANSFORM_OPTIONS); - } - else - { - entity.node.set(TRANSFORM_OPTIONS, options); - } - } - - try - { - InlineTransformer transform = jsonObjectMapper.convertValue(entity.node, InlineTransformer.class); - transforms.add(new TransformAndItsOrigin(transform, entity.baseUrl, entity.readFrom)); - } - catch (IllegalArgumentException e) - { - log.error("Invalid transformer "+getTransformName(entity.node)+" "+e.getMessage()+" baseUrl="+entity.baseUrl); - } - } - catch (IllegalArgumentException e) - { - String transformString = jsonObjectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(entity.node); - log.error(e.getMessage()); - log.debug(transformString); - } - } - if (log.isTraceEnabled()) - { - log.trace("Combined config:\n"+jsonObjectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(transformersNode)); - } - - transforms = sortTransformers(transforms); - return transforms; - } - - // Sort transformers so there are no forward references, if that is possible. - private List sortTransformers(List original) - { - List transformers = new ArrayList<>(original.size()); - List todo = new ArrayList<>(original.size()); - Set transformerNames = new HashSet<>(); - boolean added; - do - { - added = false; - for (TransformAndItsOrigin entry : original) - { - String name = entry.transform.getTransformerName(); - List pipeline = entry.transform.getTransformerPipeline(); - boolean addEntry = true; - if (pipeline != null && !pipeline.isEmpty()) - { - for (TransformStep step : pipeline) - { - String stepName = step.getTransformerName(); - if (!transformerNames.contains(stepName)) - { - todo.add(entry); - addEntry = false; - break; - } - } - } - if (addEntry) - { - transformers.add(entry); - added = true; - if (name != null) - { - transformerNames.add(name); - } - } - } - - original.clear(); - original.addAll(todo); - todo.clear(); - } - while (added && !original.isEmpty()); - - transformers.addAll(todo); - - return transformers; - } - - private ArrayNode getTransformOptions(ArrayNode transformOptions, int i, ObjectNode transform) - { - ArrayNode options = null; - JsonNode optionName = transformOptions.get(i); - if (optionName.isTextual()) - { - String name = optionName.asText(); - options = allTransformOptions.get(name); - if (options == null) - { - String message = "Reference to \"transformOptions\": \"" + name + "\" not found. Transformer " + - getTransformName(transform) + " ignored."; - throw new IllegalArgumentException(message); - } - } - return options; - } - - private String getTransformName(ObjectNode transform) - { - String name = "Unknown"; - JsonNode nameNode = transform.get(TRANSFORMER_NAME); - if (nameNode != null && nameNode.isTextual()) - { - name = '"'+nameNode.asText()+'"'; - } - return name; - } -} diff --git a/src/main/java/org/alfresco/transform/client/model/config/TransformServiceRegistry.java b/src/main/java/org/alfresco/transform/client/model/config/TransformServiceRegistry.java deleted file mode 100644 index c1bcf59f7d..0000000000 --- a/src/main/java/org/alfresco/transform/client/model/config/TransformServiceRegistry.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * #%L - * Alfresco Repository - * %% - * Copyright (C) 2005 - 2018 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 . - * #L% - */ -package org.alfresco.transform.client.model.config; - -import org.quartz.CronExpression; - -import java.util.Map; - -/** - * Used by clients work out if a transformation is supported by a Transform Service. - */ -public interface TransformServiceRegistry -{ - /** - * Works out if the Transform Server should be able to transform content of a given source mimetype and size into a - * target mimetype given a list of actual transform option names and values (Strings) plus the data contained in the - * {@Transform} objects registered with this class. - * @param sourceMimetype the mimetype of the source content - * @param sourceSizeInBytes the size in bytes of the source content. Ignored if negative. - * @param targetMimetype the mimetype of the target - * @param actualOptions the actual name value pairs available that could be passed to the Transform Service. - * @param transformName (optional) name for the set of options and target mimetype. If supplied is used to cache - * results to avoid having to work out if a given transformation is supported a second time. - * The sourceMimetype and sourceSizeInBytes may still change. In the case of ACS this is the - * rendition name. - */ - boolean isSupported(String sourceMimetype, long sourceSizeInBytes, String targetMimetype, - Map actualOptions, String transformName); - - /** - * Returns the maximun size (in bytes) of the source content that can be transformed. - * @param sourceMimetype the mimetype of the source content - * @param targetMimetype the mimetype of the target - * @param actualOptions the actual name value pairs available that could be passed to the Transform Service. - * @param transformName (optional) name for the set of options and target mimetype. If supplied is used to cache - * results to avoid having to work out if a given transformation is supported a second time. - * The sourceMimetype and sourceSizeInBytes may still change. In the case of ACS this is the - * rendition name. - * @return the maximum size (in bytes) of the source content that can be transformed. If {@code -1} there is no - * limit, but if {@code 0} the transform is not supported. - */ - long getMaxSize(String sourceMimetype, String targetMimetype, - Map actualOptions, String transformName); -} diff --git a/src/main/java/org/alfresco/transform/client/model/config/TransformServiceRegistryImpl.java b/src/main/java/org/alfresco/transform/client/model/config/TransformServiceRegistryImpl.java deleted file mode 100644 index 56d0fc142c..0000000000 --- a/src/main/java/org/alfresco/transform/client/model/config/TransformServiceRegistryImpl.java +++ /dev/null @@ -1,459 +0,0 @@ -/* - * #%L - * Alfresco Repository - * %% - * Copyright (C) 2005 - 2018 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 . - * #L% - */ -package org.alfresco.transform.client.model.config; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.alfresco.util.ConfigScheduler; -import org.alfresco.util.PropertyCheck; -import org.apache.commons.logging.Log; -import org.quartz.CronExpression; -import org.springframework.beans.factory.InitializingBean; - -import java.io.IOException; -import java.io.Reader; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import static org.alfresco.repo.rendition2.RenditionDefinition2.TIMEOUT; - -/** - * Used by clients to work out if a transformation is supported by the Transform Service. - */ -public abstract class TransformServiceRegistryImpl implements TransformServiceRegistry, InitializingBean -{ - public static class Data - { - ConcurrentMap>> transformers = new ConcurrentHashMap<>(); - ConcurrentMap>> cachedSupportedTransformList = new ConcurrentHashMap<>(); - private int transformerCount = 0; - private int transformCount = 0; - private int tEngineCount = 0; - private int fileCount; - boolean firstTime = true; - - @Override - public String toString() - { - return transformerCount == 0 && transformCount == 0 && tEngineCount == 0 && fileCount == 0 - ? "" - : "(transformers: "+transformerCount+" transforms: "+transformCount+" t-engines: "+tEngineCount+" files: "+fileCount+")"; - } - - public void setTEngineCount(int tEngineCount) - { - this.tEngineCount = tEngineCount; - } - - public void setFileCount(int fileCount) - { - this.fileCount = fileCount; - } - } - - static class SupportedTransform - { - TransformOptionGroup transformOptions; - long maxSourceSizeBytes; - private String name; - private int priority; - - public SupportedTransform(Data data, String name, Set transformOptions, long maxSourceSizeBytes, int priority) - { - // Logically the top level TransformOptionGroup is required, so that child options are optional or required - // based on their own setting. - this.transformOptions = new TransformOptionGroup(true, transformOptions); - this.maxSourceSizeBytes = maxSourceSizeBytes; - this.name = name; - this.priority = priority; - data.transformCount++; - } - } - - protected boolean enabled = true; - private ObjectMapper jsonObjectMapper; - private CronExpression cronExpression; - private CronExpression initialAndOnErrorCronExpression; - - private ConfigScheduler configScheduler = new ConfigScheduler(this) - { - @Override - public boolean readConfig() throws IOException - { - return TransformServiceRegistryImpl.this.readConfig(); - } - - @Override - public Object createData() - { - return TransformServiceRegistryImpl.this.createData(); - } - }; - - public void setJsonObjectMapper(ObjectMapper jsonObjectMapper) - { - this.jsonObjectMapper = jsonObjectMapper; - } - - public CronExpression getCronExpression() - { - return cronExpression; - } - - public void setCronExpression(CronExpression cronExpression) - { - this.cronExpression = cronExpression; - } - - public CronExpression getInitialAndOnErrorCronExpression() - { - return initialAndOnErrorCronExpression; - } - - public void setInitialAndOnErrorCronExpression(CronExpression initialAndOnErrorCronExpression) - { - this.initialAndOnErrorCronExpression = initialAndOnErrorCronExpression; - } - - @Override - public void afterPropertiesSet() throws Exception - { - PropertyCheck.mandatory(this, "jsonObjectMapper", jsonObjectMapper); - // If we have a cronExpression it indicates that we will schedule reading. - if (cronExpression != null) - { - PropertyCheck.mandatory(this, "initialAndOnErrorCronExpression", initialAndOnErrorCronExpression); - } - - Log log = getLog(); - configScheduler.run(enabled, log, cronExpression, initialAndOnErrorCronExpression); - } - - public Data createData() - { - return new Data(); - } - - public Data getData() - { - return configScheduler.getData(); - } - - public abstract boolean readConfig() throws IOException; - - public boolean isEnabled() - { - return enabled; - } - - public void setEnabled(boolean enabled) - { - this.enabled = enabled; - setFirstTime(true); - } - - protected void setFirstTime(boolean firstTime) - { - getData().firstTime = firstTime; - } - - protected boolean getFirstTime() - { - return getData().firstTime; - } - - protected abstract Log getLog(); - - public void register(Reader reader, String readFrom) throws IOException - { - List transformers = jsonObjectMapper.readValue(reader, new TypeReference>(){}); - transformers.forEach(t -> register(t, null, readFrom)); - } - - protected void register(InlineTransformer transformer, String baseUrl, String readFrom) - { - Data data = getData(); - data.transformerCount++; - transformer.getSupportedSourceAndTargetList().forEach( - e -> data.transformers.computeIfAbsent(e.getSourceMediaType(), - k -> new ConcurrentHashMap<>()).computeIfAbsent(e.getTargetMediaType(), - k -> new ArrayList<>()).add( - new SupportedTransform(data, transformer.getTransformerName(), - transformer.getTransformOptions(), e.getMaxSourceSizeBytes(), e.getPriority()))); - } - - @Override - public boolean isSupported(String sourceMimetype, long sourceSizeInBytes, String targetMimetype, - Map actualOptions, String renditionName) - { - long maxSize = getMaxSize(sourceMimetype, targetMimetype, actualOptions, renditionName); - return maxSize != 0 && (maxSize == -1L || maxSize >= sourceSizeInBytes); - } - - /** - * Works out the name of the transformer (might not map to an actual transformer) that will be used to transform - * content of a given source mimetype and size into a target mimetype given a list of actual transform option names - * and values (Strings) plus the data contained in the {@Transform} objects registered with this class. - * @param sourceMimetype the mimetype of the source content - * @param sourceSizeInBytes the size in bytes of the source content. Ignored if negative. - * @param targetMimetype the mimetype of the target - * @param actualOptions the actual name value pairs available that could be passed to the Transform Service. - * @param renditionName (optional) name for the set of options and target mimetype. If supplied is used to cache - * results to avoid having to work out if a given transformation is supported a second time. - * The sourceMimetype and sourceSizeInBytes may still change. In the case of ACS this is the - * rendition name. - */ - protected String getTransformerName(String sourceMimetype, long sourceSizeInBytes, String targetMimetype, Map actualOptions, String renditionName) - { - List supportedTransforms = getTransformListBySize(sourceMimetype, targetMimetype, actualOptions, renditionName); - for (SupportedTransform supportedTransform : supportedTransforms) - { - if (supportedTransform.maxSourceSizeBytes == -1 || supportedTransform.maxSourceSizeBytes >= sourceSizeInBytes) - { - return supportedTransform.name; - } - } - - return null; - } - - @Override - public long getMaxSize(String sourceMimetype, String targetMimetype, - Map actualOptions, String renditionName) - { - List supportedTransforms = getTransformListBySize(sourceMimetype, targetMimetype, actualOptions, renditionName); - return supportedTransforms.isEmpty() ? 0 : supportedTransforms.get(supportedTransforms.size()-1).maxSourceSizeBytes; - } - - // Returns transformers in increasing supported size order, where lower priority transformers for the same size have - // been discarded. - private List getTransformListBySize(String sourceMimetype, String targetMimetype, - Map actualOptions, String renditionName) - { - if (actualOptions == null) - { - actualOptions = Collections.EMPTY_MAP; - } - if (renditionName != null && renditionName.trim().isEmpty()) - { - renditionName = null; - } - - Data data = getData(); - List transformListBySize = renditionName == null ? null - : data.cachedSupportedTransformList.computeIfAbsent(renditionName, k -> new ConcurrentHashMap<>()).get(sourceMimetype); - if (transformListBySize != null) - { - return transformListBySize; - } - - // Remove the "timeout" property from the actualOptions as it is not used to select a transformer. - if (actualOptions.containsKey(TIMEOUT)) - { - actualOptions = new HashMap(actualOptions); - actualOptions.remove(TIMEOUT); - } - - transformListBySize = new ArrayList<>(); - ConcurrentMap> targetMap = data.transformers.get(sourceMimetype); - if (targetMap != null) - { - List supportedTransformList = targetMap.get(targetMimetype); - if (supportedTransformList != null) - { - for (SupportedTransform supportedTransform : supportedTransformList) - { - TransformOptionGroup transformOptions = supportedTransform.transformOptions; - Map possibleTransformOptions = new HashMap<>(); - addToPossibleTransformOptions(possibleTransformOptions, transformOptions, true, actualOptions); - if (isSupported(possibleTransformOptions, actualOptions)) - { - addToSupportedTransformList(transformListBySize, supportedTransform); - } - } - } - } - - if (renditionName != null) - { - data.cachedSupportedTransformList.get(renditionName).put(sourceMimetype, transformListBySize); - } - - return transformListBySize; - } - - // Add newTransform to the transformListBySize in increasing size order and discards lower priority (numerically - // higher) transforms with a smaller or equal size. - private void addToSupportedTransformList(List transformListBySize, SupportedTransform newTransform) - { - for (int i=0; i < transformListBySize.size(); i++) - { - SupportedTransform existingTransform = transformListBySize.get(i); - int added = -1; - int compare = compare(newTransform.maxSourceSizeBytes, existingTransform.maxSourceSizeBytes); - if (compare < 0) - { - transformListBySize.add(i, newTransform); - added = i; - } - else if (compare == 0) - { - if (newTransform.priority < existingTransform.priority) - { - transformListBySize.set(i, newTransform); - added = i; - } - } - if (added == i) - { - for (i--; i >= 0; i--) - { - existingTransform = transformListBySize.get(i); - if (newTransform.priority <= existingTransform.priority) - { - transformListBySize.remove(i); - } - } - return; - } - } - transformListBySize.add(newTransform); - } - - // compare where -1 is unlimited. - private int compare(long a, long b) - { - return a == -1 - ? b == -1 ? 0 : 1 - : b == -1 ? -1 - : a == b ? 0 - : a > b ? 1 : -1; - } - - /** - * Flatten out the transform options by adding them to the supplied possibleTransformOptions.

- * - * If possible discards options in the supplied transformOptionGroup if the group is optional and the actualOptions - * don't provide any of the options in the group. Or to put it another way:

- * - * It adds individual transform options from the transformOptionGroup to possibleTransformOptions if the group is - * required or if the actualOptions include individual options from the group. As a result it is possible that none - * of the group are added if it is optional. It is also possible to add individual transform options that are - * themselves required but not in the actualOptions. In this the isSupported method will return false. - * @return true if any options were added. Used by nested call parents to determine if an option was added from a - * nested sub group. - */ - boolean addToPossibleTransformOptions(Map possibleTransformOptions, - TransformOptionGroup transformOptionGroup, - Boolean parentGroupRequired, Map actualOptions) - { - boolean added = false; - boolean required = false; - - Set optionList = transformOptionGroup.getTransformOptions(); - if (optionList != null && !optionList.isEmpty()) - { - // We need to avoid adding options from a group that is required but its parents are not. - boolean transformOptionGroupRequired = transformOptionGroup.isRequired() && parentGroupRequired; - - // Check if the group contains options in actualOptions. This will add any options from sub groups. - for (TransformOption transformOption : optionList) - { - if (transformOption instanceof TransformOptionGroup) - { - added = addToPossibleTransformOptions(possibleTransformOptions, (TransformOptionGroup) transformOption, - transformOptionGroupRequired, actualOptions); - required |= added; - } - else - { - String name = ((TransformOptionValue) transformOption).getName(); - if (actualOptions.containsKey(name)) - { - required = true; - } - } - } - - if (required || transformOptionGroupRequired) - { - for (TransformOption transformOption : optionList) - { - if (transformOption instanceof TransformOptionValue) - { - added = true; - TransformOptionValue transformOptionValue = (TransformOptionValue) transformOption; - String name = transformOptionValue.getName(); - boolean optionValueRequired = transformOptionValue.isRequired(); - possibleTransformOptions.put(name, optionValueRequired); - } - } - } - } - - return added; - } - - boolean isSupported(Map transformOptions, Map actualOptions) - { - boolean supported = true; - - // Check all required transformOptions are supplied - for (Map.Entry transformOption : transformOptions.entrySet()) - { - Boolean required = transformOption.getValue(); - if (required) - { - String name = transformOption.getKey(); - if (!actualOptions.containsKey(name)) - { - supported = false; - break; - } - } - } - - if (supported) - { - // Check there are no extra unused actualOptions - for (String actualOption : actualOptions.keySet()) - { - if (!transformOptions.containsKey(actualOption)) - { - supported = false; - break; - } - } - } - return supported; - } -} diff --git a/src/main/java/org/alfresco/transform/client/registry/CombinedConfig.java b/src/main/java/org/alfresco/transform/client/registry/CombinedConfig.java new file mode 100644 index 0000000000..e440844f51 --- /dev/null +++ b/src/main/java/org/alfresco/transform/client/registry/CombinedConfig.java @@ -0,0 +1,241 @@ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2019 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 . + * #L% + */ +package org.alfresco.transform.client.registry; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.transform.client.model.config.TransformConfig; +import org.alfresco.transform.client.model.config.TransformOption; +import org.alfresco.transform.client.model.config.Transformer; +import org.alfresco.util.ConfigFileFinder; +import org.apache.commons.logging.Log; +import org.apache.http.HttpEntity; +import org.apache.http.StatusLine; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * This class reads multiple T-Engine config and local files and registers them all with a registry as if they were all + * in one file. Transform options are shared between all sources.

+ * + * The caller should make calls to {@link #addRemoteConfig(List, String)} and {@link #addLocalConfig(String)} followed + * by a call to {@link #register(TransformServiceRegistryImpl)}. + * + * @author adavis + */ +public class CombinedConfig +{ + private static final String TRANSFORM_CONFIG = "/transform/config"; + + private final Log log; + + static class TransformAndItsOrigin + { + final Transformer transformer; + final String baseUrl; + final String readFrom; + + TransformAndItsOrigin(Transformer transformer, String baseUrl, String readFrom) + { + this.transformer = transformer; + this.baseUrl = baseUrl; + this.readFrom = readFrom; + } + } + + Map> combinedTransformOptions = new HashMap<>(); + List combinedTransformers = new ArrayList<>(); + + private ObjectMapper jsonObjectMapper = new ObjectMapper(); + private ConfigFileFinder configFileFinder; + private int tEngineCount; + + public CombinedConfig(Log log) + { + this.log = log; + + configFileFinder = new ConfigFileFinder(jsonObjectMapper) + { + @Override + protected void readJson(JsonNode jsonNode, String readFrom, String baseUrl) + { + TransformConfig transformConfig = jsonObjectMapper.convertValue(jsonNode, TransformConfig.class); + transformConfig.getTransformOptions().forEach((key, map) -> combinedTransformOptions.put(key, map)); + transformConfig.getTransformers().forEach(transformer -> combinedTransformers.add( + new TransformAndItsOrigin(transformer, baseUrl, readFrom))); + } + }; + } + + public boolean addLocalConfig(String path) + { + return configFileFinder.readFiles(path, log); + } + + public boolean addRemoteConfig(List urls, String remoteType) + { + boolean successReadingConfig = true; + for (String url : urls) + { + if (addRemoteConfig(url, remoteType)) + { + tEngineCount++ ; + } + else + { + successReadingConfig = false; + } + } + return successReadingConfig; + } + + private boolean addRemoteConfig(String baseUrl, String remoteType) + { + String url = baseUrl + TRANSFORM_CONFIG; + HttpGet httpGet = new HttpGet(url); + boolean successReadingConfig = true; + try + { + try (CloseableHttpClient httpclient = HttpClients.createDefault()) + { + try (CloseableHttpResponse response = execute(httpclient, httpGet)) + { + StatusLine statusLine = response.getStatusLine(); + if (statusLine == null) + { + throw new AlfrescoRuntimeException(remoteType+" on " + url+" returned no status "); + } + HttpEntity resEntity = response.getEntity(); + if (resEntity != null) + { + int statusCode = statusLine.getStatusCode(); + if (statusCode == 200) + { + try + { + String content = getContent(resEntity); + + try (StringReader reader = new StringReader(content)) + { + int transformCount = combinedTransformers.size(); + configFileFinder.readFile(reader, remoteType+" on "+baseUrl, "json", baseUrl, log); + if (transformCount == combinedTransformers.size()) + { + successReadingConfig = false; + } + } + + EntityUtils.consume(resEntity); + } + catch (IOException e) + { + throw new AlfrescoRuntimeException("Failed to read the returned content from "+ + remoteType+" on " + url, e); + } + } + else + { + String message = getErrorMessage(resEntity); + throw new AlfrescoRuntimeException(remoteType+" on " + url+" returned a " + statusCode + + " status " + message); + } + } + else + { + throw new AlfrescoRuntimeException(remoteType+" on " + url+" did not return an entity " + url); + } + } + catch (IOException e) + { + throw new AlfrescoRuntimeException("Failed to connect or to read the response from "+remoteType+ + " on " + url, e); + } + } + catch (IOException e) + { + throw new AlfrescoRuntimeException(remoteType+" on " + url+" failed to create an HttpClient", e); + } + } + catch (AlfrescoRuntimeException e) + { + log.error(e.getMessage()); + successReadingConfig = false; + } + return successReadingConfig; + } + + // Tests mock the return values + CloseableHttpResponse execute(CloseableHttpClient httpclient, HttpGet httpGet) throws IOException + { + return httpclient.execute(httpGet); + } + + // Tests mock the return values + String getContent(HttpEntity resEntity) throws IOException + { + return EntityUtils.toString(resEntity); + } + + // Strip out just the error message in the response + private String getErrorMessage(HttpEntity resEntity) throws IOException + { + String message = ""; + String content = getContent(resEntity); + 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; + } + + public void register(TransformServiceRegistryImpl registry) + { + TransformServiceRegistryImpl.Data data = registry.getData(); + data.setTEngineCount(tEngineCount); + data.setFileCount(configFileFinder.getFileCount()); + + combinedTransformers.forEach(transformer -> + registry.register(transformer.transformer, combinedTransformOptions, + transformer.baseUrl, transformer.readFrom)); + } +} diff --git a/src/main/java/org/alfresco/transform/client/registry/TransformServiceRegistryImpl.java b/src/main/java/org/alfresco/transform/client/registry/TransformServiceRegistryImpl.java new file mode 100644 index 0000000000..c1058faf0b --- /dev/null +++ b/src/main/java/org/alfresco/transform/client/registry/TransformServiceRegistryImpl.java @@ -0,0 +1,169 @@ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2018 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 . + * #L% + */ +package org.alfresco.transform.client.registry; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.alfresco.transform.client.registry.AbstractTransformRegistry; +import org.alfresco.transform.client.registry.TransformCache; +import org.alfresco.util.ConfigScheduler; +import org.alfresco.util.PropertyCheck; +import org.apache.commons.logging.Log; +import org.quartz.CronExpression; +import org.springframework.beans.factory.InitializingBean; + +import java.io.IOException; + +/** + * Used by clients to work out if a transformation is supported by the Transform Service. + */ +public abstract class TransformServiceRegistryImpl extends AbstractTransformRegistry implements InitializingBean +{ + public static class Data extends TransformCache + { + private int tEngineCount = 0; + private int fileCount; + boolean firstTime = true; + + @Override + public String toString() + { + return transformerCount == 0 && transformCount == 0 && tEngineCount == 0 && fileCount == 0 + ? "" + : "(transformers: "+transformerCount+" transforms: "+transformCount+" t-engines: "+tEngineCount+" files: "+fileCount+")"; + } + + public void setTEngineCount(int tEngineCount) + { + this.tEngineCount = tEngineCount; + } + + public void setFileCount(int fileCount) + { + this.fileCount = fileCount; + } + } + + protected boolean enabled = true; + private ObjectMapper jsonObjectMapper; + private CronExpression cronExpression; + private CronExpression initialAndOnErrorCronExpression; + + private ConfigScheduler configScheduler = new ConfigScheduler<>(this) + { + @Override + public boolean readConfig() throws IOException + { + return TransformServiceRegistryImpl.this.readConfig(); + } + + @Override + public Data createData() + { + return TransformServiceRegistryImpl.this.createData(); + } + }; + + public void setJsonObjectMapper(ObjectMapper jsonObjectMapper) + { + this.jsonObjectMapper = jsonObjectMapper; + } + + public CronExpression getCronExpression() + { + return cronExpression; + } + + public void setCronExpression(CronExpression cronExpression) + { + this.cronExpression = cronExpression; + } + + public CronExpression getInitialAndOnErrorCronExpression() + { + return initialAndOnErrorCronExpression; + } + + public void setInitialAndOnErrorCronExpression(CronExpression initialAndOnErrorCronExpression) + { + this.initialAndOnErrorCronExpression = initialAndOnErrorCronExpression; + } + + @Override + public void afterPropertiesSet() throws Exception + { + PropertyCheck.mandatory(this, "jsonObjectMapper", jsonObjectMapper); + // If we have a cronExpression it indicates that we will schedule reading. + if (cronExpression != null) + { + PropertyCheck.mandatory(this, "initialAndOnErrorCronExpression", initialAndOnErrorCronExpression); + } + + Log log = getLog(); + configScheduler.run(enabled, log, cronExpression, initialAndOnErrorCronExpression); + } + + public Data createData() + { + return new Data(); + } + + public Data getData() + { + return configScheduler.getData(); + } + + public abstract boolean readConfig() throws IOException; + + public boolean isEnabled() + { + return enabled; + } + + public void setEnabled(boolean enabled) + { + this.enabled = enabled; + setFirstTime(true); + } + + protected void setFirstTime(boolean firstTime) + { + getData().firstTime = firstTime; + } + + protected boolean getFirstTime() + { + return getData().firstTime; + } + + protected abstract Log getLog(); + + @Override + protected void logError(String msg) + { + getLog().error(msg); + } +} diff --git a/src/test/java/org/alfresco/AllUnitTestsSuite.java b/src/test/java/org/alfresco/AllUnitTestsSuite.java index 1b75edccdd..7e52805a73 100644 --- a/src/test/java/org/alfresco/AllUnitTestsSuite.java +++ b/src/test/java/org/alfresco/AllUnitTestsSuite.java @@ -201,7 +201,7 @@ import org.junit.runners.Suite; org.alfresco.util.resource.HierarchicalResourceLoaderTest.class, org.alfresco.repo.events.ClientUtilTest.class, org.alfresco.repo.rendition2.RenditionService2Test.class, - org.alfresco.transform.client.model.config.TransformServiceRegistryConfigTest.class + org.alfresco.transform.client.registry.TransformServiceRegistryConfigTest.class }) public class AllUnitTestsSuite { diff --git a/src/test/java/org/alfresco/AppContext06TestSuite.java b/src/test/java/org/alfresco/AppContext06TestSuite.java index 5e89f0e768..28fe12c76a 100644 --- a/src/test/java/org/alfresco/AppContext06TestSuite.java +++ b/src/test/java/org/alfresco/AppContext06TestSuite.java @@ -49,7 +49,7 @@ import org.junit.runners.Suite; org.alfresco.repo.rawevents.TransactionAwareEventProducerTest.class, // Requires running transformers - org.alfresco.transform.client.model.config.LocalTransformServiceRegistryConfigTest.class, + org.alfresco.transform.client.registry.LocalTransformServiceRegistryConfigTest.class, org.alfresco.repo.rendition2.RenditionService2IntegrationTest.class, org.alfresco.repo.rendition2.LocalTransformServiceRegistryIntegrationTest.class, org.alfresco.repo.rendition2.LocalTransformClientIntegrationTest.class, diff --git a/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionIntegrationTest.java b/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionIntegrationTest.java index ec5c443599..efd5066195 100644 --- a/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionIntegrationTest.java +++ b/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionIntegrationTest.java @@ -45,7 +45,7 @@ import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.namespace.QName; import org.alfresco.service.transaction.TransactionService; -import org.alfresco.transform.client.model.config.TransformServiceRegistry; +import org.alfresco.transform.client.registry.TransformServiceRegistry; import org.alfresco.util.BaseSpringTest; import org.alfresco.util.GUID; import org.alfresco.util.PropertyMap; diff --git a/src/test/java/org/alfresco/repo/rendition2/LocalRenditionTest.java b/src/test/java/org/alfresco/repo/rendition2/LocalRenditionTest.java index 6337e6832e..597d0b8de6 100644 --- a/src/test/java/org/alfresco/repo/rendition2/LocalRenditionTest.java +++ b/src/test/java/org/alfresco/repo/rendition2/LocalRenditionTest.java @@ -59,6 +59,6 @@ public class LocalRenditionTest extends AbstractRenditionTest @Test public void testAllSourceExtensions() throws Exception { - internalTestAllSourceExtensions(57, 0); + internalTestAllSourceExtensions(81, 0); } } diff --git a/src/test/java/org/alfresco/repo/rendition2/LocalTransformServiceRegistryIntegrationTest.java b/src/test/java/org/alfresco/repo/rendition2/LocalTransformServiceRegistryIntegrationTest.java index 4683c88907..c858058a23 100644 --- a/src/test/java/org/alfresco/repo/rendition2/LocalTransformServiceRegistryIntegrationTest.java +++ b/src/test/java/org/alfresco/repo/rendition2/LocalTransformServiceRegistryIntegrationTest.java @@ -26,8 +26,8 @@ package org.alfresco.repo.rendition2; import org.alfresco.repo.content.transform.LocalTransformServiceRegistry; -import org.alfresco.transform.client.model.config.TransformServiceRegistry; -import org.alfresco.transform.client.model.config.TransformServiceRegistryImpl; +import org.alfresco.transform.client.registry.TransformServiceRegistry; +import org.alfresco.transform.client.registry.TransformServiceRegistryImpl; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; diff --git a/src/test/java/org/alfresco/repo/rendition2/RenditionService2Test.java b/src/test/java/org/alfresco/repo/rendition2/RenditionService2Test.java index 60334f9080..4cefa661fd 100644 --- a/src/test/java/org/alfresco/repo/rendition2/RenditionService2Test.java +++ b/src/test/java/org/alfresco/repo/rendition2/RenditionService2Test.java @@ -39,7 +39,7 @@ import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.rule.RuleService; import org.alfresco.service.namespace.QName; import org.alfresco.service.transaction.TransactionService; -import org.alfresco.transform.client.model.config.TransformServiceRegistryImpl; +import org.alfresco.transform.client.registry.TransformServiceRegistryImpl; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/src/test/java/org/alfresco/transform/client/model/config/TransformBuilder.java b/src/test/java/org/alfresco/transform/client/model/config/TransformBuilder.java deleted file mode 100644 index 1cd65aed9d..0000000000 --- a/src/test/java/org/alfresco/transform/client/model/config/TransformBuilder.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * #%L - * Alfresco Repository - * %% - * Copyright (C) 2005 - 2018 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 . - * #L% - */ -package org.alfresco.transform.client.model.config; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * Helper class that builds a {@link InlineTransformer} given the source and target types and a pipeline of Transformers - * for creating intermediary content. - */ -public class TransformBuilder -{ - public InlineTransformer buildPipeLine(String name, Set sourceAndTargetList, - List transformerList) - { - Set options = new HashSet<>(transformerList.size()); - transformerList.forEach(t -> - { - // Avoid creating an enpty TransformOptionGroup if the transformer has no options. - // Works with an empty TransformOptionGroup but adds to the complexity. - if (t.getTransformer().getTransformOptions() != null) - { - options.add(new TransformOptionGroup(t.isRequired(), t.getTransformer().getTransformOptions())); - } - }); - return new InlineTransformer(name, options, sourceAndTargetList); - } -} diff --git a/src/test/java/org/alfresco/transform/client/model/config/TransformServiceRegistryConfigTest.java b/src/test/java/org/alfresco/transform/client/model/config/TransformServiceRegistryConfigTest.java deleted file mode 100644 index 80f0e84c76..0000000000 --- a/src/test/java/org/alfresco/transform/client/model/config/TransformServiceRegistryConfigTest.java +++ /dev/null @@ -1,896 +0,0 @@ -/* - * #%L - * Alfresco Repository - * %% - * Copyright (C) 2005 - 2019 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 . - * #L% - */ -package org.alfresco.transform.client.model.config; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.log4j.Level; -import org.apache.log4j.LogManager; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.quartz.CronExpression; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.Reader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentMap; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * Test the config received from the Transform Service about what it supports. - */ -public class TransformServiceRegistryConfigTest -{ - private static Log log = LogFactory.getLog(TransformServiceRegistryConfigTest.class); - - public static final String GIF = "image/gif"; - public static final String JPEG = "image/jpeg"; - public static final String PNG = "image/png"; - public static final String TIFF = "image/tiff"; - public static final String PDF = "application/pdf"; - public static final String DOC = "application/msword"; - public static final String XLS = "application/vnd.ms-excel"; - public static final String PPT = "application/vnd.ms-powerpoint"; - public static final String MSG = "application/vnd.ms-outlook"; - public static final String TXT = "text/plain"; - - private static final String TRANSFORM_SERVICE_CONFIG = "alfresco/transform-service-config-test.json"; - private static final String TRANSFORM_SERVICE_CONFIG_PIPELINE = "alfresco/transform-service-config-pipeline-test.json"; - - public static final ObjectMapper JSON_OBJECT_MAPPER = new ObjectMapper(); - - private TransformServiceRegistryImpl registry; - protected TransformBuilder builder; - protected InlineTransformer transformer; - - @Before - public void setUp() throws Exception - { - registry = buildTransformServiceRegistryImpl(); - builder = new TransformBuilder(); - LogManager.getLogger(TransformServiceRegistryConfigTest.class).setLevel(Level.DEBUG); - } - - protected TransformServiceRegistryImpl buildTransformServiceRegistryImpl() throws Exception - { - TransformServiceRegistryImpl registry = new TransformServiceRegistryImpl() - { - @Override - public boolean readConfig() throws IOException - { - return true; - } - - @Override - protected Log getLog() - { - return log; - } - }; - registry.setJsonObjectMapper(JSON_OBJECT_MAPPER); - registry.setCronExpression(null); // just read once - registry.afterPropertiesSet(); - return registry; - } - - @After - public void tearDown() - { - // shut down - } - - protected String getTransformServiceConfig() - { - return TRANSFORM_SERVICE_CONFIG; - } - - protected String getTransformServiceConfigPipeline() - { - return TRANSFORM_SERVICE_CONFIG_PIPELINE; - } - - private void assertAddToPossibleOptions(TransformOptionGroup transformOptionGroup, String actualOptionNames, String expectedNames, String expectedRequired) - { - Map actualOptions = buildActualOptions(actualOptionNames); - Set expectedNameSet = expectedNames == null || expectedNames.isEmpty() ? Collections.EMPTY_SET : new HashSet(Arrays.asList(expectedNames.split(", "))); - Set expectedRequiredSet = expectedRequired == null || expectedRequired.isEmpty() ? Collections.EMPTY_SET : new HashSet(Arrays.asList(expectedRequired.split(", "))); - - Map possibleTransformOptions = new HashMap<>(); - - registry.addToPossibleTransformOptions(possibleTransformOptions, transformOptionGroup, true, actualOptions); - - assertEquals("The expected options don't match", expectedNameSet, possibleTransformOptions.keySet()); - for (String name: possibleTransformOptions.keySet()) - { - Boolean required = possibleTransformOptions.get(name); - if (required) - { - assertTrue(name+" should be REQUIRED", expectedRequiredSet.contains(name)); - } - else - { - assertFalse(name+" should be OPTIONAL", expectedRequiredSet.contains(name)); - } - } - } - - // transformOptionNames are upper case if required. - private void assertIsSupported(String actualOptionNames, String transformOptionNames, String unsupportedMsg) - { - Map actualOptions = buildActualOptions(actualOptionNames); - - Map transformOptions = new HashMap<>(); - Set transformOptionNameSet = transformOptionNames == null || transformOptionNames.isEmpty() ? Collections.EMPTY_SET : new HashSet(Arrays.asList(transformOptionNames.split(", "))); - for (String name : transformOptionNameSet) - { - Boolean required = name.toUpperCase().equals(name); - transformOptions.put(name, required); - } - - boolean supported = registry.isSupported(transformOptions, actualOptions); - if (unsupportedMsg == null || unsupportedMsg.isEmpty()) - { - assertTrue("Expected these options to be SUPPORTED", supported); - } - else - { - assertFalse("Expected these options NOT to be supported, because "+unsupportedMsg, supported); - } - } - - private void assertTransformOptions(Set transformOptions) throws Exception - { - transformer = new InlineTransformer("name", - transformOptions, - Set.of( - new SupportedSourceAndTarget(DOC, TXT, -1), - new SupportedSourceAndTarget(XLS, TXT, 1024000))); - - registry = buildTransformServiceRegistryImpl(); - registry.register(transformer, getBaseUrl(transformer), getClass().getName()); - - assertTrue(registry.isSupported(XLS, 1024, TXT, Collections.emptyMap(), null)); - assertTrue(registry.isSupported(XLS, 1024000, TXT, null, null)); - assertFalse(registry.isSupported(XLS, 1024001, TXT, Collections.emptyMap(), null)); - assertTrue(registry.isSupported(DOC, 1024001, TXT, null, null)); - } - - protected String getBaseUrl(InlineTransformer transformer) - { - return null; - } - - private void assertTransformerName(String sourceMimetype, long sourceSizeInBytes, String targetMimetype, - Map actualOptions, String expectedTransformerName, - InlineTransformer... transformers) throws Exception - { - buildAndPopulateRegistry(transformers); - String transformerName = registry.getTransformerName(sourceMimetype, sourceSizeInBytes, targetMimetype, actualOptions, null); - assertEquals(sourceMimetype+" to "+targetMimetype+" should have returned "+expectedTransformerName, expectedTransformerName, transformerName); - } - - private void assertSupported(String sourceMimetype, long sourceSizeInBytes, String targetMimetype, - Map actualOptions, String unsupportedMsg) throws Exception - { - assertSupported(sourceMimetype, sourceSizeInBytes, targetMimetype, actualOptions, unsupportedMsg, transformer); - } - - private void assertSupported(String sourceMimetype, long sourceSizeInBytes, String targetMimetype, - Map actualOptions, String unsupportedMsg, - InlineTransformer... transformers) throws Exception - { - buildAndPopulateRegistry(transformers); - assertSupported(sourceMimetype, sourceSizeInBytes, targetMimetype, actualOptions, null, unsupportedMsg); - } - - private void buildAndPopulateRegistry(InlineTransformer[] transformers) throws Exception - { - registry = buildTransformServiceRegistryImpl(); - for (InlineTransformer transformer : transformers) - { - registry.register(transformer, getBaseUrl(transformer), getClass().getName()); - } - } - - private void assertSupported(String sourceMimetype, long sourceSizeInBytes, String targetMimetype, - Map actualOptions, String renditionName, - String unsupportedMsg) - { - boolean supported = registry.isSupported(sourceMimetype, sourceSizeInBytes, targetMimetype, actualOptions, renditionName); - if (unsupportedMsg == null || unsupportedMsg.isEmpty()) - { - assertTrue(sourceMimetype+" to "+targetMimetype+" should be SUPPORTED", supported); - } - else - { - assertFalse(sourceMimetype+" to "+targetMimetype+" should NOT be supported", supported); - } - } - - private Map buildActualOptions(String actualOptionNames) - { - Map actualOptions = new HashMap<>(); - Set actualOptionNamesSet = actualOptionNames == null || actualOptionNames.isEmpty() ? Collections.EMPTY_SET : new HashSet(Arrays.asList(actualOptionNames.split(", "))); - for (String name : actualOptionNamesSet) - { - actualOptions.put(name, "value for " + name); - } - return actualOptions; - } - - private void register(String path) throws IOException - { - CombinedConfig combinedConfig = new CombinedConfig(log); - combinedConfig.addLocalConfig(path); - combinedConfig.register(registry); - } - - @Test - public void testReadWriteJson() throws IOException - { - InlineTransformer libreoffice = new InlineTransformer("libreoffice", - null, // there are no options - Set.of( - new SupportedSourceAndTarget(DOC, PDF, -1), - new SupportedSourceAndTarget(XLS, PDF, 1024000), - new SupportedSourceAndTarget(PPT, PDF, -1), - new SupportedSourceAndTarget(MSG, PDF, -1))); - - InlineTransformer pdfrenderer = new InlineTransformer("pdfrenderer", - Set.of( - new TransformOptionValue(false, "page"), - new TransformOptionValue(false, "width"), - new TransformOptionValue(false, "height"), - new TransformOptionValue(false, "allowPdfEnlargement"), - new TransformOptionValue(false, "maintainPdfAspectRatio")), - Set.of( - new SupportedSourceAndTarget(PDF, PNG, -1))); - - InlineTransformer tika = new InlineTransformer("tika", - Set.of( - new TransformOptionValue(false, "transform"), - new TransformOptionValue(false, "includeContents"), - new TransformOptionValue(false, "notExtractBookmarksText"), - new TransformOptionValue(false, "targetMimetype"), - new TransformOptionValue(false, "targetEncoding")), - Set.of( - new SupportedSourceAndTarget(PDF, TXT, -1), - new SupportedSourceAndTarget(DOC, TXT, -1), - new SupportedSourceAndTarget(XLS, TXT, 1024000), - new SupportedSourceAndTarget(PPT, TXT, -1), - new SupportedSourceAndTarget(MSG, TXT, -1))); - - InlineTransformer imagemagick = new InlineTransformer("imagemagick", - Set.of( - new TransformOptionValue(false, "alphaRemove"), - new TransformOptionValue(false, "autoOrient"), - new TransformOptionGroup(false, Set.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, Set.of( - new TransformOptionValue(false, "thumbnail"), - new TransformOptionValue(false, "resizeHeight"), - new TransformOptionValue(false, "resizeWidth"), - new TransformOptionValue(false, "resizePercentage"), - new TransformOptionValue(false, "maintainAspectRatio")))), - Set.of( - new SupportedSourceAndTarget(GIF, GIF, -1), - new SupportedSourceAndTarget(GIF, JPEG, -1), - new SupportedSourceAndTarget(GIF, PNG, -1), - new SupportedSourceAndTarget(GIF, TIFF, -1), - - new SupportedSourceAndTarget(JPEG, GIF, -1), - new SupportedSourceAndTarget(JPEG, JPEG, -1), - new SupportedSourceAndTarget(JPEG, PNG, -1), - new SupportedSourceAndTarget(JPEG, TIFF, -1), - - new SupportedSourceAndTarget(PNG, GIF, -1), - new SupportedSourceAndTarget(PNG, JPEG, -1), - new SupportedSourceAndTarget(PNG, PNG, -1), - new SupportedSourceAndTarget(PNG, TIFF, -1), - - new SupportedSourceAndTarget(TIFF, GIF, -1), - new SupportedSourceAndTarget(TIFF, JPEG, -1), - new SupportedSourceAndTarget(TIFF, PNG, -1), - new SupportedSourceAndTarget(TIFF, TIFF, -1))); - - InlineTransformer officeToImage = builder.buildPipeLine("transformer1", - Set.of( - new SupportedSourceAndTarget(DOC, GIF, -1), - new SupportedSourceAndTarget(DOC, JPEG, -1), - new SupportedSourceAndTarget(DOC, PNG, -1), - new SupportedSourceAndTarget(DOC, TIFF, -1), - new SupportedSourceAndTarget(XLS, GIF, -1), - new SupportedSourceAndTarget(XLS, JPEG, -1), - new SupportedSourceAndTarget(XLS, PNG, -1), - new SupportedSourceAndTarget(XLS, TIFF, -1), - new SupportedSourceAndTarget(PPT, GIF, -1), - new SupportedSourceAndTarget(PPT, JPEG, -1), - new SupportedSourceAndTarget(PPT, PNG, -1), - new SupportedSourceAndTarget(PPT, TIFF, -1), - new SupportedSourceAndTarget(MSG, GIF, -1), - new SupportedSourceAndTarget(MSG, JPEG, -1), - new SupportedSourceAndTarget(MSG, PNG, -1), - new SupportedSourceAndTarget(MSG, TIFF, -1)), - Arrays.asList( - new ChildTransformer(false, libreoffice), // to pdf - new ChildTransformer(false, pdfrenderer), // to png - new ChildTransformer(true, imagemagick))); // to other image formats - - List transformers1 = Arrays.asList(libreoffice, tika, pdfrenderer, imagemagick, officeToImage); - - File tempFile = File.createTempFile("test", ".json"); - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.writerWithDefaultPrettyPrinter().writeValue(new FileWriter(tempFile), transformers1); - - try (Reader reader = new BufferedReader(new FileReader(tempFile))) - { - registry.register(reader, getClass().getName()); - // Check the count of transforms supported - assertEquals("The number of UNIQUE source to target mimetypes transforms has changed. Config change?", - 42, countSupportedTransforms(true)); - assertEquals("The number of source to target mimetypes transforms has changed. " + - "There may be multiple transformers for the same combination. Config change?", - 42, countSupportedTransforms(false)); - - // Check a supported transform for each transformer. - assertSupported(DOC, 1234, PDF, null, null, ""); // libreoffice - assertSupported(DOC, 1234, PDF, null, null, ""); // libreoffice - assertSupported(PDF, 1234, PNG, null, null, ""); // pdfrenderer - assertSupported(JPEG,1234, GIF, null, null, ""); // imagemagick - assertSupported(MSG, 1234, TXT, null, null, ""); // tika - assertSupported(MSG, 1234, GIF, null, null, ""); // transformer1 (officeToImageViaPdf) - assertSupported(DOC, 1234, PNG, null, null, ""); // transformer1 (officeToImageViaPdf) - } - } - - @Test - public void testJsonConfig() throws IOException - { - register(getTransformServiceConfig()); - - // Check the count of transforms supported - assertEquals("The number of UNIQUE source to target mimetypes transforms has changed. Config change?", - 60, countSupportedTransforms(true)); - assertEquals("The number of source to target mimetypes transforms has changed. " + - "There may be multiple transformers for the same combination. Config change?", - 60, countSupportedTransforms(false)); - - // Check a supported transform for each transformer. - assertSupported(DOC, 1234, PDF, null, null, ""); // libreoffice - assertSupported(DOC, 1234, PDF, null, null, ""); // libreoffice - assertSupported(PDF, 1234, PNG, null, null, ""); // pdfrenderer - assertSupported(JPEG,1234, GIF, null, null, ""); // imagemagick - assertSupported(MSG, 1234, TXT, null, null, ""); // tika - assertSupported(MSG, 1234, GIF, null, null, ""); // officeToImageViaPdf - - Map invalidPdfOptions = new HashMap<>(); - invalidPdfOptions.put("allowEnlargement", "false"); - assertSupported(DOC, 1234, PDF, invalidPdfOptions, null, "Invalid as there is a extra option"); - } - - @Test - public void testJsonPipeline() throws IOException - { - register(getTransformServiceConfigPipeline()); - - // Check the count of transforms supported - int expectedTransforms = getExpectedTransformsForTestJsonPipeline(); - assertEquals("The number of UNIQUE source to target mimetypes transforms has changed. Config change?", - expectedTransforms, countSupportedTransforms(true)); - assertEquals("The number of source to target mimetypes transforms has changed. " + - "There may be multiple transformers for the same combination. Config change?", - expectedTransforms, countSupportedTransforms(false)); - - ConcurrentMap> transformer = - registry.getData().transformers.get("officeToImageViaPdf"); - - // Check required and optional default correctly - ConcurrentMap> transformsToWord = - registry.getData().transformers.get(DOC); - List supportedTransforms = transformsToWord.get(GIF); - TransformServiceRegistryImpl.SupportedTransform supportedTransform = supportedTransforms.get(0); - - Set transformOptionsSet = supportedTransform.transformOptions.getTransformOptions(); - System.out.println("Nothing"); - - Iterator iterator = transformOptionsSet.iterator(); - assertTrue("Expected transform values", iterator.hasNext()); - // Because Set is unordered we don't know which TransformOptionGroup we retrieve - TransformOptionGroup transformOptions1 = (TransformOptionGroup)iterator.next(); - - assertTrue("Expected transform values", iterator.hasNext()); - TransformOptionGroup transformOptions2 = (TransformOptionGroup)iterator.next(); - - TransformOptionGroup imagemagick; - TransformOptionGroup pdf; - - if(containsTransformOptionValueName(transformOptions1, "alphaRemove")) - { - imagemagick = transformOptions1; - pdf = transformOptions2; - } - else - { - imagemagick = transformOptions2; - pdf = transformOptions1; - } - - TransformOptionValue alphaRemove = (TransformOptionValue)retrieveTransformOptionByPropertyName(imagemagick, "alphaRemove", "TransformOptionValue"); - TransformOptionGroup crop = (TransformOptionGroup)retrieveTransformOptionByPropertyName(imagemagick, "crop", "TransformOptionGroup"); - TransformOptionValue cropGravity = (TransformOptionValue)retrieveTransformOptionByPropertyName(crop, "cropGravity", "TransformOptionValue"); - TransformOptionValue cropWidth = (TransformOptionValue)retrieveTransformOptionByPropertyName(crop, "cropWidth", "TransformOptionValue"); - - assertTrue("The holding group should be required", supportedTransform.transformOptions.isRequired()); - assertFalse("imagemagick should be optional as it is not set", imagemagick.isRequired()); - assertFalse("pdf should be optional as required is not set", pdf.isRequired()); - assertEquals("alphaRemove", alphaRemove.getName()); - assertEquals("cropGravity", cropGravity.getName()); - assertEquals("cropWidth", cropWidth.getName()); - assertFalse("alphaRemove should be optional as required is not set", alphaRemove.isRequired()); - assertFalse("crop should be optional as required is not set", crop.isRequired()); - assertTrue("cropGravity should be required as it is set", cropGravity.isRequired()); - assertFalse("cropWidth should be optional as required is not set", cropWidth.isRequired()); - - // Check a supported transform for each transformer. - assertSupported(DOC,1234, GIF, null, null, ""); - assertSupported(DOC,1234, PNG, null, null, ""); - assertSupported(DOC,1234, JPEG, null, null, ""); - assertSupported(DOC,1234, TIFF, null, null, ""); - - Map actualOptions = new HashMap<>(); - actualOptions.put("thumbnail", "true"); - actualOptions.put("resizeWidth", "100"); - actualOptions.put("resizeHeight", "100"); - actualOptions.put("allowEnlargement", "false"); - actualOptions.put("maintainAspectRatio", "true"); - assertSupported(DOC,1234, PNG, actualOptions, null, ""); - } - - private TransformOption retrieveTransformOptionByPropertyName (TransformOptionGroup transformOptionGroup, String propertyName, String propertyType) - { - Iterator iterator = transformOptionGroup.getTransformOptions().iterator(); - - List transformOptionsList = new ArrayList<>(); - while(iterator.hasNext()) - { - transformOptionsList.add(iterator.next()); - } - - for (TransformOption t : transformOptionsList) - { - if (t instanceof TransformOptionValue) - { - TransformOptionValue value = (TransformOptionValue) t; - if (propertyType.equalsIgnoreCase("TransformOptionValue")) - { - if (value.getName().equalsIgnoreCase(propertyName)) - return value; - } - else - { - if (value.getName().contains(propertyName)) - return transformOptionGroup; - } - } - else - { - TransformOption result = retrieveTransformOptionByPropertyName((TransformOptionGroup)t, propertyName, propertyType); - if (result != null) - return result; - } - } - return null; - } - - private boolean containsTransformOptionValueName (TransformOptionGroup transformOptionGroup, String propertyName) - { - if (retrieveTransformOptionByPropertyName(transformOptionGroup, propertyName, "TransformOptionValue") != null) - return true; - return false; - } - - private boolean containsTransformOptionGroupeName (TransformOptionGroup transformOptionGroup, String propertyName) - { - if (retrieveTransformOptionByPropertyName(transformOptionGroup, propertyName, "TransformOptionGroup") != null) - return true; - return false; - } - - protected int getExpectedTransformsForTestJsonPipeline() - { - return 4; - } - - private int countSupportedTransforms(boolean unique) - { - int count = 0; - int uniqueCount = 0; - for (ConcurrentMap> targetMap : registry.getData().transformers.values()) - { - for (List supportedTransforms : targetMap.values()) - { - uniqueCount++; - count += supportedTransforms.size(); - } - } - return unique ? uniqueCount : count; - } - - @Test - public void testOptionalGroups() - { - TransformOptionGroup transformOptionGroup = - new TransformOptionGroup(true, Set.of( - new TransformOptionValue(false, "1"), - new TransformOptionValue(true, "2"), - new TransformOptionGroup(false, Set.of( - new TransformOptionValue(false, "3.1"), - new TransformOptionValue(false, "3.2"), - new TransformOptionValue(false, "3.3"))), - new TransformOptionGroup(false, Set.of( // OPTIONAL - new TransformOptionValue(false, "4.1"), - new TransformOptionValue(true, "4.2"), - new TransformOptionValue(false, "4.3"))))); - - assertAddToPossibleOptions(transformOptionGroup, "", "1, 2", "2"); - assertAddToPossibleOptions(transformOptionGroup, "1", "1, 2", "2"); - assertAddToPossibleOptions(transformOptionGroup, "2", "1, 2", "2"); - assertAddToPossibleOptions(transformOptionGroup, "2, 3.2", "1, 2, 3.1, 3.2, 3.3", "2"); - assertAddToPossibleOptions(transformOptionGroup, "2, 4.1", "1, 2, 4.1, 4.2, 4.3", "2, 4.2"); - assertAddToPossibleOptions(transformOptionGroup, "2, 4.2", "1, 2, 4.1, 4.2, 4.3", "2, 4.2"); - } - - @Test - public void testRequiredGroup() - { - TransformOptionGroup transformOptionGroup = - new TransformOptionGroup(true, Set.of( - new TransformOptionValue(false, "1"), - new TransformOptionValue(true, "2"), - new TransformOptionGroup(false, Set.of( - new TransformOptionValue(false, "3.1"), - new TransformOptionValue(false, "3.2"), - new TransformOptionValue(false, "3.3"))), - new TransformOptionGroup(true, Set.of( // REQUIRED - new TransformOptionValue(false, "4.1"), - new TransformOptionValue(true, "4.2"), - new TransformOptionValue(false, "4.3"))))); - - assertAddToPossibleOptions(transformOptionGroup, "", "1, 2, 4.1, 4.2, 4.3", "2, 4.2"); - assertAddToPossibleOptions(transformOptionGroup, "1", "1, 2, 4.1, 4.2, 4.3", "2, 4.2"); - assertAddToPossibleOptions(transformOptionGroup, "2, 3.2", "1, 2, 3.1, 3.2, 3.3, 4.1, 4.2, 4.3", "2, 4.2"); - assertAddToPossibleOptions(transformOptionGroup, "2, 4.1", "1, 2, 4.1, 4.2, 4.3", "2, 4.2"); - assertAddToPossibleOptions(transformOptionGroup, "2, 4.2", "1, 2, 4.1, 4.2, 4.3", "2, 4.2"); - } - - @Test - public void testNesstedGrpups() - { - TransformOptionGroup transformOptionGroup = - new TransformOptionGroup(false, Set.of( - new TransformOptionGroup(false, Set.of( - new TransformOptionValue(false, "1"), - new TransformOptionGroup(false, Set.of( - new TransformOptionValue(false, "1.2"), - new TransformOptionGroup(false, Set.of( - new TransformOptionValue(false, "1.2.3"))))))), - new TransformOptionGroup(false, Set.of( - new TransformOptionValue(false, "2"), - new TransformOptionGroup(false, Set.of( - new TransformOptionValue(false, "2.2"), - new TransformOptionGroup(false, Set.of( - new TransformOptionGroup(false, Set.of( - new TransformOptionValue(false, "2.2.1.2"))))))))), - new TransformOptionGroup(false, Set.of( - new TransformOptionValue(true, "3"), // REQUIRED - new TransformOptionGroup(false, Set.of( - new TransformOptionGroup(false, Set.of( - new TransformOptionGroup(false, Set.of( - new TransformOptionValue(false, "3.1.1.2"))))))))), - new TransformOptionGroup(false, Set.of( - new TransformOptionValue(false, "4"), - new TransformOptionGroup(true, Set.of( // REQUIRED - new TransformOptionGroup(false, Set.of( - new TransformOptionGroup(false, Set.of( - new TransformOptionValue(false, "4.1.1.2"))))))))), - new TransformOptionGroup(false, Set.of( - new TransformOptionValue(false, "5"), - new TransformOptionGroup(false, Set.of( - new TransformOptionGroup(true, Set.of( // REQUIRED - new TransformOptionGroup(false, Set.of( - new TransformOptionValue(false, "5.1.1.2"))))))))), - new TransformOptionGroup(false, Set.of( - new TransformOptionValue(false, "6"), - new TransformOptionGroup(false, Set.of( - new TransformOptionGroup(false, Set.of( - new TransformOptionGroup(true, Set.of( // REQUIRED - new TransformOptionValue(false, "6.1.1.2"))))))))), - new TransformOptionGroup(false, Set.of( - new TransformOptionValue(false, "7"), - new TransformOptionGroup(false, Set.of( - new TransformOptionGroup(false, Set.of( - new TransformOptionGroup(false, Set.of( - new TransformOptionValue(true, "7.1.1.2"))))))))) // REQUIRED - )); - - assertAddToPossibleOptions(transformOptionGroup, "", "", ""); - assertAddToPossibleOptions(transformOptionGroup, "1", "1", ""); - assertAddToPossibleOptions(transformOptionGroup, "1, 7", "1, 7", ""); - assertAddToPossibleOptions(transformOptionGroup, "1, 7.1.1.2", "1, 7, 7.1.1.2", "7.1.1.2"); - assertAddToPossibleOptions(transformOptionGroup, "1, 6", "1, 6", ""); - assertAddToPossibleOptions(transformOptionGroup, "1, 6.1.1.2", "1, 6, 6.1.1.2", ""); - assertAddToPossibleOptions(transformOptionGroup, "1, 5", "1, 5", ""); - assertAddToPossibleOptions(transformOptionGroup, "1, 5.1.1.2", "1, 5, 5.1.1.2", ""); - assertAddToPossibleOptions(transformOptionGroup, "1, 4", "1, 4", ""); - assertAddToPossibleOptions(transformOptionGroup, "1, 4.1.1.2", "1, 4, 4.1.1.2", ""); - assertAddToPossibleOptions(transformOptionGroup, "1, 3", "1, 3", "3"); - assertAddToPossibleOptions(transformOptionGroup, "1, 3.1.1.2", "1, 3, 3.1.1.2", "3"); - - assertAddToPossibleOptions(transformOptionGroup, "2", "2", ""); - assertAddToPossibleOptions(transformOptionGroup, "2, 2.2", "2, 2.2", ""); - assertAddToPossibleOptions(transformOptionGroup, "3", "3", "3"); - assertAddToPossibleOptions(transformOptionGroup, "3.1.1.2", "3, 3.1.1.2", "3"); - } - - @Test - public void testSupportedOptions() - { - assertIsSupported("a", "a, B, c", "required option B is missing"); - assertIsSupported("", "a, B, c", "required option B is missing"); - assertIsSupported("B", "a, B, c", null); - assertIsSupported("B, c", "a, B, c", null); - assertIsSupported("B, a, c", "a, B, c", null); - - assertIsSupported("B, d", "a, B, c", "there is an extra option d"); - assertIsSupported("B, c, d", "a, B, c", "there is an extra option d"); - assertIsSupported("d", "a, B, c", "required option B is missing and there is an extra option d"); - - assertIsSupported("a", "a, b, c", null); - assertIsSupported("", "a, b, c", null); - assertIsSupported("a, b, c", "a, b, c", null); - } - - @Test - public void testNoActualOptions() throws Exception - { - assertTransformOptions(Set.of( - new TransformOptionValue(false, "option1"), - new TransformOptionValue(false, "option2"))); - } - - @Test - public void testNoTrasformOptions() throws Exception - { - assertTransformOptions(Collections.emptySet()); - assertTransformOptions(null); - } - - @Test - public void testSupported() throws Exception - { - transformer = new InlineTransformer("name", - Set.of( - new TransformOptionValue(false, "page"), - new TransformOptionValue(false, "width"), - new TransformOptionValue(false, "height")), - Set.of( - new SupportedSourceAndTarget(DOC, GIF, 102400), - new SupportedSourceAndTarget(DOC, JPEG, -1), - new SupportedSourceAndTarget(MSG, GIF, -1))); - - assertSupported(DOC, 1024, GIF, null, null); - assertSupported(DOC, 102400, GIF, null, null); - assertSupported(DOC, 102401, GIF, null, "source is too large"); - assertSupported(DOC, 1024, JPEG, null, null); - assertSupported(GIF, 1024, DOC, null, GIF+" is not a source of this transformer"); - assertSupported(MSG, 1024, GIF, null, null); - assertSupported(MSG, 1024, JPEG, null, MSG+" to "+JPEG+" is not supported by this transformer"); - - assertSupported(DOC, 1024, GIF, buildActualOptions("page, width"), null); - assertSupported(DOC, 1024, GIF, buildActualOptions("page, width, startPage"), "startPage is not an option"); - } - - @Test - public void testCache() - { - // Note: transformNames are an alias for a set of actualOptions and the target mimetpe. The source mimetype may change. - transformer = new InlineTransformer("name", - Set.of( - new TransformOptionValue(false, "page"), - new TransformOptionValue(false, "width"), - new TransformOptionValue(false, "height")), - Set.of( - new SupportedSourceAndTarget(DOC, GIF, 102400), - new SupportedSourceAndTarget(MSG, GIF, -1))); - - registry.register(transformer, getBaseUrl(transformer), getClass().getName()); - - assertSupported(DOC, 1024, GIF, null, "doclib", ""); - assertSupported(MSG, 1024, GIF, null, "doclib", ""); - - assertEquals(102400L, registry.getMaxSize(DOC, GIF, null, "doclib")); - assertEquals(-1L, registry.getMaxSize(MSG, GIF, null, "doclib")); - - // Change the cached value and try and check we are now using the cached value. - List supportedTransforms = registry.getData().cachedSupportedTransformList.get("doclib").get(DOC); - supportedTransforms.get(0).maxSourceSizeBytes = 1234L; - assertEquals(1234L, registry.getMaxSize(DOC, GIF, null, "doclib")); - } - - @Test - public void testGetTransformerName() throws Exception - { - InlineTransformer t1 = new InlineTransformer("transformer1", null, - Set.of(new SupportedSourceAndTarget(MSG, GIF, 100, 50))); - InlineTransformer t2 = new InlineTransformer("transformer2", null, - Set.of(new SupportedSourceAndTarget(MSG, GIF, 200, 60))); - InlineTransformer t3 = new InlineTransformer("transformer3", null, - Set.of(new SupportedSourceAndTarget(MSG, GIF, 200, 40))); - InlineTransformer t4 = new InlineTransformer("transformer4", null, - Set.of(new SupportedSourceAndTarget(MSG, GIF, -1, 100))); - InlineTransformer t5 = new InlineTransformer("transformer5", null, - Set.of(new SupportedSourceAndTarget(MSG, GIF, -1, 80))); - - Map actualOptions = null; - - // Select on size - priority is ignored - assertTransformerName(MSG, 100, GIF, actualOptions, "transformer1", t1, t2); - assertTransformerName(MSG, 150, GIF, actualOptions, "transformer2", t1, t2); - assertTransformerName(MSG, 250, GIF, actualOptions, null, t1, t2); - // Select on priority - t1, t2 and t4 are discarded. - // t3 is a higher priority and has a larger size than t1 and t2. - // Similar story fo t4 with t5. - assertTransformerName(MSG, 100, GIF, actualOptions, "transformer3", t1, t2, t3, t4, t5); - assertTransformerName(MSG, 200, GIF, actualOptions, "transformer3", t1, t2, t3, t4, t5); - // Select on size and priority, t1 and t2 discarded - assertTransformerName(MSG, 200, GIF, actualOptions, "transformer3", t1, t2, t3, t4); - assertTransformerName(MSG, 300, GIF, actualOptions, "transformer4", t1, t2, t3, t4); - assertTransformerName(MSG, 300, GIF, actualOptions, "transformer5", t1, t2, t3, t4, t5); - } - - @Test - public void testMultipleTransformers() throws Exception - { - InlineTransformer transformer1 = new InlineTransformer("transformer1", - Set.of( - new TransformOptionValue(false, "page"), - new TransformOptionValue(false, "width"), - new TransformOptionValue(false, "height")), - Set.of( - new SupportedSourceAndTarget(DOC, GIF, 102400), - new SupportedSourceAndTarget(DOC, JPEG, -1), - new SupportedSourceAndTarget(MSG, GIF, -1))); - - InlineTransformer transformer2 = new InlineTransformer("transformer2", - Set.of( - new TransformOptionValue(false, "opt1"), - new TransformOptionValue(false, "opt2")), - Set.of( - new SupportedSourceAndTarget(PDF, GIF, -1), - new SupportedSourceAndTarget(PPT, JPEG, -1))); - - InlineTransformer transformer3 = new InlineTransformer("transformer3", - Set.of( - new TransformOptionValue(false, "opt1")), - Set.of( - new SupportedSourceAndTarget(DOC, GIF, -1))); - - Map actualOptions = null; - - assertSupported(DOC, 1024, GIF, actualOptions, null, transformer1); - assertSupported(DOC, 1024, GIF, actualOptions, null, transformer1, transformer2); - assertSupported(DOC, 1024, GIF, actualOptions, null, transformer1, transformer2, transformer3); - - assertSupported(DOC, 102401, GIF, null, "source is too large", transformer1); - assertSupported(DOC, 102401, GIF, null, null, transformer1, transformer3); - - assertSupported(PDF, 1024, GIF, actualOptions, "Only transformer2 supports these mimetypes", transformer1); - assertSupported(PDF, 1024, GIF, actualOptions, null, transformer1, transformer2); - assertSupported(PDF, 1024, GIF, actualOptions, null, transformer1, transformer2, transformer3); - - actualOptions = buildActualOptions("opt1"); - assertSupported(PDF, 1024, GIF, actualOptions, "Only transformer2/4 supports these options", transformer1); - assertSupported(PDF, 1024, GIF, actualOptions, null, transformer1, transformer2); - assertSupported(PDF, 1024, GIF, actualOptions, null, transformer1, transformer2, transformer3); - assertSupported(PDF, 1024, GIF, actualOptions, "transformer4 supports opt1 but not the source mimetype ", transformer1, transformer3); - } - - @Test - public void testPipeline() throws Exception - { - InlineTransformer transformer1 = new InlineTransformer("transformer1", - null, // there are no options - Set.of( - new SupportedSourceAndTarget(DOC, PDF, -1), - new SupportedSourceAndTarget(MSG, PDF, -1))); - - InlineTransformer transformer2 = new InlineTransformer("transformer2", - Set.of( - new TransformOptionValue(false, "page"), - new TransformOptionValue(false, "width"), - new TransformOptionValue(false, "height")), - Set.of( - new SupportedSourceAndTarget(PDF, GIF, -1), - new SupportedSourceAndTarget(PDF, JPEG, -1))); - - buildPipelineTransformer(transformer1, transformer2); - - assertSupported(DOC, 1024, GIF, null, null); - assertSupported(DOC, 1024, JPEG, null, null); - assertSupported(GIF, 1024, DOC, null, GIF+" is not a source of this transformer"); - assertSupported(MSG, 1024, GIF, null, null); - assertSupported(MSG, 1024, JPEG, null, MSG+" to "+JPEG+" is not supported by this transformer"); - - // Now try the options - assertSupported(DOC, 1024, GIF, buildActualOptions("page, width"), null); - assertSupported(DOC, 1024, GIF, buildActualOptions("page, width, startPage"), "startPage is not an option"); - - // Add options to the first transformer - transformer1.setTransformOptions(Set.of( - new TransformOptionValue(false, "startPage"), - new TransformOptionValue(false, "endPage"))); - buildPipelineTransformer(transformer1, transformer2); - - assertSupported(DOC, 1024, GIF, buildActualOptions("page, width"), null); - assertSupported(DOC, 1024, GIF, buildActualOptions("page, width, startPage"), null); - } - - private void buildPipelineTransformer(InlineTransformer transformer1, InlineTransformer transformer2) - { - transformer = builder.buildPipeLine("transformer1", - Set.of( - new SupportedSourceAndTarget(DOC, GIF, -1), - new SupportedSourceAndTarget(DOC, JPEG, -1), - new SupportedSourceAndTarget(MSG, GIF, -1)), - Arrays.asList( - new ChildTransformer(false, transformer1), - new ChildTransformer(true, transformer2))); - } -} \ No newline at end of file diff --git a/src/test/java/org/alfresco/transform/client/model/config/LocalTransformServiceRegistryConfigTest.java b/src/test/java/org/alfresco/transform/client/registry/LocalTransformServiceRegistryConfigTest.java similarity index 77% rename from src/test/java/org/alfresco/transform/client/model/config/LocalTransformServiceRegistryConfigTest.java rename to src/test/java/org/alfresco/transform/client/registry/LocalTransformServiceRegistryConfigTest.java index b9805c58b3..b8d48ab47b 100644 --- a/src/test/java/org/alfresco/transform/client/model/config/LocalTransformServiceRegistryConfigTest.java +++ b/src/test/java/org/alfresco/transform/client/registry/LocalTransformServiceRegistryConfigTest.java @@ -23,12 +23,15 @@ * along with Alfresco. If not, see . * #L% */ -package org.alfresco.transform.client.model.config; +package org.alfresco.transform.client.registry; import com.fasterxml.jackson.databind.ObjectMapper; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.transform.LocalTransformServiceRegistry; import org.alfresco.repo.content.transform.TransformerDebug; +import org.alfresco.transform.client.model.config.SupportedSourceAndTarget; +import org.alfresco.transform.client.model.config.TransformOption; +import org.alfresco.transform.client.model.config.Transformer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.Before; @@ -43,12 +46,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Set; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; /** * Extends the {@link TransformServiceRegistryConfigTest} (used to test the config received from the Transform Service) @@ -115,12 +118,7 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg } } - protected TestLocalTransformServiceRegistry registry; - - private Properties properties = new Properties(); - - @Mock private TransformerDebug transformerDebug; - @Mock private MimetypeMap mimetypeMap; + private static Log log = LogFactory.getLog(LocalTransformServiceRegistry.class); private static final String LOCAL_TRANSFORM_SERVICE_CONFIG = "alfresco/local-transform-service-config-test.json"; private static final String LOCAL_TRANSFORM_SERVICE_CONFIG_PIPELINE = "alfresco/local-transform-service-config-pipeline-test.json"; @@ -129,7 +127,15 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg private static final String LOCAL_TRANSFORM = "localTransform."; private static final String URL = ".url"; - private static Log log = LogFactory.getLog(LocalTransformServiceRegistry.class); + private Map> mapOfTransformOptions; + private List transformerList; + + protected TestLocalTransformServiceRegistry registry; + + private Properties properties = new Properties(); + + @Mock private TransformerDebug transformerDebug; + @Mock private MimetypeMap mimetypeMap; private Map> imagemagickSupportedTransformation; private Map> tikaSupportedTransformation; @@ -187,20 +193,14 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg } /** - * Reads and loads localTransforms from LOCAL_TRANSFORM_SERVICE_CONFIG config file. - * @return List list of local transformers. + * Loads localTransforms from the LOCAL_TRANSFORM_SERVICE_CONFIG config file. */ - private List retrieveLocalTransformList() + private void retrieveLocalTransformList() { - try { - CombinedConfig combinedConfig = new CombinedConfig(log); - combinedConfig.addLocalConfig(LOCAL_TRANSFORM_SERVICE_CONFIG); - return combinedConfig.getTransforms(); - } catch (IOException e) { - log.error("Could not read LocalTransform config file"); - fail(); - } - return null; + CombinedConfig combinedConfig = new CombinedConfig(log); + combinedConfig.addLocalConfig(LOCAL_TRANSFORM_SERVICE_CONFIG); + mapOfTransformOptions = combinedConfig.combinedTransformOptions; + transformerList = combinedConfig.combinedTransformers; } /** @@ -280,11 +280,24 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg officeToImageViaPdfSupportedTransformation.put("application/vnd.ms-outlook", targetMimetype); } - protected String getBaseUrl(InlineTransformer transformer) + @Override + protected String getBaseUrl(Transformer transformer) { return LOCAL_TRANSFORM+transformer.getTransformerName()+".url"; } + + private int countTopLevelOptions(Set transformOptionNames) + { + int i = 0; + for (String name: transformOptionNames) + { + Set transformOptions = mapOfTransformOptions.get(name); + i += transformOptions.size(); + } + return i; + } + @Test public void testReadWriteJson() throws IOException { @@ -294,7 +307,8 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg @Test public void testReadJsonConfig() { - List transformerList = retrieveLocalTransformList(); + retrieveLocalTransformList(); + // Assert expected size of the transformers. assertNotNull("Transformer list is null.", transformerList); assertEquals("Unexpected number of transformers retrieved", 5, transformerList.size()); @@ -309,18 +323,20 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg for (CombinedConfig.TransformAndItsOrigin t : transformerList) { - assertTrue(t.transform.getTransformerName() + " should be an expected local transformer.", listOfExpectedTransformersName.contains(t.transform.getTransformerName())); - listOfExpectedTransformersName.remove(t.transform.getTransformerName()); + assertTrue(t.transformer.getTransformerName() + " should be an expected local transformer.", listOfExpectedTransformersName.contains(t.transformer.getTransformerName())); + listOfExpectedTransformersName.remove(t.transformer.getTransformerName()); - switch (t.transform.getTransformerName()) + switch (t.transformer.getTransformerName()) { case "imagemagick": - assertEquals(t.transform.getTransformerName() + " incorrect number of supported transform", 14, t.transform.getSupportedSourceAndTargetList().size()); - assertEquals( t.transform.getTransformerName() + "incorrect number of transform options", 6, t.transform.getTransformOptions().size()); - assertEquals(t.transform.getTransformerName() + " expected to not be a transformer pipeline", t.transform.getTransformerPipeline().size(), 0); + assertEquals(t.transformer.getTransformerName() + " incorrect number of supported transform", 14, t.transformer.getSupportedSourceAndTargetList().size()); + assertEquals( t.transformer.getTransformerName() + "incorrect number of transform option names", 1, t.transformer.getTransformOptions().size()); + assertEquals( t.transformer.getTransformerName() + "incorrect number of transform options", 6, countTopLevelOptions(t.transformer.getTransformOptions())); + assertEquals(t.transformer.getTransformerName() + " expected to not be a transformer pipeline", t.transformer.getTransformerPipeline().size(), 0); + assertEquals(t.transformer.getTransformerName() + " expected to not be a failover pipeline", t.transformer.getTransformerFailover().size(), 0); //Test supportedSourceAndTargetList - for ( SupportedSourceAndTarget ssat: t.transform.getSupportedSourceAndTargetList()) + for ( SupportedSourceAndTarget ssat: t.transformer.getSupportedSourceAndTargetList()) { assertTrue(ssat.getSourceMediaType() + " not expected to be a supported transform source.", imagemagickSupportedTransformation.containsKey(ssat.getSourceMediaType())); assertTrue(ssat.getTargetMediaType() + " not expected to be a supported transform target for " + ssat.getSourceMediaType(), imagemagickSupportedTransformation.get(ssat.getSourceMediaType()).contains(ssat.getTargetMediaType())); @@ -328,12 +344,14 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg break; case "tika": - assertEquals(t.transform.getTransformerName() + " incorrect number of supported transform", 8, t.transform.getSupportedSourceAndTargetList().size()); - assertEquals( t.transform.getTransformerName() + "incorrect number of transform options", 5, t.transform.getTransformOptions().size()); - assertEquals(t.transform.getTransformerName() + " expected to not be a transformer pipeline", t.transform.getTransformerPipeline().size(), 0); + assertEquals(t.transformer.getTransformerName() + " incorrect number of supported transform", 8, t.transformer.getSupportedSourceAndTargetList().size()); + assertEquals( t.transformer.getTransformerName() + "incorrect number of transform option names", 1, t.transformer.getTransformOptions().size()); + assertEquals( t.transformer.getTransformerName() + "incorrect number of transform options", 5, countTopLevelOptions(t.transformer.getTransformOptions())); + assertEquals(t.transformer.getTransformerName() + " expected to not be a transformer pipeline", t.transformer.getTransformerPipeline().size(), 0); + assertEquals(t.transformer.getTransformerName() + " expected to not be a failover pipeline", t.transformer.getTransformerFailover().size(), 0); //Test supportedSourceAndTargetList - for ( SupportedSourceAndTarget ssat: t.transform.getSupportedSourceAndTargetList()) + for ( SupportedSourceAndTarget ssat: t.transformer.getSupportedSourceAndTargetList()) { assertTrue(ssat.getSourceMediaType() + " not expected to be a supported transform source.", tikaSupportedTransformation.containsKey(ssat.getSourceMediaType())); assertTrue(ssat.getTargetMediaType() + " not expected to be a supported transform target for " + ssat.getSourceMediaType(), tikaSupportedTransformation.get(ssat.getSourceMediaType()).contains(ssat.getTargetMediaType())); @@ -341,12 +359,14 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg break; case "pdfrenderer": - assertEquals(t.transform.getTransformerName() + " incorrect number of supported transform", 1, t.transform.getSupportedSourceAndTargetList().size()); - assertEquals( t.transform.getTransformerName() + "incorrect number of transform options", 5, t.transform.getTransformOptions().size()); - assertEquals(t.transform.getTransformerName() + " expected to not be a transformer pipeline", t.transform.getTransformerPipeline().size(), 0); + assertEquals(t.transformer.getTransformerName() + " incorrect number of supported transform", 1, t.transformer.getSupportedSourceAndTargetList().size()); + assertEquals( t.transformer.getTransformerName() + "incorrect number of transform option names", 1, t.transformer.getTransformOptions().size()); + assertEquals( t.transformer.getTransformerName() + "incorrect number of transform options", 5, countTopLevelOptions(t.transformer.getTransformOptions())); + assertEquals(t.transformer.getTransformerName() + " expected to not be a transformer pipeline", t.transformer.getTransformerPipeline().size(), 0); + assertEquals(t.transformer.getTransformerName() + " expected to not be a failover pipeline", t.transformer.getTransformerFailover().size(), 0); //Test supportedSourceAndTargetList - for ( SupportedSourceAndTarget ssat: t.transform.getSupportedSourceAndTargetList()) + for ( SupportedSourceAndTarget ssat: t.transformer.getSupportedSourceAndTargetList()) { assertTrue(ssat.getSourceMediaType() + " not expected to be a supported transform source.", pdfRendererSupportedTransformation.containsKey(ssat.getSourceMediaType())); assertTrue(ssat.getTargetMediaType() + " not expected to be a supported transform target for " + ssat.getSourceMediaType(), pdfRendererSupportedTransformation.get(ssat.getSourceMediaType()).contains(ssat.getTargetMediaType())); @@ -354,12 +374,14 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg break; case "libreoffice": - assertEquals(t.transform.getTransformerName() + " incorrect number of supported transform", 9, t.transform.getSupportedSourceAndTargetList().size()); - assertEquals( t.transform.getTransformerName() + "incorrect number of transform options", t.transform.getTransformOptions().size(), 0); - assertEquals(t.transform.getTransformerName() + " expected to not be a transformer pipeline", t.transform.getTransformerPipeline().size(), 0); + assertEquals(t.transformer.getTransformerName() + " incorrect number of supported transform", 9, t.transformer.getSupportedSourceAndTargetList().size()); + assertEquals( t.transformer.getTransformerName() + "incorrect number of transform option names", 0, t.transformer.getTransformOptions().size()); + assertEquals( t.transformer.getTransformerName() + "incorrect number of transform options", 0, countTopLevelOptions(t.transformer.getTransformOptions())); + assertEquals(t.transformer.getTransformerName() + " expected to not be a transformer pipeline", t.transformer.getTransformerPipeline().size(), 0); + assertEquals(t.transformer.getTransformerName() + " expected to not be a failover pipeline", t.transformer.getTransformerFailover().size(), 0); //Test supportedSourceAndTargetList - for ( SupportedSourceAndTarget ssat: t.transform.getSupportedSourceAndTargetList()) + for ( SupportedSourceAndTarget ssat: t.transformer.getSupportedSourceAndTargetList()) { assertTrue(ssat.getSourceMediaType() + " not expected to be a supported transform source.", libreofficeSupportedTransformation.containsKey(ssat.getSourceMediaType())); assertTrue(ssat.getTargetMediaType() + " not expected to be a supported transform target for " + ssat.getSourceMediaType(), libreofficeSupportedTransformation.get(ssat.getSourceMediaType()).contains(ssat.getTargetMediaType())); @@ -367,12 +389,13 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg break; case "officeToImageViaPdf": - assertEquals(t.transform.getTransformerName() + " incorrect number of supported transform", 28, t.transform.getSupportedSourceAndTargetList().size()); - assertEquals( t.transform.getTransformerName() + "incorrect number of transform options", 2, t.transform.getTransformOptions().size()); - assertEquals(t.transform.getTransformerName() + " expected to be a transformer pipeline", t.transform.getTransformerPipeline().size(), 3); + assertEquals(t.transformer.getTransformerName() + " incorrect number of supported transform", 28, t.transformer.getSupportedSourceAndTargetList().size()); + assertEquals( t.transformer.getTransformerName() + "incorrect number of transform option names", 2, t.transformer.getTransformOptions().size()); + assertEquals( t.transformer.getTransformerName() + "incorrect number of transform options", 11, countTopLevelOptions(t.transformer.getTransformOptions())); + assertEquals(t.transformer.getTransformerName() + " expected to be a transformer pipeline", t.transformer.getTransformerPipeline().size(), 3); //Test supportedSourceAndTargetList - for ( SupportedSourceAndTarget ssat: t.transform.getSupportedSourceAndTargetList()) + for ( SupportedSourceAndTarget ssat: t.transformer.getSupportedSourceAndTargetList()) { assertTrue(ssat.getSourceMediaType() + " not expected to be a supported transform source.", officeToImageViaPdfSupportedTransformation.containsKey(ssat.getSourceMediaType())); assertTrue(ssat.getTargetMediaType() + " not expected to be a supported transform target for " + ssat.getSourceMediaType(), officeToImageViaPdfSupportedTransformation.get(ssat.getSourceMediaType()).contains(ssat.getTargetMediaType())); @@ -386,13 +409,14 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg @Test public void testReadTransformProperties() { - List transformerList = retrieveLocalTransformList(); + retrieveLocalTransformList(); + assertNotNull("Transformer list is null.", transformerList); for (CombinedConfig.TransformAndItsOrigin t : transformerList) { - if(t.transform.getTransformerPipeline() == null) + if(t.transformer.getTransformerPipeline() == null) { - assertNotNull(t.transform.getTransformerName()+ " JVM property not set.", System.getProperty(LOCAL_TRANSFORM + t.transform.getTransformerName() + URL)); + assertNotNull(t.transformer.getTransformerName()+ " JVM property not set.", System.getProperty(LOCAL_TRANSFORM + t.transformer.getTransformerName() + URL)); } } assertEquals("Unexpected pdfrenderer JVM property value", "http://localhost:8090/", System.getProperty(LOCAL_TRANSFORM + "pdfrenderer" + URL)); @@ -402,9 +426,9 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg for (CombinedConfig.TransformAndItsOrigin t : transformerList) { - if(t.transform.getTransformerPipeline() == null) + if(t.transformer.getTransformerPipeline() == null) { - assertNotNull(t.transform.getTransformerName()+ " alfresco-global property not set.", properties.getProperty(LOCAL_TRANSFORM + t.transform.getTransformerName() + URL)); + assertNotNull(t.transformer.getTransformerName()+ " alfresco-global property not set.", properties.getProperty(LOCAL_TRANSFORM + t.transformer.getTransformerName() + URL)); } } assertEquals("Unexpected pdfrenderer alfresco-global property value", "http://localhost:8090/", properties.getProperty(LOCAL_TRANSFORM + "pdfrenderer" + URL)); diff --git a/src/test/java/org/alfresco/transform/client/registry/TransformServiceRegistryConfigTest.java b/src/test/java/org/alfresco/transform/client/registry/TransformServiceRegistryConfigTest.java new file mode 100644 index 0000000000..40abf62ba8 --- /dev/null +++ b/src/test/java/org/alfresco/transform/client/registry/TransformServiceRegistryConfigTest.java @@ -0,0 +1,287 @@ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2019 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 . + * #L% + */ +package org.alfresco.transform.client.registry; + +import static java.util.Collections.emptyMap; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.transform.client.model.config.TransformOption; +import org.alfresco.transform.client.model.config.TransformOptionGroup; +import org.alfresco.transform.client.model.config.TransformOptionValue; +import org.alfresco.transform.client.registry.SupportedTransform; +import org.alfresco.transform.client.registry.TransformRegistryTest; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.log4j.Level; +import org.apache.log4j.LogManager; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Test the config received from the Transform Service about what it supports. + * + * @author adavis + */ +public class TransformServiceRegistryConfigTest extends TransformRegistryTest +{ + private static Log log = LogFactory.getLog(TransformServiceRegistryConfigTest.class); + + public static final String PNG = "image/png"; + public static final String TIFF = "image/tiff"; + + private static final String TRANSFORM_SERVICE_CONFIG = "alfresco/transform-service-config-test.json"; + private static final String TRANSFORM_SERVICE_CONFIG_PIPELINE = "alfresco/transform-service-config-pipeline-test.json"; + + public static final ObjectMapper JSON_OBJECT_MAPPER = new ObjectMapper(); + + @Before + @Override + public void setUp() throws Exception + { + super.setUp(); + LogManager.getLogger(TransformServiceRegistryConfigTest.class).setLevel(Level.DEBUG); + } + + @Override + protected TransformServiceRegistryImpl buildTransformServiceRegistryImpl() throws Exception + { + TransformServiceRegistryImpl registry = new TransformServiceRegistryImpl() + { + @Override + public boolean readConfig() throws IOException + { + return true; + } + + @Override + protected Log getLog() + { + return log; + } + }; + registry.setJsonObjectMapper(JSON_OBJECT_MAPPER); + registry.setCronExpression(null); // just read once + registry.afterPropertiesSet(); + return registry; + } + + @After + public void tearDown() + { + // shut down + } + + protected String getTransformServiceConfig() + { + return TRANSFORM_SERVICE_CONFIG; + } + + protected String getTransformServiceConfigPipeline() + { + return TRANSFORM_SERVICE_CONFIG_PIPELINE; + } + + private void register(String path) throws IOException + { + CombinedConfig combinedConfig = new CombinedConfig(log); + combinedConfig.addLocalConfig(path); + combinedConfig.register((TransformServiceRegistryImpl)registry); + } + + @Test + public void testJsonConfig() throws IOException + { + register(getTransformServiceConfig()); + + // Check the count of transforms supported + assertEquals("The number of UNIQUE source to target mimetypes transforms has changed. Config change?", + 60, countSupportedTransforms(true)); + assertEquals("The number of source to target mimetypes transforms has changed. " + + "There may be multiple transformers for the same combination. Config change?", + 60, countSupportedTransforms(false)); + + // Check a supported transform for each transformer. + assertSupported(DOC, 1234, PDF, emptyMap(), null, ""); // libreoffice + assertSupported(DOC, 1234, PDF, emptyMap(), null, ""); // libreoffice + assertSupported(PDF, 1234, PNG, emptyMap(), null, ""); // pdfrenderer + assertSupported(JPEG,1234, GIF, emptyMap(), null, ""); // imagemagick + assertSupported(MSG, 1234, TXT, emptyMap(), null, ""); // tika + assertSupported(MSG, 1234, GIF, emptyMap(), null, ""); // officeToImageViaPdf + + Map invalidPdfOptions = new HashMap<>(); + invalidPdfOptions.put("allowEnlargement", "false"); + assertSupported(DOC, 1234, PDF, invalidPdfOptions, null, "Invalid as there is a extra option"); + } + + @Test + public void testJsonPipeline() throws IOException + { + register(getTransformServiceConfigPipeline()); + + // Check the count of transforms supported + int expectedTransforms = getExpectedTransformsForTestJsonPipeline(); + assertEquals("The number of UNIQUE source to target mimetypes transforms has changed. Config change?", + expectedTransforms, countSupportedTransforms(true)); + assertEquals("The number of source to target mimetypes transforms has changed. " + + "There may be multiple transformers for the same combination. Config change?", + expectedTransforms, countSupportedTransforms(false)); + + // Check required and optional default correctly + Map> transformsToWord = + registry.getData().getTransforms().get(DOC); + List supportedTransforms = transformsToWord.get(GIF); + SupportedTransform supportedTransform = supportedTransforms.get(0); + + Set transformOptionsSet = supportedTransform.getTransformOptions().getTransformOptions(); + System.out.println("Nothing"); + + Iterator iterator = transformOptionsSet.iterator(); + assertTrue("Expected transform values", iterator.hasNext()); + // Because Set is unordered we don't know which TransformOptionGroup we retrieve + TransformOptionGroup transformOptions1 = (TransformOptionGroup)iterator.next(); + + assertTrue("Expected transform values", iterator.hasNext()); + TransformOptionGroup transformOptions2 = (TransformOptionGroup)iterator.next(); + + TransformOptionGroup imagemagick; + TransformOptionGroup pdf; + + if(containsTransformOptionValueName(transformOptions1, "alphaRemove")) + { + imagemagick = transformOptions1; + pdf = transformOptions2; + } + else + { + imagemagick = transformOptions2; + pdf = transformOptions1; + } + + TransformOptionValue alphaRemove = (TransformOptionValue)retrieveTransformOptionByPropertyName(imagemagick, "alphaRemove", "TransformOptionValue"); + TransformOptionGroup crop = (TransformOptionGroup)retrieveTransformOptionByPropertyName(imagemagick, "crop", "TransformOptionGroup"); + TransformOptionValue cropGravity = (TransformOptionValue)retrieveTransformOptionByPropertyName(crop, "cropGravity", "TransformOptionValue"); + TransformOptionValue cropWidth = (TransformOptionValue)retrieveTransformOptionByPropertyName(crop, "cropWidth", "TransformOptionValue"); + + assertTrue("The holding group should be required", supportedTransform.getTransformOptions().isRequired()); + assertFalse("imagemagick should be optional as it is not set", imagemagick.isRequired()); + assertFalse("pdf should be optional as required is not set", pdf.isRequired()); + assertEquals("alphaRemove", alphaRemove.getName()); + assertEquals("cropGravity", cropGravity.getName()); + assertEquals("cropWidth", cropWidth.getName()); + assertFalse("alphaRemove should be optional as required is not set", alphaRemove.isRequired()); + assertFalse("crop should be optional as required is not set", crop.isRequired()); + assertTrue("cropGravity should be required as it is set", cropGravity.isRequired()); + assertFalse("cropWidth should be optional as required is not set", cropWidth.isRequired()); + + // Check a supported transform for each transformer. + assertSupported(DOC,1234, GIF, emptyMap(), null, ""); + assertSupported(DOC,1234, PNG, emptyMap(), null, ""); + assertSupported(DOC,1234, JPEG, emptyMap(), null, ""); + assertSupported(DOC,1234, TIFF, emptyMap(), null, ""); + + Map actualOptions = new HashMap<>(); + actualOptions.put("thumbnail", "true"); + actualOptions.put("resizeWidth", "100"); + actualOptions.put("resizeHeight", "100"); + actualOptions.put("allowEnlargement", "false"); + actualOptions.put("maintainAspectRatio", "true"); + assertSupported(DOC,1234, PNG, actualOptions, null, ""); + } + + private TransformOption retrieveTransformOptionByPropertyName (TransformOptionGroup transformOptionGroup, String propertyName, String propertyType) + { + Iterator iterator = transformOptionGroup.getTransformOptions().iterator(); + + List transformOptionsList = new ArrayList<>(); + while(iterator.hasNext()) + { + transformOptionsList.add(iterator.next()); + } + + for (TransformOption t : transformOptionsList) + { + if (t instanceof TransformOptionValue) + { + TransformOptionValue value = (TransformOptionValue) t; + if (propertyType.equalsIgnoreCase("TransformOptionValue")) + { + if (value.getName().equalsIgnoreCase(propertyName)) + return value; + } + else + { + if (value.getName().contains(propertyName)) + return transformOptionGroup; + } + } + else + { + TransformOption result = retrieveTransformOptionByPropertyName((TransformOptionGroup)t, propertyName, propertyType); + if (result != null) + return result; + } + } + return null; + } + + private boolean containsTransformOptionValueName (TransformOptionGroup transformOptionGroup, String propertyName) + { + return retrieveTransformOptionByPropertyName(transformOptionGroup, propertyName, "TransformOptionValue") != null; + } + + protected int getExpectedTransformsForTestJsonPipeline() + { + return 4; + } + + private int countSupportedTransforms(boolean unique) + { + int count = 0; + int uniqueCount = 0; + for (Map> targetMap : registry.getData().getTransforms().values()) + { + for (List supportedTransforms : targetMap.values()) + { + uniqueCount++; + count += supportedTransforms.size(); + } + } + return unique ? uniqueCount : count; + } +} \ No newline at end of file