diff --git a/src/main/java/org/alfresco/repo/content/transform/AbstractLocalTransform.java b/src/main/java/org/alfresco/repo/content/transform/AbstractLocalTransform.java index cccccfbf1b..7dff7edb69 100644 --- a/src/main/java/org/alfresco/repo/content/transform/AbstractLocalTransform.java +++ b/src/main/java/org/alfresco/repo/content/transform/AbstractLocalTransform.java @@ -31,9 +31,14 @@ 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.TransformOption; +import org.alfresco.transform.client.model.config.TransformOptionGroup; +import org.alfresco.transform.client.model.config.TransformOptionValue; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -48,6 +53,7 @@ public abstract class AbstractLocalTransform implements LocalTransform protected final MimetypeService mimetypeService; protected final TransformerDebug transformerDebug; + protected final Set transformsTransformOptionNames = new HashSet<>(); private final LocalTransformServiceRegistry localTransformServiceRegistry; private final boolean strictMimeTypeCheck; private final Map> strictMimetypeExceptions; @@ -57,6 +63,7 @@ public abstract class AbstractLocalTransform implements LocalTransform AbstractLocalTransform(String name, TransformerDebug transformerDebug, MimetypeService mimetypeService, boolean strictMimeTypeCheck, Map> strictMimetypeExceptions, boolean retryTransformOnDifferentMimeType, + Set transformsTransformOptions, LocalTransformServiceRegistry localTransformServiceRegistry) { this.name = name; @@ -66,6 +73,8 @@ public abstract class AbstractLocalTransform implements LocalTransform this.strictMimetypeExceptions = strictMimetypeExceptions; this.retryTransformOnDifferentMimeType = retryTransformOnDifferentMimeType; this.localTransformServiceRegistry = localTransformServiceRegistry; + + addOptionNames(transformsTransformOptionNames, transformsTransformOptions); } public abstract boolean isAvailable(); @@ -77,6 +86,16 @@ public abstract class AbstractLocalTransform implements LocalTransform String renditionName, NodeRef sourceNodeRef) throws Exception; + public String getName() + { + return name; + } + + public Set getTransformsTransformOptionNames() + { + return transformsTransformOptionNames; + } + @Override public void transform(ContentReader reader, ContentWriter writer, Map transformOptions, String renditionName, NodeRef sourceNodeRef) @@ -98,6 +117,7 @@ public abstract class AbstractLocalTransform implements LocalTransform " target extension: " + targetExtension); } + transformOptions = getStrippedTransformOptions(transformOptions); transformWithDebug(reader, writer, transformOptions, renditionName, sourceNodeRef, sourceMimetype, targetMimetype, sourceExtension, targetExtension); @@ -111,10 +131,14 @@ public abstract class AbstractLocalTransform implements LocalTransform } else { - log.debug("Local transformer not available: \n" + - " source: " + reader + "\n" + - " target: " + writer + "\n" + - " options: " + transformOptions); + if (log.isDebugEnabled()) + { + transformOptions = getStrippedTransformOptions(transformOptions); + log.debug("Local transformer not available: \n" + + " source: " + reader + "\n" + + " target: " + writer + "\n" + + " options: " + transformOptions); + } } } @@ -224,7 +248,7 @@ public abstract class AbstractLocalTransform implements LocalTransform long sourceSizeInBytes = reader.getSize(); LocalTransform localTransform = localTransformServiceRegistry.getLocalTransform( - transformOptions, renditionName, differentType, targetMimetype, sourceSizeInBytes); + differentType, sourceSizeInBytes, targetMimetype, transformOptions, renditionName); if (localTransform == null) { transformerDebug.debug(" Failed", e); @@ -254,4 +278,54 @@ public abstract class AbstractLocalTransform implements LocalTransform } } } + + /** + * Returns a list of transform option names known to this transformer. When a transform is part of a pipeline or a + * failover, the rendition options may include options needed for other transforms. So that extra options are not + * passed to the T-Engine for this transform and rejected, {@link #getStrippedTransformOptions(Map)} removes them + * using the names obtained here. + */ + private static void addOptionNames(Set transformsTransformOptionNames, Set transformsTransformOptions) + { + for (TransformOption transformOption : transformsTransformOptions) + { + if (transformOption instanceof TransformOptionValue) + { + transformsTransformOptionNames.add(((TransformOptionValue)transformOption).getName()); + } + else + { + addOptionNames(transformsTransformOptionNames, ((TransformOptionGroup)transformOption).getTransformOptions()); + } + } + } + + /** + * Returns a subset of the supplied actual transform options from the rendition definition that are known to this + * transformer. The ones that will be passed to the T-Engine. It strips out extra ones. + * @param transformOptions the complete set of actual transform options. This will be returned if all options are + * known to this transformer. Otherwise a new Map is returned. + * @return the transformOptions to be past to the T-Engine. + */ + public Map getStrippedTransformOptions(Map transformOptions) + { + Set optionNames = transformOptions.keySet(); + if (transformsTransformOptionNames.containsAll(optionNames)) + { + return transformOptions; + } + + Map strippedTransformOptions = new HashMap<>(transformOptions.size()); + for (Map.Entry entry : transformOptions.entrySet()) + { + String key = entry.getKey(); + if (transformsTransformOptionNames.contains(key)) + { + String value = entry.getValue(); + strippedTransformOptions.put(key, value); + } + } + + return strippedTransformOptions; + } } 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 044fba82a2..055b3048e6 100644 --- a/src/main/java/org/alfresco/repo/content/transform/ArchiveContentTransformer.java +++ b/src/main/java/org/alfresco/repo/content/transform/ArchiveContentTransformer.java @@ -41,6 +41,8 @@ import org.apache.tika.parser.ParseContext; import org.apache.tika.parser.Parser; import org.apache.tika.parser.pkg.PackageParser; +import static org.alfresco.repo.rendition2.RenditionDefinition2.TARGET_ENCODING; + /** * This class transforms archive files (zip, tar etc) to text, which enables indexing * and searching of archives as well as webpreviewing. @@ -159,6 +161,6 @@ public class ArchiveContentTransformer extends TikaPoweredContentTransformer "includeContents", Boolean.toString(recurse), "sourceMimetype", sourceMimetype, "targetMimetype", targetMimetype, - "targetEncoding", targetEncoding); + TARGET_ENCODING, targetEncoding); } } diff --git a/src/main/java/org/alfresco/repo/content/transform/LocalFailoverTransform.java b/src/main/java/org/alfresco/repo/content/transform/LocalFailoverTransform.java new file mode 100644 index 0000000000..9fafefc060 --- /dev/null +++ b/src/main/java/org/alfresco/repo/content/transform/LocalFailoverTransform.java @@ -0,0 +1,159 @@ +/* + * #%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.repo.content.transform; + +import org.alfresco.repo.content.filestore.FileContentWriter; +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.TransformOption; +import org.alfresco.util.TempFileProvider; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Transformer that passes a document to a sequence of transforms until one succeeds. + * + * Instances are automatically created for transformers identified by alfresco/transform json files and returned from + * T-Engines which are themselves identified by global properties the match the pattern localTransform.<name>.url. + * The transforms take place in a separate process (typically a Docker container). + */ +public class LocalFailoverTransform extends AbstractLocalTransform +{ + private final List transformers = new ArrayList<>(); + + public LocalFailoverTransform(String name, TransformerDebug transformerDebug, + MimetypeService mimetypeService, boolean strictMimeTypeCheck, + Map> strictMimetypeExceptions, + boolean retryTransformOnDifferentMimeType, + Set transformsTransformOptions, + LocalTransformServiceRegistry localTransformServiceRegistry) + { + super(name, transformerDebug, mimetypeService, strictMimeTypeCheck, strictMimetypeExceptions, + retryTransformOnDifferentMimeType, transformsTransformOptions, localTransformServiceRegistry); + } + + @Override + public boolean isAvailable() + { + return true; + } + + public void addStepTransformer(LocalTransform stepTransformer) + { + transformers.add(stepTransformer); + } + + @Override + protected void transformImpl(ContentReader reader, + ContentWriter writer, Map transformOptions, + String sourceMimetype, String targetMimetype, + String sourceExtension, String targetExtension, + String renditionName, NodeRef sourceNodeRef) throws Exception + { + final String targetExt = mimetypeService.getExtension(targetMimetype); + + // We need to keep a reference to thrown exceptions as we're going to catch them and + // then move on to the next transformer. In the event that they all fail, we will throw + // the first exception. + Exception transformationException = null; + + for (int i = 0; i < transformers.size(); i++) + { + LocalTransform stepTransformer = transformers.get(i); + ContentWriter currentWriter = null; + File tempFile = null; + try + { + if (log.isDebugEnabled()) + { + log.debug("Transformation attempt " + (i+1) + " of " + transformers.size() + ": " + stepTransformer); + } + + // We can't know in advance which transformer in the sequence will work - if any. + // Therefore we can't write into the ContentWriter stream. + // So make a temporary file writer with the current transformer name. + tempFile = TempFileProvider.createTempFile( + "LocalFailoverTransformer_intermediate_" + stepTransformer.getClass().getSimpleName() + "_", + "." + targetExt); + currentWriter = new FileContentWriter(tempFile); + currentWriter.setMimetype(targetMimetype); + currentWriter.setEncoding(writer.getEncoding()); + + // attempt to transform + stepTransformer.transform(reader, currentWriter, transformOptions, renditionName, sourceNodeRef); + } + catch (Exception are) + { + if (transformationException == null) + { + transformationException = are; + } + else + { + // Don't log the first exception in full until the end as we're going to throw it and it will + // get logged again. + log.debug("The below exception is provided for information purposes only.", are); + } + + // Set a new reader to refresh the input stream. + reader = reader.getReader(); + // and move to the next transformer + continue; + } + + + if (transformationException == null) + { + log.debug("The following exception (from the first transformer) is provided for " + + "information purposes only as a later transformer succeeded.", transformationException); + } + + // No need to close input or output streams + // Now we must copy the content from the temporary file into the ContentWriter stream. + if (tempFile != null) + { + writer.putContent(tempFile); + } + + log.info("Transformation was successful"); + return; + } + + // At this point we have tried all transformers in the sequence without apparent success. + if (transformationException != null) + { + transformerDebug.debug(" No more transformations to failover to"); + log.debug("All transformations were unsuccessful. Throwing first exception.", transformationException); + throw transformationException; + } + } +} \ No newline at end of file diff --git a/src/main/java/org/alfresco/repo/content/transform/LocalPipelineTransform.java b/src/main/java/org/alfresco/repo/content/transform/LocalPipelineTransform.java index a387a18db1..d31dc4d921 100644 --- a/src/main/java/org/alfresco/repo/content/transform/LocalPipelineTransform.java +++ b/src/main/java/org/alfresco/repo/content/transform/LocalPipelineTransform.java @@ -30,6 +30,7 @@ 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.TransformOption; import org.alfresco.util.TempFileProvider; import java.io.File; @@ -59,10 +60,11 @@ public class LocalPipelineTransform extends AbstractLocalTransform MimetypeService mimetypeService, boolean strictMimeTypeCheck, Map> strictMimetypeExceptions, boolean retryTransformOnDifferentMimeType, + Set transformsTransformOptions, LocalTransformServiceRegistry localTransformServiceRegistry) { super(name, transformerDebug, mimetypeService, strictMimeTypeCheck, strictMimetypeExceptions, - retryTransformOnDifferentMimeType, localTransformServiceRegistry); + retryTransformOnDifferentMimeType, transformsTransformOptions, localTransformServiceRegistry); } @Override @@ -79,6 +81,11 @@ public class LocalPipelineTransform extends AbstractLocalTransform transformers.add(transformer); } + public LocalTransform getIntermediateTransformer(int i) + { + return i >= transformers.size() ? null : transformers.get(i).intermediateTransformer; + } + @Override protected void transformImpl(ContentReader reader, ContentWriter writer, Map transformOptions, 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 26a75d7c5e..2eb2b474ce 100644 --- a/src/main/java/org/alfresco/repo/content/transform/LocalTransformImpl.java +++ b/src/main/java/org/alfresco/repo/content/transform/LocalTransformImpl.java @@ -30,6 +30,7 @@ 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.TransformOption; import org.alfresco.util.Pair; import java.util.HashMap; @@ -38,6 +39,7 @@ import java.util.Set; import static org.alfresco.repo.rendition2.RenditionDefinition2.SOURCE_ENCODING; import static org.alfresco.repo.rendition2.RenditionDefinition2.SOURCE_NODE_REF; +import static org.alfresco.repo.rendition2.RenditionDefinition2.TARGET_ENCODING; /** * A local transformer using flat transform options. @@ -56,11 +58,12 @@ public class LocalTransformImpl extends AbstractLocalTransform MimetypeService mimetypeService, boolean strictMimeTypeCheck, Map> strictMimetypeExceptions, boolean retryTransformOnDifferentMimeType, + Set transformsTransformOptions, LocalTransformServiceRegistry localTransformServiceRegistry, String baseUrl, int startupRetryPeriodSeconds) { super(name, transformerDebug, mimetypeService, strictMimeTypeCheck, strictMimetypeExceptions, - retryTransformOnDifferentMimeType, localTransformServiceRegistry); + retryTransformOnDifferentMimeType, transformsTransformOptions, localTransformServiceRegistry); remoteTransformerClient = new RemoteTransformerClient(name, baseUrl); remoteTransformerClient.setStartupRetryPeriodSeconds(startupRetryPeriodSeconds); @@ -157,6 +160,13 @@ public class LocalTransformImpl extends AbstractLocalTransform transformOptions.put(SOURCE_NODE_REF, sourceNodeRef.toString()); } + // The targetEncoding is passed as an option if it is know to the transformer and has not been set. + if (transformOptions.get(TARGET_ENCODING) == null && transformsTransformOptionNames.contains(TARGET_ENCODING)) + { + String targetEncoding = writer.getEncoding(); + transformOptions.put(TARGET_ENCODING, targetEncoding); + } + // Build an array of option names and values and extract the timeout. long timeoutMs = 0; int nonOptions = transformOptions.containsKey(RenditionDefinition2.TIMEOUT) ? 1 : 0; 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 4f36af7255..ab87bf6a9e 100644 --- a/src/main/java/org/alfresco/repo/content/transform/LocalTransformServiceRegistry.java +++ b/src/main/java/org/alfresco/repo/content/transform/LocalTransformServiceRegistry.java @@ -33,11 +33,13 @@ import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; +import java.util.function.Consumer; 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.TransformOptionGroup; import org.alfresco.transform.client.registry.CombinedConfig; import org.alfresco.transform.client.model.config.TransformOption; import org.alfresco.transform.client.registry.TransformServiceRegistryImpl; @@ -49,6 +51,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; +import static java.util.Collections.emptySet; + /** * 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 @@ -171,9 +175,20 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl " Read from "+readFrom); } + Set transformsTransformOptions = lookupTransformOptions( + transformer.getTransformOptions(), transformOptions, readFrom, this::logError); + LocalTransform localTransform; List pipeline = transformer.getTransformerPipeline(); - if (pipeline == null || pipeline.isEmpty()) + List failover = transformer.getTransformerFailover(); + boolean isPipeline = pipeline != null && !pipeline.isEmpty(); + boolean isFailover = failover != null && !failover.isEmpty(); + if (isPipeline && isFailover) + { + throw new IllegalArgumentException("Local transformer " + name + + " cannot have pipeline and failover sections. Read from "+readFrom); + } + if (!isPipeline && !isFailover) { baseUrl = getBaseUrlIfTesting(name, baseUrl); if (baseUrl == null) @@ -185,9 +200,9 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl int startupRetryPeriodSeconds = getStartupRetryPeriodSeconds(name); localTransform = new LocalTransformImpl(name, transformerDebug, mimetypeService, strictMimeTypeCheck, strictMimetypeExceptions, retryTransformOnDifferentMimeType, - this, baseUrl, startupRetryPeriodSeconds); + transformsTransformOptions, this, baseUrl, startupRetryPeriodSeconds); } - else + else if (isPipeline) { int transformerCount = pipeline.size(); if (transformerCount <= 1) @@ -199,18 +214,11 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl localTransform = new LocalPipelineTransform(name, transformerDebug, mimetypeService, strictMimeTypeCheck, strictMimetypeExceptions, retryTransformOnDifferentMimeType, - this); + transformsTransformOptions, this); for (int i=0; i < transformerCount; i++) { TransformStep intermediateTransformerStep = pipeline.get(i); String intermediateTransformerName = intermediateTransformerStep.getTransformerName(); - if (name == null || localTransforms.get(name) != null) - { - throw new IllegalArgumentException("Local pipeline transformer " + name + - " did not specified an intermediate transformer name."+ - " Read from "+readFrom); - } - LocalTransform intermediateTransformer = localTransforms.get(intermediateTransformerName); if (intermediateTransformer == null) { @@ -243,6 +251,34 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl ((LocalPipelineTransform) localTransform).addIntermediateTransformer(intermediateTransformer, targetMimetype); } } + else // if (isFailover) + { + int transformerCount = failover.size(); + if (transformerCount <= 1) + { + throw new IllegalArgumentException("Local failover transformer " + name + + " must have more than one transformer defined."+ + " Read from "+readFrom); + } + + localTransform = new LocalFailoverTransform(name, transformerDebug, mimetypeService, + strictMimeTypeCheck, strictMimetypeExceptions, retryTransformOnDifferentMimeType, + transformsTransformOptions, this); + + for (String transformerStepName : failover) + { + LocalTransform stepTransformer = localTransforms.get(transformerStepName); + if (stepTransformer == null) + { + throw new IllegalArgumentException("Local failover transformer " + name + + " specified an intermediate transformer " + + transformerStepName + " that has not been defined."+ + " Read from "+readFrom); + } + + ((LocalFailoverTransform) localTransform).addStepTransformer(stepTransformer); + } + } localTransforms.put(name, localTransform); super.register(transformer, transformOptions, baseUrl, readFrom); } @@ -253,6 +289,47 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl } } + /** + * Returns the set of TransformOptions for this transform. In the JSON structure, each transform lists the names + * of each set of transform options it uses. In the case of pipelines and failovers transforms, there is typically + * more than one set. Typically there is one for each child transform. + * @param transformOptionNames the names of the transform options used by this transform. + * @param transformOptions a map keyed on transform option name of all the TransformOptions + * @param readFrom used in debug messages to indicate where the transformer config was read from. + * @param logError used to log an error message if a transformOptionName is invalid. + * + * For more information how this is used see {@link AbstractLocalTransform#addOptionNames(Set, Set)}. + */ + private static Set lookupTransformOptions(final Set transformOptionNames, + final Map> transformOptions, + final String readFrom, + final Consumer logError) + { + if (transformOptionNames == null) + { + return emptySet(); + } + + final Set options = new HashSet<>(); + for (String name : transformOptionNames) + { + final Set oneSetOfTransformOptions = transformOptions.get(name); + if (oneSetOfTransformOptions == null) + { + logError.accept("transformOptions in " + readFrom + " with the name " + name + + " does not exist. Ignored"); + continue; + } + options.add(new TransformOptionGroup(false, oneSetOfTransformOptions)); + } + + // If there is only one transform name, the set from the holding TransformOptionGroup can be returned, + // rather than having a nested structure. + return options.size() == 1 ? + ((TransformOptionGroup) options.iterator().next()).getTransformOptions() : + options; + } + // When testing, we need to be able to set the baseUrl when reading from a file. protected String getBaseUrlIfTesting(String name, String baseUrl) { @@ -417,12 +494,11 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl String sourceMimetype = reader.getMimetype(); String targetMimetype = writer.getMimetype(); long sourceSizeInBytes = reader.getSize(); - LocalTransform localTransform = getLocalTransform(actualOptions, renditionName, sourceMimetype, targetMimetype, sourceSizeInBytes); + LocalTransform localTransform = getLocalTransform(sourceMimetype, sourceSizeInBytes, targetMimetype, actualOptions, renditionName); localTransform.transform(reader, writer, actualOptions, renditionName, sourceNodeRef); } - public LocalTransform getLocalTransform(Map actualOptions, String renditionName, - String sourceMimetype, String targetMimetype, long sourceSizeInBytes) + public LocalTransform getLocalTransform(String sourceMimetype, long sourceSizeInBytes, String targetMimetype, Map actualOptions, String renditionName) { String name = findTransformerName(sourceMimetype, sourceSizeInBytes, targetMimetype, actualOptions, renditionName); LocalData data = getData(); 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 239884290c..9c62b3a8e7 100644 --- a/src/main/java/org/alfresco/repo/content/transform/PdfBoxContentTransformer.java +++ b/src/main/java/org/alfresco/repo/content/transform/PdfBoxContentTransformer.java @@ -37,6 +37,8 @@ import org.apache.tika.parser.Parser; import org.apache.tika.parser.pdf.PDFParser; import org.apache.tika.parser.pdf.PDFParserConfig; +import static org.alfresco.repo.rendition2.RenditionDefinition2.TARGET_ENCODING; + /** * Uses Apache Tika and * Apache PDFBox to perform @@ -118,6 +120,6 @@ public class PdfBoxContentTransformer extends TikaPoweredContentTransformer "notExtractBookmarksText", notExtractBookmarksText, "sourceMimetype", sourceMimetype, "targetMimetype", targetMimetype, - "targetEncoding", targetEncoding); + TARGET_ENCODING, targetEncoding); } } diff --git a/src/main/java/org/alfresco/repo/content/transform/StringExtractingContentTransformer.java b/src/main/java/org/alfresco/repo/content/transform/StringExtractingContentTransformer.java index 3cae0bb1d7..7a78ffbec9 100644 --- a/src/main/java/org/alfresco/repo/content/transform/StringExtractingContentTransformer.java +++ b/src/main/java/org/alfresco/repo/content/transform/StringExtractingContentTransformer.java @@ -38,6 +38,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import static org.alfresco.repo.rendition2.RenditionDefinition2.SOURCE_ENCODING; +import static org.alfresco.repo.rendition2.RenditionDefinition2.TARGET_ENCODING; /** * Converts any textual format to plain text. @@ -187,7 +188,7 @@ public class StringExtractingContentTransformer extends AbstractRemoteContentTra "sourceMimetype", sourceMimetype, "targetMimetype", targetMimetype, SOURCE_ENCODING, sourceEncoding, - "targetEncoding", targetEncoding); + TARGET_ENCODING, targetEncoding); } } 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 481a8297a9..ae77e367e7 100644 --- a/src/main/java/org/alfresco/repo/content/transform/TikaPoweredContentTransformer.java +++ b/src/main/java/org/alfresco/repo/content/transform/TikaPoweredContentTransformer.java @@ -52,6 +52,8 @@ import org.apache.tika.sax.BodyContentHandler; import org.apache.tika.sax.ExpandedTitleContentHandler; import org.xml.sax.ContentHandler; +import static org.alfresco.repo.rendition2.RenditionDefinition2.TARGET_ENCODING; + /** * Provides helpful services for {@link org.alfresco.repo.content.transform.ContentTransformer} * implementations which are powered by Apache Tika. @@ -298,7 +300,7 @@ public abstract class TikaPoweredContentTransformer extends AbstractRemoteConten timeoutMs, logger, "sourceMimetype", sourceMimetype, "targetMimetype", targetMimetype, - "targetEncoding", targetEncoding); + TARGET_ENCODING, targetEncoding); } private String calculateMemoryAndTimeUsage(ContentReader reader, long startTime) diff --git a/src/main/java/org/alfresco/repo/rendition2/RenditionDefinition2.java b/src/main/java/org/alfresco/repo/rendition2/RenditionDefinition2.java index 638146b3aa..1551a414b6 100644 --- a/src/main/java/org/alfresco/repo/rendition2/RenditionDefinition2.java +++ b/src/main/java/org/alfresco/repo/rendition2/RenditionDefinition2.java @@ -110,6 +110,12 @@ public interface RenditionDefinition2 */ public static final String SOURCE_NODE_REF = "sourceNodeRef"; + /** + * The encoding of a Target Node is automatically added to the Transform Options if not specified and the + * transformer knows about it. + */ + public static final String TARGET_ENCODING = "targetEncoding"; + String getRenditionName(); String getTargetMimetype(); diff --git a/src/main/java/org/alfresco/transform/client/registry/CombinedConfig.java b/src/main/java/org/alfresco/transform/client/registry/CombinedConfig.java index e440844f51..43b1dd802d 100644 --- a/src/main/java/org/alfresco/transform/client/registry/CombinedConfig.java +++ b/src/main/java/org/alfresco/transform/client/registry/CombinedConfig.java @@ -30,6 +30,7 @@ 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.TransformStep; import org.alfresco.transform.client.model.config.Transformer; import org.alfresco.util.ConfigFileFinder; import org.apache.commons.logging.Log; @@ -45,6 +46,7 @@ import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -234,8 +236,71 @@ public class CombinedConfig data.setTEngineCount(tEngineCount); data.setFileCount(configFileFinder.getFileCount()); + combinedTransformers = sortTransformers(combinedTransformers); + combinedTransformers.forEach(transformer -> registry.register(transformer.transformer, combinedTransformOptions, transformer.baseUrl, transformer.readFrom)); } + + // Sort transformers so there are no forward references, if that is possible. + private static 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.transformer.getTransformerName(); + List pipeline = entry.transformer.getTransformerPipeline(); + Set referencedTransformerNames = new HashSet<>(); + boolean addEntry = true; + if (pipeline != null) + { + for (TransformStep step : pipeline) + { + String stepName = step.getTransformerName(); + referencedTransformerNames.add(stepName); + } + } + List failover = entry.transformer.getTransformerFailover(); + if (failover != null) + { + referencedTransformerNames.addAll(failover); + } + + for (String referencedTransformerName : referencedTransformerNames) + { + if (!transformerNames.contains(referencedTransformerName)) + { + 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; + } } diff --git a/src/main/resources/alfresco/transforms/0100-basePipelines.json b/src/main/resources/alfresco/transforms/0100-basePipelines.json new file mode 100644 index 0000000000..d6b8973218 --- /dev/null +++ b/src/main/resources/alfresco/transforms/0100-basePipelines.json @@ -0,0 +1,278 @@ +{ + "transformers": [ + { + "transformerName": "pdfToImageViaPng", + "transformerPipeline" : [ + {"transformerName": "pdfrenderer", "targetMediaType": "image/png"}, + {"transformerName": "imagemagick"} + ], + "supportedSourceAndTargetList": [ + {"sourceMediaType": "application/pdf", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/pdf", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/pdf", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/pdf", "targetMediaType": "image/tiff"} + ], + "transformOptions": [ + "pdfRendererOptions", + "imageMagickOptions" + ] + }, + { + "transformerName": "aiToImageViaPng", + "transformerPipeline" : [ + {"transformerName": "pdfrenderer", "targetMediaType": "image/png"}, + {"transformerName": "imagemagick"} + ], + "supportedSourceAndTargetList": [ + {"sourceMediaType": "application/illustrator", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/illustrator", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/illustrator", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/illustrator", "targetMediaType": "image/tiff"} + ], + "transformOptions": [ + "pdfRendererOptions", + "imageMagickOptions" + ] + }, + { + "transformerName": "iWorksToImageViaJpg", + "transformerPipeline" : [ + {"transformerName": "appleIWorks", "targetMediaType": "image/jpeg"}, + {"transformerName": "imagemagick"} + ], + "supportedSourceAndTargetList": [ + {"sourceMediaType": "application/vnd.apple.keynote", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.apple.keynote", "priority": "60", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.apple.keynote", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.apple.keynote", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.apple.numbers", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.apple.numbers", "priority": "60", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.apple.numbers", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.apple.numbers", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.apple.pages", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.apple.pages", "priority": "60", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.apple.pages", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.apple.pages", "targetMediaType": "image/tiff"} + ], + "transformOptions": [ + "imageMagickOptions" + ] + }, + { + "transformerName": "outlookMsg2Image", + "transformerPipeline" : [ + {"transformerName": "OutlookMsg", "targetMediaType": "text/plain"}, + {"transformerName": "textToImageViaPdf"} + ], + "supportedSourceAndTargetList": [ + {"sourceMediaType": "application/vnd.ms-outlook", "priority": "55", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.ms-outlook", "priority": "55", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.ms-outlook", "priority": "55", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.ms-outlook", "priority": "55", "targetMediaType": "image/tiff"} + ], + "transformOptions": [ + "tikaOptions", + "pdfRendererOptions", + "imageMagickOptions" + ] + }, + { + "transformerName": "outlookMsg2Pdf", + "transformerPipeline" : [ + {"transformerName": "OutlookMsg", "targetMediaType": "text/plain"}, + {"transformerName": "libreoffice"} + ], + "supportedSourceAndTargetList": [ + {"sourceMediaType": "application/vnd.ms-outlook", "targetMediaType": "application/pdf" } + ], + "transformOptions": [ + "tikaOptions" + ] + }, + { + "transformerName": "rfc822ToPdf", + "transformerPipeline" : [ + {"transformerName": "rfc822", "targetMediaType": "text/plain"}, + {"transformerName": "libreoffice"} + ], + "supportedSourceAndTargetList": [ + {"sourceMediaType": "message/rfc822", "targetMediaType": "application/pdf" } + ], + "transformOptions": [ + ] + }, + { + "transformerName": "rfc822ToImage", + "transformerPipeline" : [ + {"transformerName": "rfc822", "targetMediaType": "text/plain"}, + {"transformerName": "textToImageViaPdf"} + ], + "supportedSourceAndTargetList": [ + {"sourceMediaType": "message/rfc822", "targetMediaType": "image/gif" }, + {"sourceMediaType": "message/rfc822", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "message/rfc822", "targetMediaType": "image/tiff"}, + {"sourceMediaType": "message/rfc822", "targetMediaType": "image/png" } + ], + "transformOptions": [ + "pdfRendererOptions", + "imageMagickOptions" + ] + }, + { + "transformerName": "textToImageViaPdf", + "transformerPipeline" : [ + {"transformerName": "libreoffice", "targetMediaType": "application/pdf"}, + {"transformerName": "pdfToImageViaPng"} + ], + "supportedSourceAndTargetList": [ + {"sourceMediaType": "text/plain", "targetMediaType": "image/gif" }, + {"sourceMediaType": "text/plain", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "text/plain", "targetMediaType": "image/tiff"}, + {"sourceMediaType": "text/plain", "targetMediaType": "image/png" }, + + {"sourceMediaType": "text/csv", "targetMediaType": "image/gif" }, + {"sourceMediaType": "text/csv", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "text/csv", "targetMediaType": "image/tiff"}, + {"sourceMediaType": "text/csv", "targetMediaType": "image/png" }, + + {"sourceMediaType": "text/xml", "targetMediaType": "image/gif" }, + {"sourceMediaType": "text/xml", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "text/xml", "targetMediaType": "image/tiff"}, + {"sourceMediaType": "text/xml", "targetMediaType": "image/png" } + ], + "transformOptions": [ + "pdfRendererOptions", + "imageMagickOptions" + ] + }, + { + "transformerName": "htmlToPdfViaOdt", + "transformerPipeline" : [ + {"transformerName": "libreoffice", "targetMediaType": "application/vnd.oasis.opendocument.text"}, + {"transformerName": "libreoffice"} + ], + "supportedSourceAndTargetList": [ + {"sourceMediaType": "text/html", "targetMediaType": "application/pdf" } + ], + "transformOptions": [ + ] + }, + { + "transformerName": "htmlToImageViaPdf", + "transformerPipeline" : [ + {"transformerName": "htmlToPdfViaOdt", "targetMediaType": "application/pdf"}, + {"transformerName": "pdfToImageViaPng"} + ], + "supportedSourceAndTargetList": [ + {"sourceMediaType": "text/html", "targetMediaType": "image/gif" }, + {"sourceMediaType": "text/html", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "text/html", "targetMediaType": "image/tiff"}, + {"sourceMediaType": "text/html", "targetMediaType": "image/png" } + ], + "transformOptions": [ + "pdfRendererOptions", + "imageMagickOptions" + ] + }, + { + "transformerName": "ooXmlToImageViaText", + "transformerPipeline" : [ + {"transformerName": "OOXML", "targetMediaType": "text/plain"}, + {"transformerName": "textToImageViaPdf"} + ], + "supportedSourceAndTargetList": [ + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.wordprocessingml.template", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.wordprocessingml.template", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.wordprocessingml.template", "targetMediaType": "image/tiff"}, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.wordprocessingml.template", "targetMediaType": "image/png" }, + + {"sourceMediaType": "application/vnd.ms-powerpoint.slideshow.macroenabled.12", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.ms-powerpoint.slideshow.macroenabled.12", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.ms-powerpoint.slideshow.macroenabled.12", "targetMediaType": "image/tiff"}, + {"sourceMediaType": "application/vnd.ms-powerpoint.slideshow.macroenabled.12", "targetMediaType": "image/png" }, + + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.slideshow", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.slideshow", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.slideshow", "targetMediaType": "image/tiff"}, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.slideshow", "targetMediaType": "image/png" }, + + {"sourceMediaType": "application/vnd.ms-excel.addin.macroenabled.12", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.ms-excel.addin.macroenabled.12", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.ms-excel.addin.macroenabled.12", "targetMediaType": "image/tiff"}, + {"sourceMediaType": "application/vnd.ms-excel.addin.macroenabled.12", "targetMediaType": "image/png" } + ], + "transformOptions": [ + "tikaOptions", + "pdfRendererOptions", + "imageMagickOptions" + ] + }, + { + "transformerName": "archiveToImageViaText", + "transformerPipeline" : [ + {"transformerName": "Archive", "targetMediaType": "text/plain"}, + {"transformerName": "textToImageViaPdf"} + ], + "supportedSourceAndTargetList": [ + {"sourceMediaType": "application/x-cpio", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/x-cpio", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/x-cpio", "targetMediaType": "image/tiff"}, + {"sourceMediaType": "application/x-cpio", "targetMediaType": "image/png" }, + + {"sourceMediaType": "application/java-archive", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/java-archive", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/java-archive", "targetMediaType": "image/tiff"}, + {"sourceMediaType": "application/java-archive", "targetMediaType": "image/png" }, + + {"sourceMediaType": "application/x-tar", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/x-tar", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/x-tar", "targetMediaType": "image/tiff"}, + {"sourceMediaType": "application/x-tar", "targetMediaType": "image/png" }, + + {"sourceMediaType": "application/zip", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/zip", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/zip", "targetMediaType": "image/tiff"}, + {"sourceMediaType": "application/zip", "targetMediaType": "image/png" } + ], + "transformOptions": [ + "archiveOptions", + "pdfRendererOptions", + "imageMagickOptions" + ] + }, + { + "transformerName": "ooXmlToPdfViaText", + "transformerPipeline" : [ + {"transformerName": "OOXML", "targetMediaType": "text/plain"}, + {"transformerName": "libreoffice"} + ], + "supportedSourceAndTargetList": [ + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.wordprocessingml.template", "priority": "55", "targetMediaType": "application/pdf"}, + {"sourceMediaType": "application/vnd.ms-powerpoint.slideshow.macroenabled.12", "targetMediaType": "application/pdf" }, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.slideshow", "targetMediaType": "application/pdf" }, + {"sourceMediaType": "application/vnd.ms-excel.addin.macroenabled.12", "targetMediaType": "application/pdf" } + ], + "transformOptions": [ + "tikaOptions" + ] + }, + { + "transformerName": "archiveToPdfViaText2", + "transformerPipeline" : [ + {"transformerName": "Archive", "targetMediaType": "text/plain"}, + {"transformerName": "libreoffice"} + ], + "supportedSourceAndTargetList": [ + {"sourceMediaType": "application/x-cpio", "targetMediaType": "application/pdf" }, + {"sourceMediaType": "application/java-archive", "targetMediaType": "application/pdf"}, + {"sourceMediaType": "application/x-tar", "targetMediaType": "application/pdf" }, + {"sourceMediaType": "application/zip", "targetMediaType": "application/pdf" } + ], + "transformOptions": [ + "archiveOptions" + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/alfresco/transforms/0150-officeToImageViaPdf.json b/src/main/resources/alfresco/transforms/0150-officeToImageViaPdf.json index b03e52b25a..f095c4a88b 100644 --- a/src/main/resources/alfresco/transforms/0150-officeToImageViaPdf.json +++ b/src/main/resources/alfresco/transforms/0150-officeToImageViaPdf.json @@ -41,7 +41,158 @@ {"sourceMediaType": "application/vnd.ms-outlook", "targetMediaType": "image/gif" }, {"sourceMediaType": "application/vnd.ms-outlook", "targetMediaType": "image/jpeg"}, {"sourceMediaType": "application/vnd.ms-outlook", "targetMediaType": "image/png" }, - {"sourceMediaType": "application/vnd.ms-outlook", "targetMediaType": "image/tiff"} + {"sourceMediaType": "application/vnd.ms-outlook", "targetMediaType": "image/tiff"}, + + + {"sourceMediaType": "application/vnd.ms-word.document.macroenabled.12", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.ms-word.document.macroenabled.12", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.ms-word.document.macroenabled.12", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.ms-word.document.macroenabled.12", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.ms-word.template.macroenabled.12", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.ms-word.template.macroenabled.12", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.ms-word.template.macroenabled.12", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.ms-word.template.macroenabled.12", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.oasis.opendocument.graphics", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.oasis.opendocument.graphics", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.oasis.opendocument.graphics", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.oasis.opendocument.graphics", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.oasis.opendocument.presentation", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.oasis.opendocument.presentation", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.oasis.opendocument.presentation", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.oasis.opendocument.presentation", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.oasis.opendocument.spreadsheet", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.oasis.opendocument.spreadsheet", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.oasis.opendocument.spreadsheet", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.oasis.opendocument.spreadsheet", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.oasis.opendocument.presentation-template", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.oasis.opendocument.presentation-template", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.oasis.opendocument.presentation-template", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.oasis.opendocument.presentation-template", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.oasis.opendocument.spreadsheet-template", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.oasis.opendocument.spreadsheet-template", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.oasis.opendocument.spreadsheet-template", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.oasis.opendocument.spreadsheet-template", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.oasis.opendocument.text", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.oasis.opendocument.text", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.oasis.opendocument.text", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.oasis.opendocument.text", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.oasis.opendocument.text-template", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.oasis.opendocument.text-template", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.oasis.opendocument.text-template", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.oasis.opendocument.text-template", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.ms-powerpoint.template.macroenabled.12", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.ms-powerpoint.template.macroenabled.12", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.ms-powerpoint.template.macroenabled.12", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.ms-powerpoint.template.macroenabled.12", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.template", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.template", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.template", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.template", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.ms-powerpoint.addin.macroenabled.12", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.ms-powerpoint.addin.macroenabled.12", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.ms-powerpoint.addin.macroenabled.12", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.ms-powerpoint.addin.macroenabled.12", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.ms-powerpoint.presentation.macroenabled.12", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.ms-powerpoint.presentation.macroenabled.12", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.ms-powerpoint.presentation.macroenabled.12", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.ms-powerpoint.presentation.macroenabled.12", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.presentation", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.presentation", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.presentation", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.presentation", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/rtf", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/rtf", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/rtf", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/rtf", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.ms-powerpoint.slide.macroenabled.12", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.ms-powerpoint.slide.macroenabled.12", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.ms-powerpoint.slide.macroenabled.12", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.ms-powerpoint.slide.macroenabled.12", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.slide", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.slide", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.slide", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.slide", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.sun.xml.calc.template", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.sun.xml.calc.template", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.sun.xml.calc.template", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.sun.xml.calc.template", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.sun.xml.impress.template", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.sun.xml.impress.template", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.sun.xml.impress.template", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.sun.xml.impress.template", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.sun.xml.writer.template", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.sun.xml.writer.template", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.sun.xml.writer.template", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.sun.xml.writer.template", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.sun.xml.calc", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.sun.xml.calc", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.sun.xml.calc", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.sun.xml.calc", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.sun.xml.impress", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.sun.xml.impress", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.sun.xml.impress", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.sun.xml.impress", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.sun.xml.writer", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.sun.xml.writer", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.sun.xml.writer", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.sun.xml.writer", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "text/tab-separated-values", "targetMediaType": "image/gif" }, + {"sourceMediaType": "text/tab-separated-values", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "text/tab-separated-values", "targetMediaType": "image/png" }, + {"sourceMediaType": "text/tab-separated-values", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.visio", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.visio", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.visio", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.visio", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.visio2013", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.visio2013", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.visio2013", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.visio2013", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/wordperfect", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/wordperfect", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/wordperfect", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/wordperfect", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.ms-excel.sheet.binary.macroenabled.12", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.ms-excel.sheet.binary.macroenabled.12", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.ms-excel.sheet.binary.macroenabled.12", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.ms-excel.sheet.binary.macroenabled.12", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.ms-excel.sheet.macroenabled.12", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.ms-excel.sheet.macroenabled.12", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.ms-excel.sheet.macroenabled.12", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.ms-excel.sheet.macroenabled.12", "targetMediaType": "image/tiff"}, + + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.spreadsheetml.template", "targetMediaType": "image/gif" }, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.spreadsheetml.template", "targetMediaType": "image/jpeg"}, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.spreadsheetml.template", "targetMediaType": "image/png" }, + {"sourceMediaType": "application/vnd.openxmlformats-officedocument.spreadsheetml.template", "targetMediaType": "image/tiff"} ], "transformOptions": [ "pdfRendererOptions", diff --git a/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionTest.java b/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionTest.java index c75735bfbc..5ea0714e6d 100644 --- a/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionTest.java +++ b/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionTest.java @@ -26,8 +26,11 @@ package org.alfresco.repo.rendition2; import junit.framework.AssertionFailedError; +import org.alfresco.repo.content.transform.TransformerDebug; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.thumbnail.ThumbnailDefinition; +import org.alfresco.transform.client.registry.AbstractTransformRegistry; +import org.alfresco.transform.client.registry.SupportedTransform; import org.alfresco.util.testing.category.DebugTests; import org.junit.Before; import org.junit.Test; @@ -36,12 +39,16 @@ import org.junit.experimental.categories.Category; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.StringJoiner; import java.util.concurrent.atomic.AtomicInteger; +import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_TEXT_PLAIN; + /** * Abstract test class to check it is possible to create renditions from the quick files using combinations of * local transforms, legacy transforms and the Transform Service. @@ -56,7 +63,7 @@ public abstract class AbstractRenditionTest extends AbstractRenditionIntegration public static final List TAS_REST_API_EXCLUDE_LIST = Collections.EMPTY_LIST; - public static final List ALL_SOURCE_EXTENSIONS_EXCLUDE_LIST = Arrays.asList( + public static final List ALL_SOURCE_EXTENSIONS_EXCLUDE_LIST_LEGACY = Arrays.asList( "key jpg imgpreview", "key jpg medium", "key png doclib", @@ -201,15 +208,15 @@ public abstract class AbstractRenditionTest extends AbstractRenditionIntegration @Test public void testAllSourceExtensions() throws Exception { - internalTestAllSourceExtensions(196, 0); + internalTestAllSourceExtensions(196, 0, ALL_SOURCE_EXTENSIONS_EXCLUDE_LIST_LEGACY); } - protected void internalTestAllSourceExtensions(int expectedRenditionCount, int expectedFailedCount) throws Exception + protected void internalTestAllSourceExtensions(int expectedRenditionCount, int expectedFailedCount, + List excludeList) throws Exception { List sourceExtensions = getAllSourceMimetypes(); assertRenditionsOkayFromSourceExtension(sourceExtensions, - ALL_SOURCE_EXTENSIONS_EXCLUDE_LIST, - Collections.emptyList(), expectedRenditionCount, expectedFailedCount); + excludeList, Collections.emptyList(), expectedRenditionCount, expectedFailedCount); } private List getAllSourceMimetypes() @@ -242,7 +249,10 @@ public abstract class AbstractRenditionTest extends AbstractRenditionIntegration @Category(DebugTests.class) public void testCountTotalTransforms() { + StringBuilder sourceTargetList = new StringBuilder(); + StringBuilder sourceTargetPriorityList = new StringBuilder(); AtomicInteger count = new AtomicInteger(0); + int textTargetCount = 0; mimetypeService.getMimetypesByExtension(); List mimetypes = new ArrayList(mimetypeMap.getMimetypes()); sortMimetypesByExtension(mimetypes); @@ -252,11 +262,24 @@ public abstract class AbstractRenditionTest extends AbstractRenditionIntegration { if (transformServiceRegistry.isSupported(sourceMimetype, 1, targetMimetype, Collections.emptyMap(), null)) { - logSourceTarget(count, sourceMimetype, targetMimetype); + logSourceTarget(sourceTargetList, sourceTargetPriorityList, count, sourceMimetype, targetMimetype); + if (MIMETYPE_TEXT_PLAIN.equals(targetMimetype)) + { + textTargetCount++; + } } } } - System.err.println("Number of source to target mimetype transforms: "+count); + + System.out.println("Number of source to target mimetype transforms: "+count); + System.out.println("Number of source to plain text transforms: "+textTargetCount); + System.out.println(sourceTargetList); + if (sourceTargetPriorityList.length() > 0) + { + System.out.println(""); + System.out.println("Alternate transforms"); + System.out.println(sourceTargetPriorityList); + } } /** @@ -266,6 +289,7 @@ public abstract class AbstractRenditionTest extends AbstractRenditionIntegration @Category(DebugTests.class) public void testCountTotalRenditionTransforms() { + StringBuilder sourceTargetList = new StringBuilder(); AtomicInteger count = new AtomicInteger(0); RenditionDefinitionRegistry2 renditionDefinitionRegistry = renditionService2.getRenditionDefinitionRegistry2(); List sourceMimetypes = new ArrayList(mimetypeMap.getMimetypes()); @@ -284,18 +308,50 @@ public abstract class AbstractRenditionTest extends AbstractRenditionIntegration sortMimetypesByExtension(targetMimetypesSorted); for (String targetMimetype : targetMimetypesSorted) { - logSourceTarget(count, sourceMimetype, targetMimetype); + logSourceTarget(sourceTargetList, null, count, sourceMimetype, targetMimetype); } } + System.out.println("Number of source to target mimetype transforms via renditions: "+count.get()); + System.out.println(sourceTargetList); } - private void logSourceTarget(AtomicInteger count, String sourceMimetype, String targetMimetype) + private void logSourceTarget(StringBuilder sourceTargetList, StringBuilder sourceTargetPriorityList, AtomicInteger count, String sourceMimetype, String targetMimetype) { count.incrementAndGet(); String sourceExtension = mimetypeService.getExtension(sourceMimetype); String targetExtension = mimetypeService.getExtension(targetMimetype); - System.err.printf("%4d %4s %4s\n", count.get(), sourceExtension, targetExtension); + String line = String.format("%4d %4s %4s\n", count.get(), sourceExtension, targetExtension); + sourceTargetList.append(line); + + if (sourceTargetPriorityList != null) + { + AbstractTransformRegistry registry = getAbstractTransformRegistry(); + if (registry != null) + { + Map> supportedTransformsByTargetMimetype = registry.getData().retrieveTransforms(sourceMimetype); + List supportedTransforms = new ArrayList<>(supportedTransformsByTargetMimetype.get(targetMimetype)); + supportedTransforms.sort((t1, t2) -> t1.getPriority()-t2.getPriority()); + char a = 'a'; + int prevPriority = Integer.MAX_VALUE; + for (SupportedTransform supportedTransform : supportedTransforms) + { + int priority = supportedTransform.getPriority(); + long maxSourceSizeBytes = supportedTransform.getMaxSourceSizeBytes(); + String priorityUnchanged = prevPriority == priority ? "*" : ""; + String transformName = supportedTransform.getName(); + line = String.format("%4d %4s %4s %c) [%d%s] %s %d\n", count.get(), sourceExtension, targetExtension, + a++, priority, priorityUnchanged, transformName, maxSourceSizeBytes); + sourceTargetPriorityList.append(line); + prevPriority = priority; + } + } + } + } + + protected AbstractTransformRegistry getAbstractTransformRegistry() + { + return null; } private void sortMimetypesByExtension(List mimetypes) diff --git a/src/test/java/org/alfresco/repo/rendition2/LocalRenditionTest.java b/src/test/java/org/alfresco/repo/rendition2/LocalRenditionTest.java index 597d0b8de6..e951ee763a 100644 --- a/src/test/java/org/alfresco/repo/rendition2/LocalRenditionTest.java +++ b/src/test/java/org/alfresco/repo/rendition2/LocalRenditionTest.java @@ -25,12 +25,23 @@ */ package org.alfresco.repo.rendition2; +import org.alfresco.transform.client.registry.AbstractTransformRegistry; +import org.alfresco.transform.client.registry.SupportedTransform; import org.alfresco.util.testing.category.DebugTests; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.categories.Category; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.alfresco.repo.content.MimetypeMap.MIMETYPE_TEXT_PLAIN; + /** * Repeats quick file rendition tests with local transforms enabled but legacy transformers disabled. * The Transform Service does not exist for the Community edition. @@ -40,6 +51,18 @@ import org.junit.experimental.categories.Category; */ public class LocalRenditionTest extends AbstractRenditionTest { + public static final List ALL_SOURCE_EXTENSIONS_EXCLUDE_LIST_LOCAL = Arrays.asList( + // - textToPdf returned a 400 status Miscellaneous Transformers - U+0628 ('afii57416') is not available in this font Helvetica encoding: WinAnsiEncoding + // This is because the wrong transformer is being used due bug. The priority in the transform config is currently ignored. + "txt pdf pdf", + + "tiff jpg imgpreview", + "tiff jpg medium", + "tiff png doclib", + "tiff png avatar", + "tiff png avatar32" + ); + @BeforeClass public static void before() { @@ -53,12 +76,18 @@ public class LocalRenditionTest extends AbstractRenditionTest AbstractRenditionIntegrationTest.after(); } - // TODO this method will be removed when Local transformers support all 196 renditions supported by legacy + // TODO this method will be removed when Local transformers the same transforms as legacy @Override @Category(DebugTests.class) @Test public void testAllSourceExtensions() throws Exception { - internalTestAllSourceExtensions(81, 0); + internalTestAllSourceExtensions(196, 0, ALL_SOURCE_EXTENSIONS_EXCLUDE_LIST_LOCAL); + } + + @Override + protected AbstractTransformRegistry getAbstractTransformRegistry() + { + return (AbstractTransformRegistry) localTransformServiceRegistry; } } diff --git a/src/test/java/org/alfresco/repo/rendition2/NoneRenditionTest.java b/src/test/java/org/alfresco/repo/rendition2/NoneRenditionTest.java index e6541fe950..e3605284da 100644 --- a/src/test/java/org/alfresco/repo/rendition2/NoneRenditionTest.java +++ b/src/test/java/org/alfresco/repo/rendition2/NoneRenditionTest.java @@ -31,6 +31,8 @@ import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.categories.Category; +import java.util.Collections; + /** * Repeats quick file rendition tests with local transforms and legacy transformers disabled. * The Transform Service does not exist for the Community edition. @@ -64,7 +66,7 @@ public class NoneRenditionTest extends AbstractRenditionTest @Override public void testAllSourceExtensions() throws Exception { - internalTestAllSourceExtensions(0, 0); + internalTestAllSourceExtensions(0, 0, Collections.emptyList()); } @Test diff --git a/src/test/java/org/alfresco/transform/client/registry/LocalTransformServiceRegistryConfigTest.java b/src/test/java/org/alfresco/transform/client/registry/LocalTransformServiceRegistryConfigTest.java index b8d48ab47b..b014111a1a 100644 --- a/src/test/java/org/alfresco/transform/client/registry/LocalTransformServiceRegistryConfigTest.java +++ b/src/test/java/org/alfresco/transform/client/registry/LocalTransformServiceRegistryConfigTest.java @@ -27,11 +27,15 @@ package org.alfresco.transform.client.registry; import com.fasterxml.jackson.databind.ObjectMapper; import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.content.transform.AbstractLocalTransform; +import org.alfresco.repo.content.transform.LocalPipelineTransform; +import org.alfresco.repo.content.transform.LocalTransform; 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.camel.processor.Pipeline; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.Before; @@ -42,6 +46,7 @@ import org.quartz.CronExpression; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -199,6 +204,7 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg { CombinedConfig combinedConfig = new CombinedConfig(log); combinedConfig.addLocalConfig(LOCAL_TRANSFORM_SERVICE_CONFIG); + combinedConfig.register(registry); mapOfTransformOptions = combinedConfig.combinedTransformOptions; transformerList = combinedConfig.combinedTransformers; } @@ -231,6 +237,11 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg imagemagickSupportedTransformation.put("image/gif", targetMimetype); imagemagickSupportedTransformation.put("image/jpeg", targetMimetype); imagemagickSupportedTransformation.put("image/png", targetMimetype); + targetMimetype = new ArrayList<>(); + targetMimetype.add("target1"); + targetMimetype.add("target2"); + targetMimetype.add("target3"); + imagemagickSupportedTransformation.put("source", targetMimetype); // Tika Supported Source and Target List: targetMimetype = new ArrayList<>(); @@ -244,6 +255,11 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg tikaSupportedTransformation.put("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", targetMimetype); tikaSupportedTransformation.put("application/vnd.openxmlformats-officedocument.presentationml.presentation", targetMimetype); tikaSupportedTransformation.put("application/vnd.ms-outlook", targetMimetype); + targetMimetype = new ArrayList<>(); + targetMimetype.add("target1"); + targetMimetype.add("target2"); + targetMimetype.add("target3"); + tikaSupportedTransformation.put("source", targetMimetype); // Libre Office Source and Target List: targetMimetype = new ArrayList<>(); @@ -263,6 +279,11 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg pdfRendererSupportedTransformation = new HashMap<>(); targetMimetype.add("image/png"); pdfRendererSupportedTransformation.put("application/pdf", targetMimetype); + targetMimetype = new ArrayList<>(); + targetMimetype.add("target1"); + targetMimetype.add("target2"); + targetMimetype.add("target3"); + pdfRendererSupportedTransformation.put("source", targetMimetype); // Office to Image via Pdf Pipeline Transformer Source and Target List: targetMimetype = new ArrayList<>(); @@ -298,6 +319,14 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg return i; } + @Test + @Override + public void testJsonConfig() throws IOException + { + // Not 60, 60 as we have added source->target1..3 to three transformers + internalTestJsonConfig(63, 69); + } + @Test public void testReadWriteJson() throws IOException { @@ -329,7 +358,7 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg switch (t.transformer.getTransformerName()) { case "imagemagick": - assertEquals(t.transformer.getTransformerName() + " incorrect number of supported transform", 14, t.transformer.getSupportedSourceAndTargetList().size()); + assertEquals(t.transformer.getTransformerName() + " incorrect number of supported transform", 17, 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); @@ -344,7 +373,7 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg break; case "tika": - assertEquals(t.transformer.getTransformerName() + " incorrect number of supported transform", 8, t.transformer.getSupportedSourceAndTargetList().size()); + assertEquals(t.transformer.getTransformerName() + " incorrect number of supported transform", 11, 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); @@ -359,7 +388,7 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg break; case "pdfrenderer": - assertEquals(t.transformer.getTransformerName() + " incorrect number of supported transform", 1, t.transformer.getSupportedSourceAndTargetList().size()); + assertEquals(t.transformer.getTransformerName() + " incorrect number of supported transform", 4, 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); @@ -499,4 +528,49 @@ public class LocalTransformServiceRegistryConfigTest extends TransformServiceReg registry.setPipelineConfigDir(origPipelineConfigDir); } } + + @Test + public void testStripExtraOptions() + { + retrieveLocalTransformList(); + + Map actualOptions = Map.of( + "autoOrient", "true", + "width", "100", + "height", "50"); + LocalPipelineTransform officeToImageViaPdf = + (LocalPipelineTransform)((LocalTransformServiceRegistry)registry).getLocalTransform( + "application/msword", -1, "image/gif", actualOptions, null); + assertEquals("Original number of options officeToImageViaPdf", 21, officeToImageViaPdf.getTransformsTransformOptionNames().size()); + + AbstractLocalTransform libreoffice = (AbstractLocalTransform) officeToImageViaPdf.getIntermediateTransformer(0); + assertEquals("libreoffice options", 0, libreoffice.getTransformsTransformOptionNames().size()); + assertEquals("libreoffice actual options", 0, libreoffice.getStrippedTransformOptions(actualOptions).size()); + + AbstractLocalTransform pdfrenderer = (AbstractLocalTransform) officeToImageViaPdf.getIntermediateTransformer(1); + assertEquals("pdfrenderer options", 5, pdfrenderer.getTransformsTransformOptionNames().size()); + assertEquals("pdfrenderer actual options", 2, pdfrenderer.getStrippedTransformOptions(actualOptions).size()); // width, height + + AbstractLocalTransform imagemagick = (AbstractLocalTransform) officeToImageViaPdf.getIntermediateTransformer(2); + assertEquals("imagemagick options", 16, imagemagick.getTransformsTransformOptionNames().size()); + assertEquals("imagemagick actual options", 1, imagemagick.getStrippedTransformOptions(actualOptions).size()); // autoOrient + } + + @Test + public void testPriority() + { + retrieveLocalTransformList(); + + assertEquals("pdfrenderer", + ((AbstractLocalTransform)registry.getLocalTransform("source", -1, + "target1", Collections.emptyMap(), null)).getName()); + + assertEquals("imagemagick", + ((AbstractLocalTransform)registry.getLocalTransform("source", -1, + "target2", Collections.emptyMap(), null)).getName()); + + assertEquals("tika", + ((AbstractLocalTransform)registry.getLocalTransform("source", -1, + "target3", Collections.emptyMap(), null)).getName()); + } } diff --git a/src/test/java/org/alfresco/transform/client/registry/TransformServiceRegistryConfigTest.java b/src/test/java/org/alfresco/transform/client/registry/TransformServiceRegistryConfigTest.java index 40abf62ba8..987e723d4b 100644 --- a/src/test/java/org/alfresco/transform/client/registry/TransformServiceRegistryConfigTest.java +++ b/src/test/java/org/alfresco/transform/client/registry/TransformServiceRegistryConfigTest.java @@ -126,15 +126,20 @@ public class TransformServiceRegistryConfigTest extends TransformRegistryTest @Test public void testJsonConfig() throws IOException + { + internalTestJsonConfig(60, 60); + } + + protected void internalTestJsonConfig(int expectedSourceTargetUniqueCount, int expectedSourceTargetCount) 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)); + expectedSourceTargetUniqueCount, 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)); + expectedSourceTargetCount, countSupportedTransforms(false)); // Check a supported transform for each transformer. assertSupported(DOC, 1234, PDF, emptyMap(), null, ""); // libreoffice diff --git a/src/test/resources/alfresco/local-transform-service-config-test.json b/src/test/resources/alfresco/local-transform-service-config-test.json index f78659b3fc..a38e9c88ce 100644 --- a/src/test/resources/alfresco/local-transform-service-config-test.json +++ b/src/test/resources/alfresco/local-transform-service-config-test.json @@ -57,7 +57,10 @@ {"sourceMediaType": "image/png", "targetMediaType": "image/tiff"}, {"sourceMediaType": "image/tiff", "targetMediaType": "image/gif" }, - {"sourceMediaType": "image/tiff", "targetMediaType": "image/tiff"} + {"sourceMediaType": "image/tiff", "targetMediaType": "image/tiff"}, + {"sourceMediaType": "source", "priority": "60","targetMediaType": "target1" }, + {"sourceMediaType": "source", "priority": "50","targetMediaType": "target2" }, + {"sourceMediaType": "source", "priority": "55","targetMediaType": "target3" } ], "transformOptions": [ "imagemagickOptions" @@ -73,7 +76,10 @@ {"sourceMediaType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "targetMediaType": "text/plain"}, {"sourceMediaType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "targetMediaType": "text/plain" }, {"sourceMediaType": "application/vnd.openxmlformats-officedocument.presentationml.presentation", "targetMediaType": "text/plain" }, - {"sourceMediaType": "application/vnd.ms-outlook", "targetMediaType": "text/plain"} + {"sourceMediaType": "application/vnd.ms-outlook", "targetMediaType": "text/plain"}, + {"sourceMediaType": "source", "priority": "55","targetMediaType": "target1" }, + {"sourceMediaType": "source", "priority": "60","targetMediaType": "target2" }, + {"sourceMediaType": "source", "priority": "50","targetMediaType": "target3" } ], "transformOptions": [ "tikaOptions" @@ -82,7 +88,10 @@ { "transformerName": "pdfrenderer", "supportedSourceAndTargetList": [ - {"sourceMediaType": "application/pdf", "targetMediaType": "image/png" } + {"sourceMediaType": "application/pdf", "targetMediaType": "image/png" }, + {"sourceMediaType": "source", "priority": "50","targetMediaType": "target1" }, + {"sourceMediaType": "source", "priority": "55","targetMediaType": "target2" }, + {"sourceMediaType": "source", "priority": "60","targetMediaType": "target3" } ], "transformOptions": [ "pdfRendererOptions" diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties index 7e536e1e3a..20a928e233 100644 --- a/src/test/resources/log4j.properties +++ b/src/test/resources/log4j.properties @@ -109,7 +109,7 @@ log4j.logger.org.alfresco.util.transaction.SpringAwareUserTransaction.trace=warn log4j.logger.org.alfresco.util.AbstractTriggerBean=warn log4j.logger.org.alfresco.enterprise.repo.cluster=info log4j.logger.org.alfresco.repo.version.Version2ServiceImpl=warn -log4j.logger.org.alfresco.repo.thumbnail=debug +#log4j.logger.org.alfresco.repo.thumbnail=debug #log4j.logger.org.alfresco.web.app.DebugPhaseListener=debug @@ -242,7 +242,7 @@ log4j.logger.org.alfresco.util.remote.server.socket.HostConfigurableSocketFactor log4j.logger.org.alfresco.repo.usage.RepoUsageMonitor=info log4j.logger.org.alfresco.repo.site.SiteServiceImpl=DEBUG -log4j.logger.org.alfresco.repo.action.ActionServiceImpl=DEBUG +#log4j.logger.org.alfresco.repo.action.ActionServiceImpl=DEBUG log4j.logger.org.alfresco.repo.security.person.PersonServiceImpl=DEBUG # identity service authentication