diff --git a/.travis.yml b/.travis.yml index 7d0a65e560..270e321664 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,11 +52,21 @@ 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 - script: travis_wait 20 mvn test -B -Dtest=AppContext03TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco + - docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-pdf-renderer:2.1.0-RC3 + - docker run -d -p 8091:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-imagemagick:2.1.0-RC3 + - docker run -d -p 8092:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-libreoffice:2.1.0-RC3 + - docker run -d -p 8093:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-tika:2.1.0-RC3 + - docker run -d -p 8094:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-misc:2.1.0-RC3 + script: travis_wait 20 mvn test -B -Dtest=AppContext03TestSuite -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: "AppContext04TestSuite" 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-RC3 + - docker run -d -p 8091:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-imagemagick:2.1.0-RC3 + - docker run -d -p 8092:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-libreoffice:2.1.0-RC3 + - docker run -d -p 8093:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-tika:2.1.0-RC3 + - docker run -d -p 8094:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-misc:2.1.0-RC3 script: travis_wait 20 mvn test -B -Dtest=AppContext04TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco - name: "AppContext05TestSuite" before_install: diff --git a/src/main/java/org/alfresco/repo/action/executer/TransformActionExecuter.java b/src/main/java/org/alfresco/repo/action/executer/TransformActionExecuter.java index 786967daf3..9f02df0c15 100644 --- a/src/main/java/org/alfresco/repo/action/executer/TransformActionExecuter.java +++ b/src/main/java/org/alfresco/repo/action/executer/TransformActionExecuter.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + * 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 @@ -26,6 +26,7 @@ package org.alfresco.repo.action.executer; import java.util.List; +import java.util.Map; import org.alfresco.model.ContentModel; import org.alfresco.query.PagingRequest; @@ -33,6 +34,8 @@ import org.alfresco.query.PagingResults; import org.alfresco.repo.action.ParameterDefinitionImpl; import org.alfresco.repo.content.transform.UnimportantTransformException; import org.alfresco.repo.content.transform.UnsupportedTransformationException; +import org.alfresco.repo.rendition2.SynchronousTransformClient; +import org.alfresco.repo.rendition2.TransformationOptionsConverter; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ParameterDefinition; import org.alfresco.service.cmr.coci.CheckOutCheckInService; @@ -90,7 +93,9 @@ public class TransformActionExecuter extends ActionExecuterAbstractBase private ContentService contentService; private CopyService copyService; private MimetypeService mimetypeService; - + private SynchronousTransformClient synchronousTransformClient; + private TransformationOptionsConverter converter; + /** * Properties (needed to avoid changing method signatures) */ @@ -104,7 +109,7 @@ public class TransformActionExecuter extends ActionExecuterAbstractBase { this.mimetypeService = mimetypeService; } - + /** * Set the node service */ @@ -144,7 +149,17 @@ public class TransformActionExecuter extends ActionExecuterAbstractBase { this.copyService = copyService; } - + + public void setSynchronousTransformClient(SynchronousTransformClient synchronousTransformClient) + { + this.synchronousTransformClient = synchronousTransformClient; + } + + public void setConverter(TransformationOptionsConverter converter) + { + this.converter = converter; + } + /** * Add parameter definitions */ @@ -188,13 +203,19 @@ public class TransformActionExecuter extends ActionExecuterAbstractBase throw new RuleServiceException(CONTENT_READER_NOT_FOUND_MESSAGE); } - TransformationOptions options = newTransformationOptions(ruleAction, actionedUponNodeRef); - // getExecuteAsychronously() is not true for async convert content rules, so using Thread name - // options.setUse(ruleAction.getExecuteAsychronously() ? "asyncRule" :"syncRule"); - options.setUse(Thread.currentThread().getName().contains("Async") ? "asyncRule" :"syncRule"); - if (null == contentService.getTransformer(contentReader.getContentUrl(), contentReader.getMimetype(), contentReader.getSize(), mimeType, options)) + TransformationOptions transformationOptions = newTransformationOptions(ruleAction, actionedUponNodeRef); + // getExecuteAsynchronously() is not true for async convert content rules, so using Thread name + // options.setUse(ruleAction.getExecuteAsynchronously() ? "asyncRule" :"syncRule"); + transformationOptions.setUse(Thread.currentThread().getName().contains("Async") ? "asyncRule" :"syncRule"); + + String sourceMimetype = contentReader.getMimetype(); + long sourceSizeInBytes = contentReader.getSize(); + String contentUrl = contentReader.getContentUrl(); + Map options = converter.getOptions(transformationOptions); + if (!synchronousTransformClient.isSupported(sourceMimetype, sourceSizeInBytes, + contentUrl, mimeType, options, null, actionedUponNodeRef)) { - throw new RuleServiceException(String.format(TRANSFORMER_NOT_EXISTS_MESSAGE_PATTERN, contentReader.getMimetype(), mimeType)); + throw new RuleServiceException(String.format(TRANSFORMER_NOT_EXISTS_MESSAGE_PATTERN, sourceMimetype, mimeType)); } // Get the details of the copy destination @@ -325,9 +346,10 @@ public class TransformActionExecuter extends ActionExecuterAbstractBase { // transform - will throw NoTransformerException if there are no transformers - TransformationOptions options = newTransformationOptions(ruleAction, sourceNodeRef); - options.setTargetNodeRef(destinationNodeRef); - this.contentService.transform(contentReader, contentWriter, options); + TransformationOptions transformationOptions = newTransformationOptions(ruleAction, sourceNodeRef); + transformationOptions.setTargetNodeRef(destinationNodeRef); + Map options = converter.getOptions(transformationOptions); + synchronousTransformClient.transform(contentReader, contentWriter, options, null, sourceNodeRef); } /** diff --git a/src/main/java/org/alfresco/repo/content/ContentServiceImpl.java b/src/main/java/org/alfresco/repo/content/ContentServiceImpl.java index d740654cf4..2d6d2e09df 100644 --- a/src/main/java/org/alfresco/repo/content/ContentServiceImpl.java +++ b/src/main/java/org/alfresco/repo/content/ContentServiceImpl.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + * 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 @@ -25,15 +25,6 @@ */ package org.alfresco.repo.content; -import java.io.File; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; import org.alfresco.repo.content.ContentServicePolicies.OnContentPropertyUpdatePolicy; @@ -41,12 +32,6 @@ import org.alfresco.repo.content.ContentServicePolicies.OnContentReadPolicy; import org.alfresco.repo.content.ContentServicePolicies.OnContentUpdatePolicy; import org.alfresco.repo.content.cleanup.EagerContentStoreCleaner; import org.alfresco.repo.content.filestore.FileContentStore; -import org.alfresco.repo.content.filestore.FileContentWriter; -import org.alfresco.repo.content.transform.ContentTransformer; -import org.alfresco.repo.content.transform.ContentTransformerRegistry; -import org.alfresco.repo.content.transform.TransformerDebug; -import org.alfresco.repo.content.transform.UnimportantTransformException; -import org.alfresco.repo.content.transform.UnsupportedTransformationException; import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.policy.ClassPolicyDelegate; import org.alfresco.repo.policy.JavaBehaviour; @@ -63,10 +48,8 @@ import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.MimetypeService; import org.alfresco.service.cmr.repository.MimetypeServiceAware; -import org.alfresco.service.cmr.repository.NoTransformerException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.TransformationOptions; import org.alfresco.service.cmr.usage.ContentQuotaException; import org.alfresco.service.namespace.QName; import org.alfresco.util.EqualsHelper; @@ -78,6 +61,12 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.extensions.surf.util.I18NUtil; +import java.io.Serializable; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + /** * Service implementation acting as a level of indirection between the client * and the underlying content store. @@ -89,7 +78,7 @@ import org.springframework.extensions.surf.util.I18NUtil; * @author Derek Hulley * @since 3.2 */ -public class ContentServiceImpl implements ContentService, ApplicationContextAware +public class ContentServiceImpl extends ContentTransformServiceAdaptor implements ContentService, ApplicationContextAware { private static Log logger = LogFactory.getLog(ContentServiceImpl.class); @@ -98,25 +87,16 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa private MimetypeService mimetypeService; private RetryingTransactionHelper transactionHelper; private ApplicationContext applicationContext; - @Deprecated - protected TransformerDebug transformerDebug; - - /** a registry of all available content transformers */ - @Deprecated - private ContentTransformerRegistry transformerRegistry; /** The cleaner that will ensure that rollbacks clean up after themselves */ private EagerContentStoreCleaner eagerContentStoreCleaner; /** the store to use. Any multi-store support is provided by the store implementation. */ private ContentStore store; /** the store for all temporarily created content */ private ContentStore tempStore; - @Deprecated - private ContentTransformer imageMagickContentTransformer; /** Should we consider zero byte content to be the same as no content? */ private boolean ignoreEmptyContent; - private boolean transformerFailover = true; - + /** * The policy component */ @@ -149,15 +129,6 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa this.mimetypeService = mimetypeService; } - /** - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - public void setTransformerRegistry(ContentTransformerRegistry transformerRegistry) - { - this.transformerRegistry = transformerRegistry; - } - public void setEagerContentStoreCleaner(EagerContentStoreCleaner eagerContentStoreCleaner) { this.eagerContentStoreCleaner = eagerContentStoreCleaner; @@ -174,35 +145,13 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa } /** - * * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. */ - @Deprecated - public void setImageMagickContentTransformer(ContentTransformer imageMagickContentTransformer) - { - this.imageMagickContentTransformer = imageMagickContentTransformer; - } - public void setIgnoreEmptyContent(boolean ignoreEmptyContent) { this.ignoreEmptyContent = ignoreEmptyContent; } - /** - * Allows fail over form one transformer to another when there is - * more than one transformer available. The cost is that the output - * of the transformer must go to a temporary file in case it fails. - * @param transformerFailover {@code true} (the default) indicate - * that fail over should take place. - * @deprecated The transformations code is being moved out of the codebase and replaced by the - * new async RenditionService2 or other external libraries. - */ - @Deprecated - public void setTransformerFailover(boolean transformerFailover) - { - this.transformerFailover = transformerFailover; - } - /* (non-Javadoc) * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) */ @@ -211,17 +160,6 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa this.applicationContext = applicationContext; } - /** - * Helper setter of the transformer debug. - * @param transformerDebug TransformerDebug - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - public void setTransformerDebug(TransformerDebug transformerDebug) - { - this.transformerDebug = transformerDebug; - } - /** * Service initialise */ @@ -564,407 +502,6 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa return tempStore.getWriter(ContentContext.NULL_CONTEXT); } - /** - * @see org.alfresco.repo.content.transform.ContentTransformerRegistry - * @see org.alfresco.repo.content.transform.ContentTransformer - * @see org.alfresco.service.cmr.repository.ContentService#transform(org.alfresco.service.cmr.repository.ContentReader, org.alfresco.service.cmr.repository.ContentWriter) - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - public void transform(ContentReader reader, ContentWriter writer) - { - // Call transform with no options - TransformationOptions options = new TransformationOptions(); - this.transform(reader, writer, options); - } - - /** - * @see org.alfresco.repo.content.transform.ContentTransformerRegistry - * @see org.alfresco.repo.content.transform.ContentTransformer - * @deprecated - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - public void transform(ContentReader reader, ContentWriter writer, Map options) - throws NoTransformerException, ContentIOException - { - transform(reader, writer, new TransformationOptions(options)); - } - - /** - * @see org.alfresco.repo.content.transform.ContentTransformerRegistry - * @see org.alfresco.repo.content.transform.ContentTransformer - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - public void transform(ContentReader reader, ContentWriter writer, TransformationOptions options) - throws NoTransformerException, ContentIOException - { - // check that source and target mimetypes are available - if (reader == null) - { - throw new AlfrescoRuntimeException("The content reader must be set"); - } - String sourceMimetype = reader.getMimetype(); - if (sourceMimetype == null) - { - throw new AlfrescoRuntimeException("The content reader mimetype must be set: " + reader); - } - String targetMimetype = writer.getMimetype(); - if (targetMimetype == null) - { - throw new AlfrescoRuntimeException("The content writer mimetype must be set: " + writer); - } - - long sourceSize = reader.getSize(); - try - { - // look for a transformer - transformerDebug.pushAvailable(reader.getContentUrl(), sourceMimetype, targetMimetype, options); - List transformers = getActiveTransformers(sourceMimetype, sourceSize, targetMimetype, options); - transformerDebug.availableTransformers(transformers, sourceSize, options, "ContentService.transform(...)"); - - int count = transformers.size(); - if (count == 0) - { - throw new NoTransformerException(sourceMimetype, targetMimetype); - } - - if (count == 1 || !transformerFailover) - { - ContentTransformer transformer = transformers.size() == 0 ? null : transformers.get(0); - transformer.transform(reader, writer, options); - } - else - { - failoverTransformers(reader, writer, options, targetMimetype, transformers); - } - } - finally - { - if (transformerDebug.isEnabled()) - { - transformerDebug.popAvailable(); - debugTransformations(sourceMimetype, targetMimetype, sourceSize, options); - } - } - } - - /** - * - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - private void failoverTransformers(ContentReader reader, ContentWriter writer, - TransformationOptions options, String targetMimetype, - List transformers) - { - List exceptions = null; - boolean done = false; - try - { - // Try the best transformer and then the next if it fails - // and so on down the list - char c = 'a'; - String outputFileExt = mimetypeService.getExtension(targetMimetype); - for (ContentTransformer transformer : transformers) - { - ContentWriter currentWriter = writer; - File tempFile = null; - try - { - // We can't know in advance which of the - // available transformer will work - if any. - // We can't write into the ContentWriter stream. - // So make a temporary file writer with the - // current transformer name. - tempFile = TempFileProvider.createTempFile( - "FailoverTransformer_intermediate_" - + transformer.getClass().getSimpleName() + "_", "." - + outputFileExt); - currentWriter = new FileContentWriter(tempFile); - currentWriter.setMimetype(targetMimetype); - currentWriter.setEncoding(writer.getEncoding()); - - if (c != 'a' && transformerDebug.isEnabled()) - { - transformerDebug.debug(""); - transformerDebug.debug("Try " + c + ")"); - } - c++; - - transformer.transform(reader, currentWriter, options); - - if (tempFile != null) - { - writer.putContent(tempFile); - } - - // No need to close input or output streams - // (according - // to comment in FailoverContentTransformer) - done = true; - return; - } - catch (Exception e) - { - if (exceptions == null) - { - exceptions = new ArrayList(); - } - if (!(e instanceof AlfrescoRuntimeException)) - { - e = new AlfrescoRuntimeException(e.getMessage(), e); - } - exceptions.add((AlfrescoRuntimeException)e); - - // Set a new reader to refresh the input stream. - reader = reader.getReader(); - } - } - // Throw the exception from the first transformer. The - // others are consumed. - if (exceptions != null) - { - throw exceptions.get(0); - } - } - finally - { - // Log exceptions that we have consumed. We may have thrown the first one if - // none of the transformers worked. - if (exceptions != null) - { - boolean first = true; - for (Exception e : exceptions) - { - Throwable rootCause = (e instanceof AlfrescoRuntimeException) ? ((AlfrescoRuntimeException)e).getRootCause() : null; - String message = (rootCause == null ? null : rootCause.getMessage()); - if (done) - { - message = "Transformer succeeded after previous transformer failed"+ (message == null ? "" : ": "+message); - if (rootCause instanceof UnsupportedTransformationException || - rootCause instanceof UnimportantTransformException) - { - logger.debug(message); - } - else - { - logger.warn(message, e); - } - } - else if (!first) // The first exception is logged later - { - message = "Transformer exception"+ (message == null ? "" : ": "+message); - if (rootCause instanceof UnsupportedTransformationException || - rootCause instanceof UnimportantTransformException) - { - logger.debug(message); - } - else - { - logger.error(message, e); - } - first = false; - } - } - } - } - } - - /** - * @see org.alfresco.repo.content.transform.ContentTransformerRegistry - * @see org.alfresco.repo.content.transform.ContentTransformer - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - public ContentTransformer getTransformer(String sourceMimetype, String targetMimetype) - { - return getTransformer(null, sourceMimetype, -1, targetMimetype, new TransformationOptions()); - } - - /** - * - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - public ContentTransformer getTransformer(String sourceMimetype, String targetMimetype, TransformationOptions options) - { - return getTransformer(null, sourceMimetype, -1, targetMimetype, options); - } - - /** - * @see org.alfresco.service.cmr.repository.ContentService#getTransformer(String, java.lang.String, long, java.lang.String, org.alfresco.service.cmr.repository.TransformationOptions) - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - public ContentTransformer getTransformer(String sourceUrl, String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options) - { - List transformers = getTransformers(sourceUrl, sourceMimetype, sourceSize, targetMimetype, options); - return (transformers == null) ? null : transformers.get(0); - } - - /** - * @see org.alfresco.service.cmr.repository.ContentService#getTransformers(String, java.lang.String, long, java.lang.String, org.alfresco.service.cmr.repository.TransformationOptions) - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - public List getTransformers(String sourceUrl, String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options) - { - try - { - // look for a transformer - transformerDebug.pushAvailable(sourceUrl, sourceMimetype, targetMimetype, options); - List transformers = getActiveTransformers(sourceMimetype, sourceSize, targetMimetype, options); - transformerDebug.availableTransformers(transformers, sourceSize, options, "ContentService.getTransformer(...)"); - return transformers.isEmpty() ? null : transformers; - } - finally - { - transformerDebug.popAvailable(); - } - } - - /** - * Checks if the file just uploaded into Share is a special "debugTransformers.txt" file and - * if it is creates TransformerDebug that lists all the supported mimetype transformation for - * each transformer. - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - private void debugTransformations(String sourceMimetype, String targetMimetype, - long sourceSize, TransformationOptions transformOptions) - { - // check the file name - if (MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(sourceMimetype) && - MimetypeMap.MIMETYPE_IMAGE_PNG.equals(targetMimetype)) - { - String fileName = transformerDebug.getFileName(transformOptions, true, 0); - if (fileName != null && fileName.contains("debugTransformers.txt")) - { - transformerDebug.transformationsByTransformer(null, false, false, null); - transformerDebug.transformationsByExtension(null, null, false, false, false, null); - } - } - } - - /** - * {@inheritDoc} - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - public long getMaxSourceSizeBytes(String sourceMimetype, String targetMimetype, TransformationOptions options) - { - try - { - long maxSourceSize = 0; - transformerDebug.pushAvailable(null, sourceMimetype, targetMimetype, options); - List transformers = getActiveTransformers(sourceMimetype, -1, targetMimetype, options); - for (ContentTransformer transformer: transformers) - { - long maxSourceSizeKBytes = transformer.getMaxSourceSizeKBytes(sourceMimetype, targetMimetype, options); - if (maxSourceSize >= 0) - { - if (maxSourceSizeKBytes < 0) - { - maxSourceSize = -1; - } - else if (maxSourceSizeKBytes > 0 && maxSourceSize < maxSourceSizeKBytes) - { - maxSourceSize = maxSourceSizeKBytes; - } - } - // if maxSourceSizeKBytes == 0 this implies the transformation is disabled - } - if (transformerDebug.isEnabled()) - { - transformerDebug.availableTransformers(transformers, -1, options, - "ContentService.getMaxSourceSizeBytes() = "+transformerDebug.fileSize(maxSourceSize*1024)); - } - return (maxSourceSize > 0) ? maxSourceSize * 1024 : maxSourceSize; - } - finally - { - transformerDebug.popAvailable(); - } - } - - /** - * - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - public List getActiveTransformers(String sourceMimetype, String targetMimetype, TransformationOptions options) - { - return getActiveTransformers(sourceMimetype, -1, targetMimetype, options); - } - - /** - * - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - public List getActiveTransformers(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options) - { - return transformerRegistry.getActiveTransformers(sourceMimetype, sourceSize, targetMimetype, options); - } - - /** - * @see org.alfresco.service.cmr.repository.ContentService#getImageTransformer() - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - public ContentTransformer getImageTransformer() - { - return imageMagickContentTransformer; - } - - /** - * @see org.alfresco.repo.content.transform.ContentTransformerRegistry - * @see org.alfresco.repo.content.transform.ContentTransformer - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - public boolean isTransformable(ContentReader reader, ContentWriter writer) - { - return isTransformable(reader, writer, new TransformationOptions()); - } - - /** - * @see org.alfresco.service.cmr.repository.ContentService#isTransformable(org.alfresco.service.cmr.repository.ContentReader, org.alfresco.service.cmr.repository.ContentWriter, org.alfresco.service.cmr.repository.TransformationOptions) - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - public boolean isTransformable(ContentReader reader, ContentWriter writer, TransformationOptions options) - { - // check that source and target mimetypes are available - String sourceMimetype = reader.getMimetype(); - if (sourceMimetype == null) - { - throw new AlfrescoRuntimeException("The content reader mimetype must be set: " + reader); - } - String targetMimetype = writer.getMimetype(); - if (targetMimetype == null) - { - throw new AlfrescoRuntimeException("The content writer mimetype must be set: " + writer); - } - - long sourceSize = reader.getSize(); - try - { - // look for a transformer - transformerDebug.pushAvailable(reader.getContentUrl(), sourceMimetype, targetMimetype, options); - List transformers = getActiveTransformers(sourceMimetype, sourceSize, targetMimetype, options); - transformerDebug.availableTransformers(transformers, sourceSize, options, "ContentService.isTransformable(...)"); - - return transformers.size() > 0; - } - finally - { - transformerDebug.popAvailable(); - } - } - /** * Ensures that, upon closure of the output stream, the node is updated with * the latest URL of the content to which it refers. diff --git a/src/main/java/org/alfresco/repo/content/ContentTransformServiceAdaptor.java b/src/main/java/org/alfresco/repo/content/ContentTransformServiceAdaptor.java new file mode 100644 index 0000000000..874bcad9a6 --- /dev/null +++ b/src/main/java/org/alfresco/repo/content/ContentTransformServiceAdaptor.java @@ -0,0 +1,311 @@ +/* + * #%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.repo.content; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.content.transform.AbstractContentTransformer2; +import org.alfresco.repo.content.transform.ContentTransformer; +import org.alfresco.repo.content.transform.LocalTransform; +import org.alfresco.repo.content.transform.LocalTransformServiceRegistry; +import org.alfresco.repo.content.transform.UnsupportedTransformationException; +import org.alfresco.repo.rendition2.LegacySynchronousTransformClient; +import org.alfresco.repo.rendition2.SynchronousTransformClient; +import org.alfresco.repo.rendition2.TransformationOptionsConverter; +import org.alfresco.service.cmr.repository.ContentIOException; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentTransformService; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.NoTransformerException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.TransformationOptions; +import org.alfresco.transform.client.registry.TransformServiceRegistry; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * Contains deprecated methods originally from {@link org.alfresco.repo.content.ContentServiceImpl} that is used to + * perform Legacy transforms. + * + * @author adavis + */ +@Deprecated +public class ContentTransformServiceAdaptor implements ContentTransformService +{ + private ContentTransformer imageMagickContentTransformer; + private LegacySynchronousTransformClient legacySynchronousTransformClient; + private LocalTransformServiceRegistry localTransformServiceRegistryImpl; + private SynchronousTransformClient synchronousTransformClient; + private TransformServiceRegistry localTransformServiceRegistry; + private TransformationOptionsConverter converter; + + @Deprecated + public void setImageMagickContentTransformer(ContentTransformer imageMagickContentTransformer) + { + this.imageMagickContentTransformer = imageMagickContentTransformer; + } + + public void setLegacySynchronousTransformClient(LegacySynchronousTransformClient legacySynchronousTransformClient) + { + this.legacySynchronousTransformClient = legacySynchronousTransformClient; + } + + public void setLocalTransformServiceRegistryImpl(LocalTransformServiceRegistry localTransformServiceRegistryImpl) + { + this.localTransformServiceRegistryImpl = localTransformServiceRegistryImpl; + } + + public void setSynchronousTransformClient(SynchronousTransformClient synchronousTransformClient) + { + this.synchronousTransformClient = synchronousTransformClient; + } + + public void setLocalTransformServiceRegistry(TransformServiceRegistry localTransformServiceRegistry) + { + this.localTransformServiceRegistry = localTransformServiceRegistry; + } + + public void setConverter(TransformationOptionsConverter converter) + { + this.converter = converter; + } + + @Deprecated + @Override + public void transform(ContentReader reader, ContentWriter writer) + { + synchronousTransformClient.transform(reader, writer, Collections.emptyMap(), null, null); + } + + @Deprecated + @Override + public void transform(ContentReader reader, ContentWriter writer, Map legacyOptionsMap) + throws NoTransformerException, ContentIOException + { + TransformationOptions transformationOptions = new TransformationOptions(legacyOptionsMap); + Map options = converter.getOptions(transformationOptions); + synchronousTransformClient.transform(reader, writer, options, null, null); + } + + @Deprecated + @Override + public void transform(ContentReader reader, ContentWriter writer, TransformationOptions transformationOptions) + throws NoTransformerException, ContentIOException + { + try + { + Map options = converter.getOptions(transformationOptions); + synchronousTransformClient.transform(reader, writer, options, null, null); + } + catch (UnsupportedTransformationException ute) + { + throw newNoTransformerException(reader, writer); + } + catch (IllegalArgumentException iae) + { + if (iae.getMessage().contains("sourceNodeRef null has no content")) + { + throw newNoTransformerException(reader, writer); + } + throw new AlfrescoRuntimeException(iae.getMessage(), iae); + } + } + + private NoTransformerException newNoTransformerException(ContentReader reader, ContentWriter writer) + { + String sourceMimetype = reader == null ? "null" : reader.getMimetype(); + String targetMimetype = writer == null ? "null" : writer.getMimetype(); + return new NoTransformerException(sourceMimetype, targetMimetype); + } + + @Deprecated + @Override + public ContentTransformer getTransformer(String sourceMimetype, String targetMimetype) + { + return getTransformer(sourceMimetype, targetMimetype, new TransformationOptions()); + } + + @Deprecated + @Override + public ContentTransformer getTransformer(String sourceMimetype, String targetMimetype, TransformationOptions options) + { + return getTransformer(null, sourceMimetype, -1, targetMimetype, new TransformationOptions()); + } + + @Deprecated + @Override + public ContentTransformer getTransformer(String sourceUrl, String sourceMimetype, long sourceSize, + String targetMimetype, TransformationOptions options) + { + ContentTransformer localTransformer = wrapLocalTransformer(sourceUrl, sourceMimetype, sourceSize, targetMimetype, options); + return localTransformer == null + ? legacySynchronousTransformClient.getTransformer(sourceUrl, sourceMimetype, sourceSize, targetMimetype, options) + : localTransformer; + } + + @Deprecated + @Override + // Same as getActiveTransformers, but with debug + public List getTransformers(String sourceUrl, String sourceMimetype, long sourceSize, + String targetMimetype, TransformationOptions options) + { + ContentTransformer localTransformer = wrapLocalTransformer(sourceUrl, sourceMimetype, sourceSize, targetMimetype, options); + return localTransformer == null + ? legacySynchronousTransformClient.getTransformers(sourceUrl, sourceMimetype, sourceSize, targetMimetype, options) + : Collections.singletonList(localTransformer); + } + + @Deprecated + @Override + // Same as getTransformers, but without debug + public List getActiveTransformers(String sourceMimetype, + String targetMimetype, TransformationOptions options) + { + return getActiveTransformers(sourceMimetype, -1, targetMimetype, options); + } + + @Deprecated + @Override + // Same as getTransformers, but without debug + public List getActiveTransformers(String sourceMimetype, long sourceSize, + String targetMimetype, TransformationOptions options) + { + ContentTransformer localTransformer = wrapLocalTransformer(null, sourceMimetype, sourceSize, targetMimetype, options); + return localTransformer == null + ? legacySynchronousTransformClient.getActiveTransformers(sourceMimetype, sourceSize, targetMimetype, options) + : Collections.singletonList(localTransformer); + } + + private ContentTransformer wrapLocalTransformer(String sourceUrl, String sourceMimetype, long sourceSize, + String targetMimetype, TransformationOptions transformationOptions) + { + AbstractContentTransformer2 transformer = null; + Map options = converter.getOptions(transformationOptions); + LocalTransform localTransform = localTransformServiceRegistryImpl.getLocalTransform(sourceMimetype, + sourceSize, targetMimetype, options, null); + if (localTransform != null) + { + transformer = new AbstractContentTransformer2() { + + @Override + public void transform(ContentReader reader, ContentWriter writer, TransformationOptions options) + throws ContentIOException + { + try + { + transformInternal(reader, writer, transformationOptions); + } + catch (Exception e) + { + throw new ContentIOException(e.getMessage(), e); + } + } + + + @Override + protected void transformInternal(ContentReader reader, ContentWriter writer, TransformationOptions transformationOptions) throws Exception + { + localTransform.transform(reader, writer, options, null, null); + } + + @Override + public void register() + { + } + + @Override + public boolean isSupportedTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options) + { + return true; + } + + @Override + public boolean isTransformable(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options) + { + return true; + } + + @Override + public boolean isTransformableMimetype(String sourceMimetype, String targetMimetype, TransformationOptions options) + { + return true; + } + + @Override + public boolean isTransformableSize(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options) + { + return true; + } + + @Override + public String getName() + { + return "Wrapped<"+localTransformServiceRegistryImpl.findTransformerName(sourceMimetype, sourceSize, + targetMimetype, options, null)+">"; + } + }; + } + return transformer; + } + + @Deprecated + @Override + public long getMaxSourceSizeBytes(String sourceMimetype, + String targetMimetype, TransformationOptions transformationOptions) + { + Map options = converter.getOptions(transformationOptions); + return localTransformServiceRegistry.findMaxSize(sourceMimetype, targetMimetype, options, null); + } + + @Deprecated + @Override + public ContentTransformer getImageTransformer() + { + return imageMagickContentTransformer; + } + + @Deprecated + @Override + public boolean isTransformable(ContentReader reader, ContentWriter writer) + { + return isTransformable(reader, writer, null); + } + + @Deprecated + @Override + public boolean isTransformable(ContentReader reader, ContentWriter writer, TransformationOptions transformationOptions) + { + String sourceMimetype = reader.getMimetype(); + long sourceSizeInBytes = reader.getSize(); + String contentUrl = reader.getContentUrl(); + String targetMimetype = writer.getMimetype(); + NodeRef sourceNodeRef = transformationOptions.getSourceNodeRef(); + Map options = converter.getOptions(transformationOptions); + return synchronousTransformClient.isSupported(sourceMimetype, sourceSizeInBytes, contentUrl, targetMimetype, + options, null, sourceNodeRef); + } +} diff --git a/src/main/java/org/alfresco/repo/content/transform/AbstractContentTransformer2.java b/src/main/java/org/alfresco/repo/content/transform/AbstractContentTransformer2.java index 0b6a8f5089..b6fd82aff7 100644 --- a/src/main/java/org/alfresco/repo/content/transform/AbstractContentTransformer2.java +++ b/src/main/java/org/alfresco/repo/content/transform/AbstractContentTransformer2.java @@ -216,7 +216,7 @@ public abstract class AbstractContentTransformer2 extends AbstractContentTransfo /** * @see org.alfresco.repo.content.transform.ContentTransformer#transform(org.alfresco.service.cmr.repository.ContentReader, org.alfresco.service.cmr.repository.ContentWriter, org.alfresco.service.cmr.repository.TransformationOptions) */ - public final void transform(ContentReader reader, ContentWriter writer, TransformationOptions options) + public void transform(ContentReader reader, ContentWriter writer, TransformationOptions options) throws ContentIOException { try 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 7dff7edb69..96064404ec 100644 --- a/src/main/java/org/alfresco/repo/content/transform/AbstractLocalTransform.java +++ b/src/main/java/org/alfresco/repo/content/transform/AbstractLocalTransform.java @@ -84,7 +84,7 @@ public abstract class AbstractLocalTransform implements LocalTransform String sourceMimetype, String targetMimetype, String sourceExtension, String targetExtension, String renditionName, NodeRef sourceNodeRef) - throws Exception; + throws UnsupportedTransformationException, ContentIOException; public String getName() { @@ -99,7 +99,6 @@ public abstract class AbstractLocalTransform implements LocalTransform @Override public void transform(ContentReader reader, ContentWriter writer, Map transformOptions, String renditionName, NodeRef sourceNodeRef) - throws Exception { if (isAvailable()) { @@ -144,16 +143,15 @@ public abstract class AbstractLocalTransform implements LocalTransform private void transformWithDebug(ContentReader reader, ContentWriter writer, Map transformOptions, String renditionName, NodeRef sourceNodeRef, String sourceMimetype, String targetMimetype, - String sourceExtension, String targetExtension) throws Exception + String sourceExtension, String targetExtension) { - try { depth.set(depth.get()+1); if (transformerDebug.isEnabled()) { - transformerDebug.pushTransform(name, reader.getContentUrl(), sourceMimetype, + transformerDebug.pushTransform("Local:"+name, reader.getContentUrl(), sourceMimetype, targetMimetype, reader.getSize(), renditionName, sourceNodeRef); } @@ -173,7 +171,6 @@ public abstract class AbstractLocalTransform implements LocalTransform } private void strictMimetypeCheck(ContentReader reader, NodeRef sourceNodeRef, String declaredMimetype) - throws UnsupportedTransformationException { if (mimetypeService != null && strictMimeTypeCheck && depth.get() == 1) { @@ -222,7 +219,7 @@ public abstract class AbstractLocalTransform implements LocalTransform private void retryWithDifferentMimetype(ContentReader reader, ContentWriter writer, String targetMimetype, Map transformOptions, String renditionName, - NodeRef sourceNodeRef, Throwable e) throws Exception + NodeRef sourceNodeRef, Throwable e) { if (mimetypeService != null && localTransformServiceRegistry != null) { @@ -238,7 +235,7 @@ public abstract class AbstractLocalTransform implements LocalTransform } else { - transformerDebug.debug(" Failed: Mime type was '" + differentType + "'", e); + transformerDebug.debug(" Failed: Mimetype was '" + differentType + "'", e); String claimedMimetype = reader.getMimetype(); if (retryTransformOnDifferentMimeType) diff --git a/src/main/java/org/alfresco/repo/content/transform/ComplexContentTransformer.java b/src/main/java/org/alfresco/repo/content/transform/ComplexContentTransformer.java index 5bf9538de4..189e8eb03c 100644 --- a/src/main/java/org/alfresco/repo/content/transform/ComplexContentTransformer.java +++ b/src/main/java/org/alfresco/repo/content/transform/ComplexContentTransformer.java @@ -39,8 +39,8 @@ import java.util.Map; import org.alfresco.api.AlfrescoPublicApi; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.repo.content.filestore.FileContentWriter; +import org.alfresco.repo.rendition2.LegacySynchronousTransformClient; import org.alfresco.service.cmr.repository.ContentReader; -import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.TransformationOptionLimits; @@ -84,7 +84,7 @@ public class ComplexContentTransformer extends AbstractContentTransformer2 imple private List transformers; private List intermediateMimetypes; private Map transformationOptionOverrides; - private ContentService contentService; + private LegacySynchronousTransformClient legacySynchronousTransformClient; public ComplexContentTransformer() { @@ -93,13 +93,11 @@ public class ComplexContentTransformer extends AbstractContentTransformer2 imple /** * The list of transformers to use. If any element is null * all possible transformers will be considered. If any element - * is null, the contentService property must be set. + * is null, the legacySynchronousTransformClient property must be set. *

* If a single transformer is supplied, then it will still be used. * * @param transformers list of at least one transformer - * - * @see #setContentService(ContentService) */ public void setTransformers(List transformers) { @@ -135,14 +133,9 @@ public class ComplexContentTransformer extends AbstractContentTransformer2 imple this.transformationOptionOverrides = transformationOptionOverrides; } - /** - * Sets the ContentService. Only required if {@code null} transformers - * are provided to {@link #setTransformers(List)}. - * @param contentService - */ - public void setContentService(ContentService contentService) + public void setLegacySynchronousTransformClient(LegacySynchronousTransformClient legacySynchronousTransformClient) { - this.contentService = contentService; + this.legacySynchronousTransformClient = legacySynchronousTransformClient; } /** @@ -167,9 +160,9 @@ public class ComplexContentTransformer extends AbstractContentTransformer2 imple { if (transformer == null) { - if (contentService == null) + if (legacySynchronousTransformClient == null) { - throw new AlfrescoRuntimeException("'contentService' is a required property if " + + throw new AlfrescoRuntimeException("'legacySynchronousTransformClient' is a required property if " + "there are any null (dynamic) transformers"); } break; @@ -297,7 +290,7 @@ public class ComplexContentTransformer extends AbstractContentTransformer2 imple { parentTransformers.get().push(this); @SuppressWarnings("deprecation") - List firstTansformers = contentService.getActiveTransformers( + List firstTansformers = legacySynchronousTransformClient.getActiveTransformers( currentSourceMimetype, -1, currentTargetMimetype, options); if (firstTansformers.isEmpty()) { @@ -344,7 +337,7 @@ public class ComplexContentTransformer extends AbstractContentTransformer2 imple { parentTransformers.get().push(this); @SuppressWarnings("deprecation") - List firstTansformers = contentService.getActiveTransformers( + List firstTansformers = legacySynchronousTransformClient.getActiveTransformers( sourceMimetype, -1, firstTargetMimetype, options); pageLimitSupported = !firstTansformers.isEmpty(); if (pageLimitSupported) @@ -397,7 +390,7 @@ public class ComplexContentTransformer extends AbstractContentTransformer2 imple { parentTransformers.get().push(this); @SuppressWarnings("deprecation") - List firstTansformers = contentService.getActiveTransformers( + List firstTansformers = legacySynchronousTransformClient.getActiveTransformers( sourceMimetype, -1, firstTargetMimetype, options); if (!firstTansformers.isEmpty()) { @@ -480,7 +473,7 @@ public class ComplexContentTransformer extends AbstractContentTransformer2 imple try { parentTransformers.get().push(this); - contentService.transform(currentReader, currentWriter, options); + legacySynchronousTransformClient.transform(currentReader, currentWriter, options); } finally { diff --git a/src/main/java/org/alfresco/repo/content/transform/LocalFailoverTransform.java b/src/main/java/org/alfresco/repo/content/transform/LocalFailoverTransform.java index 9fafefc060..a78648d3ac 100644 --- a/src/main/java/org/alfresco/repo/content/transform/LocalFailoverTransform.java +++ b/src/main/java/org/alfresco/repo/content/transform/LocalFailoverTransform.java @@ -26,6 +26,7 @@ package org.alfresco.repo.content.transform; import org.alfresco.repo.content.filestore.FileContentWriter; +import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.MimetypeService; @@ -77,14 +78,14 @@ public class LocalFailoverTransform extends AbstractLocalTransform ContentWriter writer, Map transformOptions, String sourceMimetype, String targetMimetype, String sourceExtension, String targetExtension, - String renditionName, NodeRef sourceNodeRef) throws Exception + String renditionName, NodeRef sourceNodeRef) { 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; + RuntimeException transformationException = null; for (int i = 0; i < transformers.size(); i++) { @@ -111,7 +112,7 @@ public class LocalFailoverTransform extends AbstractLocalTransform // attempt to transform stepTransformer.transform(reader, currentWriter, transformOptions, renditionName, sourceNodeRef); } - catch (Exception are) + catch (UnsupportedTransformationException | ContentIOException are) { if (transformationException == null) { 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 d31dc4d921..2250818b1d 100644 --- a/src/main/java/org/alfresco/repo/content/transform/LocalPipelineTransform.java +++ b/src/main/java/org/alfresco/repo/content/transform/LocalPipelineTransform.java @@ -91,7 +91,7 @@ public class LocalPipelineTransform extends AbstractLocalTransform ContentWriter writer, Map transformOptions, String sourceMimetype, String targetMimetype, String sourceExtension, String targetExtension, - String renditionName, NodeRef sourceNodeRef) throws Exception + String renditionName, NodeRef sourceNodeRef) { ContentReader currentReader = reader; int lastI = transformers.size() - 1; diff --git a/src/main/java/org/alfresco/repo/content/transform/LocalTransform.java b/src/main/java/org/alfresco/repo/content/transform/LocalTransform.java index 2a7bc61110..7b989796e3 100644 --- a/src/main/java/org/alfresco/repo/content/transform/LocalTransform.java +++ b/src/main/java/org/alfresco/repo/content/transform/LocalTransform.java @@ -25,6 +25,7 @@ */ package org.alfresco.repo.content.transform; +import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; @@ -36,7 +37,21 @@ import java.util.Map; */ public interface LocalTransform { + /** + * Requests a synchronous transform. + * @param reader of the source content + * @param writer to the target node's content + * @param transformOptions 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. + * @param sourceNodeRef the source node + * @throws UnsupportedTransformationException if there is an unexpected failure to transform, normally in a + * pipeline, where an intermediate transform may not be performed after all because an intermediate + * converion is too big. + * @throws ContentIOException there is an unexpected communication or transformation failure. + */ void transform(ContentReader reader, ContentWriter writer, Map transformOptions, String renditionName, NodeRef sourceNodeRef) - throws Exception; + throws UnsupportedTransformationException, ContentIOException; } 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 2eb2b474ce..5aad930980 100644 --- a/src/main/java/org/alfresco/repo/content/transform/LocalTransformImpl.java +++ b/src/main/java/org/alfresco/repo/content/transform/LocalTransformImpl.java @@ -144,7 +144,7 @@ public class LocalTransformImpl extends AbstractLocalTransform ContentWriter writer, Map transformOptions, String sourceMimetype, String targetMimetype, String sourceExtension, String targetExtension, - String renditionName, NodeRef sourceNodeRef) throws Exception + String renditionName, NodeRef sourceNodeRef) { // 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 diff --git a/src/main/java/org/alfresco/repo/content/transform/RemoteTransformerClient.java b/src/main/java/org/alfresco/repo/content/transform/RemoteTransformerClient.java index de0d7e680c..dd30540ff3 100644 --- a/src/main/java/org/alfresco/repo/content/transform/RemoteTransformerClient.java +++ b/src/main/java/org/alfresco/repo/content/transform/RemoteTransformerClient.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2018 Alfresco Software Limited + * 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 @@ -86,11 +86,11 @@ public class RemoteTransformerClient } public void request(ContentReader reader, ContentWriter writer, String sourceMimetype, String sourceExtension, - String targetExtension, long timeoutMs, Log logger, String... args) throws IllegalAccessException + String targetExtension, long timeoutMs, Log logger, String... args) { if (args.length % 2 != 0) { - throw new IllegalAccessException("There should be a value for each request property"); + throw new IllegalArgumentException("There should be a value for each request property"); } StringJoiner sj = new StringJoiner(" "); diff --git a/src/main/java/org/alfresco/repo/content/transform/RuntimeExecutableContentTransformerOptions.java b/src/main/java/org/alfresco/repo/content/transform/RuntimeExecutableContentTransformerOptions.java index 7ed61342f9..e7b5be9d57 100644 --- a/src/main/java/org/alfresco/repo/content/transform/RuntimeExecutableContentTransformerOptions.java +++ b/src/main/java/org/alfresco/repo/content/transform/RuntimeExecutableContentTransformerOptions.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + * 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 @@ -56,7 +56,12 @@ public class RuntimeExecutableContentTransformerOptions extends TransformationOp { this.propertyValues = propertyValues; } - + + public Map getPropertyValues() + { + return propertyValues; + } + /** * Overrides the base class implementation to add all values set in {@link #setPropertyValues(Map)} */ diff --git a/src/main/java/org/alfresco/repo/content/transform/TransformerConfigDynamicTransformers.java b/src/main/java/org/alfresco/repo/content/transform/TransformerConfigDynamicTransformers.java index 89bb6731d7..a37021da49 100644 --- a/src/main/java/org/alfresco/repo/content/transform/TransformerConfigDynamicTransformers.java +++ b/src/main/java/org/alfresco/repo/content/transform/TransformerConfigDynamicTransformers.java @@ -41,6 +41,7 @@ import java.util.Properties; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.rendition2.LegacySynchronousTransformClient; import org.alfresco.service.cmr.module.ModuleService; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.MimetypeService; @@ -63,16 +64,16 @@ public class TransformerConfigDynamicTransformers extends TransformerPropertyNam private final List dynamicTransformers = new ArrayList(); public TransformerConfigDynamicTransformers(TransformerConfig transformerConfig, TransformerProperties transformerProperties, - MimetypeService mimetypeService, ContentService contentService, ContentTransformerRegistry transformerRegistry, + MimetypeService mimetypeService, LegacySynchronousTransformClient legacySynchronousTransformClient, ContentTransformerRegistry transformerRegistry, TransformerDebug transformerDebug, ModuleService moduleService, DescriptorService descriptorService, Properties globalProperties) { - createDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + createDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, moduleService, descriptorService, globalProperties); } private void createDynamicTransformers(TransformerConfig transformerConfig, TransformerProperties transformerProperties, - MimetypeService mimetypeService, ContentService contentService, ContentTransformerRegistry transformerRegistry, + MimetypeService mimetypeService, LegacySynchronousTransformClient legacySynchronousTransformClient, ContentTransformerRegistry transformerRegistry, TransformerDebug transformerDebug, ModuleService moduleService, DescriptorService descriptorService, Properties globalProperties) { @@ -124,10 +125,10 @@ public class TransformerConfigDynamicTransformers extends TransformerPropertyNam AbstractContentTransformer2 transformer = property.suffix.equals(PIPELINE) ? createComplexTransformer(property, transformerConfig, mimetypeService, - contentService, transformerRegistry, transformerDebug, available, + legacySynchronousTransformClient, transformerRegistry, transformerDebug, available, globalProperties) : createFailoverTransformer(property, transformerConfig, mimetypeService, - contentService, transformerRegistry, transformerDebug, available, + transformerRegistry, transformerDebug, available, globalProperties); transformer.register(); processed.add(property); @@ -174,7 +175,7 @@ public class TransformerConfigDynamicTransformers extends TransformerPropertyNam private AbstractContentTransformer2 createComplexTransformer(TransformerSourceTargetSuffixValue property, TransformerConfig transformerConfig, - MimetypeService mimetypeService, ContentService contentService, + MimetypeService mimetypeService, LegacySynchronousTransformClient legacySynchronousTransformClient, ContentTransformerRegistry transformerRegistry, TransformerDebug transformerDebug, boolean available, Properties globalProperties) { @@ -192,11 +193,11 @@ public class TransformerConfigDynamicTransformers extends TransformerPropertyNam return getCommentNameAndAvailable(true); // suppress the ...available=false line as it is reported anyway if set } }; - setupContentTransformer2(property, transformerConfig, mimetypeService, contentService, + setupContentTransformer2(property, transformerConfig, mimetypeService, transformerRegistry, transformerDebug, available, transformer, transformers, globalProperties); // baseComplexContentTransformer - transformer.setContentService(contentService); + transformer.setLegacySynchronousTransformClient(legacySynchronousTransformClient); // ComplexContentTransformer transformer.setTransformers(transformers); @@ -207,7 +208,7 @@ public class TransformerConfigDynamicTransformers extends TransformerPropertyNam private AbstractContentTransformer2 createFailoverTransformer(TransformerSourceTargetSuffixValue property, TransformerConfig transformerConfig, - MimetypeService mimetypeService, ContentService contentService, + MimetypeService mimetypeService, ContentTransformerRegistry transformerRegistry, TransformerDebug transformerDebug, boolean available, Properties globalProperties) { @@ -224,7 +225,7 @@ public class TransformerConfigDynamicTransformers extends TransformerPropertyNam return getCommentNameAndAvailable(true); // suppress the ...available=false line as it is reported anyway if set } }; - setupContentTransformer2(property, transformerConfig, mimetypeService, contentService, + setupContentTransformer2(property, transformerConfig, mimetypeService, transformerRegistry, transformerDebug, available, transformer, transformers, globalProperties); // FailoverContentTransformer @@ -292,7 +293,7 @@ public class TransformerConfigDynamicTransformers extends TransformerPropertyNam // Set properties common to ComplexContentTransformer and FailoverContentTransformer. private void setupContentTransformer2(TransformerSourceTargetSuffixValue property, TransformerConfig transformerConfig, MimetypeService mimetypeService, - ContentService contentService, ContentTransformerRegistry transformerRegistry, + ContentTransformerRegistry transformerRegistry, TransformerDebug transformerDebug, boolean available, AbstractContentTransformer2 transformer, List transformers, Properties globalProperties) diff --git a/src/main/java/org/alfresco/repo/content/transform/TransformerConfigImpl.java b/src/main/java/org/alfresco/repo/content/transform/TransformerConfigImpl.java index 9078679962..093e37ca95 100644 --- a/src/main/java/org/alfresco/repo/content/transform/TransformerConfigImpl.java +++ b/src/main/java/org/alfresco/repo/content/transform/TransformerConfigImpl.java @@ -33,8 +33,8 @@ import java.util.Properties; import java.util.Set; import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; +import org.alfresco.repo.rendition2.LegacySynchronousTransformClient; import org.alfresco.service.cmr.module.ModuleService; -import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.MalformedNodeRefException; import org.alfresco.service.cmr.repository.MimetypeService; import org.alfresco.service.cmr.repository.NodeRef; @@ -60,7 +60,7 @@ public class TransformerConfigImpl extends AbstractLifecycleBean implements Tran private MimetypeService mimetypeService; - private ContentService contentService; + private LegacySynchronousTransformClient legacySynchronousTransformClient; private ContentTransformerRegistry transformerRegistry; @@ -131,9 +131,9 @@ public class TransformerConfigImpl extends AbstractLifecycleBean implements Tran this.mimetypeService = mimetypeService; } - public void setContentService(ContentService contentService) + public void setLegacySynchronousTransformClient(LegacySynchronousTransformClient legacySynchronousTransformClient) { - this.contentService = contentService; + this.legacySynchronousTransformClient = legacySynchronousTransformClient; } public void setContentTransformerRegistry(ContentTransformerRegistry transformerRegistry) @@ -180,7 +180,7 @@ public class TransformerConfigImpl extends AbstractLifecycleBean implements Tran transformerProperties = new TransformerProperties(subsystem, globalProperties); dynamicTransformers = new TransformerConfigDynamicTransformers(this, transformerProperties, mimetypeService, - contentService, transformerRegistry, transformerDebug, moduleService, descriptorService, globalProperties); + legacySynchronousTransformClient, transformerRegistry, transformerDebug, moduleService, descriptorService, globalProperties); statistics= new TransformerConfigStatistics(this, mimetypeService); limits = new TransformerConfigLimits(transformerProperties, mimetypeService); supported = new TransformerConfigSupported(transformerProperties, mimetypeService); diff --git a/src/main/java/org/alfresco/repo/content/transform/TransformerDebug.java b/src/main/java/org/alfresco/repo/content/transform/TransformerDebug.java index 76b135a760..5b07b03b7d 100644 --- a/src/main/java/org/alfresco/repo/content/transform/TransformerDebug.java +++ b/src/main/java/org/alfresco/repo/content/transform/TransformerDebug.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + * 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 @@ -710,6 +710,16 @@ public class TransformerDebug implements ApplicationContextAware } } + public void debug(String sourceMimetype, String targetMimetype, NodeRef sourceNodeRef, long sourceSize, + String renditionName, String message) + { + String fileName = getFileName(sourceNodeRef, true, -1); + log(" "+getMimetypeExt(sourceMimetype)+getMimetypeExt(targetMimetype) + + ((fileName != null) ? fileName+' ' : "")+ + ((sourceSize >= 0) ? fileSize(sourceSize)+' ' : "") + + (renditionName != null ? "-- "+renditionName+" -- " : "") + message); + } + /** * Called after working out what transformers are available and any * resulting transform has been called. @@ -1369,7 +1379,7 @@ public class TransformerDebug implements ApplicationContextAware boolean componentTransformer = isComponentTransformer(transformer); - StringBuilder sb = new StringBuilder(name); + StringBuilder sb = new StringBuilder("Legacy:").append(name); if (componentTransformer || type.length() > 0) { sb.append("<<"); @@ -1671,7 +1681,6 @@ public class TransformerDebug implements ApplicationContextAware ContentReader reader = contentService.getReader(sourceNodeRef, ContentModel.PROP_CONTENT); SynchronousTransformClient synchronousTransformClient = getSynchronousTransformClient(); Map actualOptions = Collections.emptyMap(); - synchronousTransformClient.isSupported(sourceNodeRef, targetMimetype, actualOptions, null, nodeService); synchronousTransformClient.transform(reader, writer, actualOptions, null, sourceNodeRef); } catch (Exception e) diff --git a/src/main/java/org/alfresco/repo/jscript/ScriptNode.java b/src/main/java/org/alfresco/repo/jscript/ScriptNode.java index 35a1b675c2..4691511f32 100644 --- a/src/main/java/org/alfresco/repo/jscript/ScriptNode.java +++ b/src/main/java/org/alfresco/repo/jscript/ScriptNode.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + * 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 @@ -66,6 +66,7 @@ import org.alfresco.repo.node.getchildren.GetChildrenCannedQuery; import org.alfresco.repo.rendition2.RenditionDefinition2; import org.alfresco.repo.rendition2.RenditionDefinitionRegistry2; import org.alfresco.repo.rendition2.RenditionService2; +import org.alfresco.repo.rendition2.SynchronousTransformClient; import org.alfresco.repo.search.QueryParameterDefImpl; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; @@ -92,6 +93,7 @@ import org.alfresco.service.cmr.model.FileNotFoundException; import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; @@ -100,7 +102,6 @@ import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.Path; import org.alfresco.service.cmr.repository.TemplateImageResolver; -import org.alfresco.service.cmr.repository.TransformationOptions; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.search.QueryParameterDefinition; import org.alfresco.service.cmr.security.AccessPermission; @@ -208,6 +209,7 @@ public class ScriptNode implements Scopeable, NamespacePrefixResolverProvider private FileFolderService fileFolderService = null; private RenditionService2 renditionService2; private RenditionDefinitionRegistry2 renditionDefinitionRegistry2; + private SynchronousTransformClient synchronousTransformClient; private RetryingTransactionHelper retryingTransactionHelper = null; private Boolean isDocument = null; private Boolean isContainer = null; @@ -279,6 +281,7 @@ public class ScriptNode implements Scopeable, NamespacePrefixResolverProvider this.scope = scope; renditionService2 = services.getRenditionService2(); renditionDefinitionRegistry2 = renditionService2.getRenditionDefinitionRegistry2(); + synchronousTransformClient = services.getSynchronousTransformClient(); } @Override @@ -2742,18 +2745,31 @@ public class ScriptNode implements Scopeable, NamespacePrefixResolverProvider // the delegate definition for transforming a document Transformer transformer = new AbstractTransformer() { - protected void doTransform(ContentService contentService, - ContentReader reader, ContentWriter writer) + protected void doTransform(SynchronousTransformClient synchronousTransformClient, ContentReader reader, ContentWriter writer) { - TransformationOptions options = new TransformationOptions(); - options.setSourceNodeRef(sourceNodeRef); - contentService.transform(reader, writer, options); + transformNodeRef(synchronousTransformClient, reader, writer, Collections.emptyMap(), sourceNodeRef); } }; return transformNode(transformer, mimetype, destination); } - + + private void transformNodeRef(SynchronousTransformClient synchronousTransformClient, + ContentReader reader, ContentWriter writer, + Map actualOptions, NodeRef sourceNodeRef) + { + try + { + synchronousTransformClient.transform(reader, writer, actualOptions, null, sourceNodeRef); + } + catch (Exception e) + { + throw new ContentIOException("Content conversion failed: \n" + + " reader: " + reader + "\n" + + " writer: " + writer + "\n", e); + } + } + /** * Generic method to transform Node content from one mimetype to another. * @@ -2791,7 +2807,7 @@ public class ScriptNode implements Scopeable, NamespacePrefixResolverProvider writer.setEncoding(reader.getEncoding()); // original encoding // Try and transform the content using the supplied delegate - transformedNode = transformer.transform(contentService, copyNodeRef, reader, writer); + transformedNode = transformer.transform(synchronousTransformClient, copyNodeRef, reader, writer); } return transformedNode; @@ -2864,17 +2880,16 @@ public class ScriptNode implements Scopeable, NamespacePrefixResolverProvider // the delegate definition for transforming an image Transformer transformer = new AbstractTransformer() { - protected void doTransform(ContentService contentService, - ContentReader reader, ContentWriter writer) + protected void doTransform(SynchronousTransformClient synchronousTransformClient, ContentReader reader, ContentWriter writer) { - ImageTransformationOptions imageOptions = new ImageTransformationOptions(); - imageOptions.setSourceNodeRef(sourceNodeRef); - - if (options != null) + Map actualOptions = Collections.emptyMap(); + if (options != null || !options.trim().isEmpty()) { - imageOptions.setCommandOptions(options); + // TODO it might be possible to extract some of the 'known ones' into actualOptions. + throw new IllegalArgumentException("ImageMagick commandOptions '"+options+ + "' may no longer be passed blindly to the transformer for security reasons."); } - contentService.getImageTransformer().transform(reader, writer, imageOptions); + transformNodeRef(synchronousTransformClient, reader, writer, actualOptions, sourceNodeRef); } }; @@ -4155,27 +4170,27 @@ public class ScriptNode implements Scopeable, NamespacePrefixResolverProvider /** * Transform the reader to the specified writer * - * @param contentService ContentService + * @param synchronousTransformClient * @param noderef NodeRef of the destination for the transform * @param reader Source reader * @param writer Destination writer - * + * * @return Node representing the transformed entity */ - ScriptNode transform(ContentService contentService, NodeRef noderef, + ScriptNode transform(SynchronousTransformClient synchronousTransformClient, NodeRef noderef, ContentReader reader, ContentWriter writer); } private abstract class AbstractTransformer implements Transformer { - public ScriptNode transform(ContentService contentService, NodeRef nodeRef, + public ScriptNode transform(SynchronousTransformClient synchronousTransformClient, NodeRef nodeRef, ContentReader reader, ContentWriter writer) { ScriptNode transformedNode = null; try { - doTransform(contentService, reader, writer); + doTransform(synchronousTransformClient, reader, writer); transformedNode = newInstance(nodeRef, services, scope); } catch (NoTransformerException e) @@ -4205,7 +4220,7 @@ public class ScriptNode implements Scopeable, NamespacePrefixResolverProvider return transformedNode; } - protected abstract void doTransform(ContentService contentService, + protected abstract void doTransform(SynchronousTransformClient synchronousTransformClient, ContentReader reader, ContentWriter writer); }; diff --git a/src/main/java/org/alfresco/repo/rendition/executer/AbstractTransformationRenderingEngine.java b/src/main/java/org/alfresco/repo/rendition/executer/AbstractTransformationRenderingEngine.java index 02c1325826..75c6a85407 100644 --- a/src/main/java/org/alfresco/repo/rendition/executer/AbstractTransformationRenderingEngine.java +++ b/src/main/java/org/alfresco/repo/rendition/executer/AbstractTransformationRenderingEngine.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + * 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 @@ -29,6 +29,7 @@ package org.alfresco.repo.rendition.executer; import java.io.Serializable; import java.util.Collection; import java.util.Date; +import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -36,12 +37,12 @@ import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; import org.alfresco.repo.action.ParameterDefinitionImpl; -import org.alfresco.repo.content.transform.ContentTransformer; import org.alfresco.repo.content.transform.TransformerConfig; -import org.alfresco.repo.content.transform.TransformerDebug; import org.alfresco.repo.content.transform.UnsupportedTransformationException; import org.alfresco.repo.rendition2.RenditionService2Impl; +import org.alfresco.repo.rendition2.SynchronousTransformClient; +import org.alfresco.repo.rendition2.TransformationOptionsConverter; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.service.cmr.action.ActionServiceException; import org.alfresco.service.cmr.action.ActionTrackingService; @@ -54,6 +55,7 @@ import org.alfresco.service.cmr.rendition.RenditionServiceException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NoTransformerException; +import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.TransformationOptionLimits; import org.alfresco.service.cmr.repository.TransformationOptions; import org.alfresco.service.cmr.repository.TransformationSourceOptions; @@ -140,7 +142,10 @@ public abstract class AbstractTransformationRenderingEngine extends AbstractRend * transforms. */ private ExecutorService executorService; - + + private SynchronousTransformClient synchronousTransformClient; + private TransformationOptionsConverter converter; + /** * Gets the ExecutorService to be used for cancel-aware * transforms. @@ -155,7 +160,17 @@ public abstract class AbstractTransformationRenderingEngine extends AbstractRend { return executorService; } - + + public void setSynchronousTransformClient(SynchronousTransformClient synchronousTransformClient) + { + this.synchronousTransformClient = synchronousTransformClient; + } + + public void setConverter(TransformationOptionsConverter converter) + { + this.converter = converter; + } + public void init() { super.init(); @@ -174,37 +189,22 @@ public abstract class AbstractTransformationRenderingEngine extends AbstractRend { ContentReader contentReader = context.makeContentReader(); // There will have been an exception if there is no content data so contentReader is not null. - String sourceUrl = contentReader.getContentUrl(); + String contentUrl = contentReader.getContentUrl(); String sourceMimeType = contentReader.getMimetype(); String targetMimeType = getTargetMimeType(context); // The child NodeRef gets created here - TransformationOptions options = getTransformOptions(context); + TransformationOptions transformationOptions = getTransformOptions(context); - // Log the following getTransform() as trace so we can see the wood for the trees - ContentTransformer transformer; - boolean orig = TransformerDebug.setDebugOutput(false); - try - { - transformer = this.contentService.getTransformer(sourceUrl, sourceMimeType, contentReader.getSize(), targetMimeType, options); - } - finally - { - TransformerDebug.setDebugOutput(orig); - } - - if (null == transformer) - { - // There's no transformer available for the requested rendition! - throw new RenditionServiceException(String.format(TRANSFORMER_NOT_EXISTS_MESSAGE_PATTERN, sourceMimeType, - targetMimeType)); - } - - if (!transformer.isTransformable(sourceMimeType, contentReader.getSize(), targetMimeType, options)) + long sourceSizeInBytes = contentReader.getSize(); + Map options = converter.getOptions(transformationOptions); + NodeRef sourceNodeRef = transformationOptions.getSourceNodeRef(); + if (!synchronousTransformClient.isSupported(sourceMimeType, sourceSizeInBytes, contentUrl, targetMimeType, + options, null, sourceNodeRef)) { throw new RenditionServiceException(String.format(NOT_TRANSFORMABLE_MESSAGE_PATTERN, sourceMimeType, targetMimeType)); } - + long startTime = new Date().getTime(); boolean actionCancelled = false; boolean actionCompleted = false; @@ -226,7 +226,7 @@ public abstract class AbstractTransformationRenderingEngine extends AbstractRend // Call the transform in a different thread so we can move on if cancelled FutureTask transformTask = new FutureTask( - new TransformationCallable(contentReader, targetMimeType, options, context, + new TransformationCallable(contentReader, targetMimeType, transformationOptions, context, AuthenticationUtil.getFullyAuthenticatedUser())); getExecutorService().execute(transformTask); @@ -242,8 +242,8 @@ public abstract class AbstractTransformationRenderingEngine extends AbstractRend break; } // Check timeout in case transformer doesn't obey it - if (options.getTimeoutMs() > 0 && - new Date().getTime() - startTime > (options.getTimeoutMs() + CANCELLED_ACTION_POLLING_INTERVAL)) + if (transformationOptions.getTimeoutMs() > 0 && + new Date().getTime() - startTime > (transformationOptions.getTimeoutMs() + CANCELLED_ACTION_POLLING_INTERVAL)) { // We hit a timeout, let the transform thread continue but results will be ignored if (logger.isDebugEnabled()) @@ -418,16 +418,16 @@ public abstract class AbstractTransformationRenderingEngine extends AbstractRend { private ContentReader contentReader; private String targetMimeType; - private TransformationOptions options; + private Map options; private RenderingContext context; private String initiatingUsername; - + public TransformationCallable(ContentReader contentReader, String targetMimeType, - TransformationOptions options, RenderingContext context, String initiatingUsername) + TransformationOptions transformationOptions, RenderingContext context, String initiatingUsername) { this.contentReader = contentReader; this.targetMimeType = targetMimeType; - this.options = options; + this.options = converter.getOptions(transformationOptions); this.context = context; this.initiatingUsername = initiatingUsername; } @@ -446,10 +446,13 @@ public abstract class AbstractTransformationRenderingEngine extends AbstractRend { // ALF-15715: Use temporary write to avoid operating on the real node for fear of row locking while long transforms are in progress ContentWriter tempContentWriter = contentService.getTempWriter(); + String renditionName = context.getDefinition().getRenditionName().getLocalName(); + NodeRef sourceNode = context.getSourceNode(); tempContentWriter.setMimetype(targetMimeType); try { - contentService.transform(contentReader, tempContentWriter, options); + synchronousTransformClient.transform(contentReader, tempContentWriter, options, + renditionName, sourceNode); return tempContentWriter; } catch (NoTransformerException|UnsupportedTransformationException ntx) diff --git a/src/main/java/org/alfresco/repo/rendition2/ContentTransformServiceImpl.java b/src/main/java/org/alfresco/repo/rendition2/ContentTransformServiceImpl.java new file mode 100644 index 0000000000..557934b71a --- /dev/null +++ b/src/main/java/org/alfresco/repo/rendition2/ContentTransformServiceImpl.java @@ -0,0 +1,362 @@ +/* + * #%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.repo.rendition2; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.content.filestore.FileContentWriter; +import org.alfresco.repo.content.transform.ContentTransformer; +import org.alfresco.repo.content.transform.ContentTransformerRegistry; +import org.alfresco.repo.content.transform.TransformerDebug; +import org.alfresco.repo.content.transform.UnimportantTransformException; +import org.alfresco.repo.content.transform.UnsupportedTransformationException; +import org.alfresco.service.cmr.repository.ContentIOException; +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.NoTransformerException; +import org.alfresco.service.cmr.repository.TransformationOptions; +import org.alfresco.util.PropertyCheck; +import org.alfresco.util.TempFileProvider; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Contains deprecated code originally from {@link org.alfresco.repo.content.ContentServiceImpl} that is used to perform + * Legacy transforms. + * + * @author adavis + */ +@Deprecated +public abstract class ContentTransformServiceImpl implements InitializingBean +{ + protected static Log logger = LogFactory.getLog(LegacyTransformClient.class); + + private MimetypeService mimetypeService; + private ContentTransformerRegistry transformerRegistry; + private TransformerDebug transformerDebug; + + private boolean transformerFailover = true; + + public void setMimetypeService(MimetypeService mimetypeService) + { + this.mimetypeService = mimetypeService; + } + + public void setTransformerRegistry(ContentTransformerRegistry transformerRegistry) + { + this.transformerRegistry = transformerRegistry; + } + + public void setTransformerDebug(TransformerDebug transformerDebug) + { + this.transformerDebug = transformerDebug; + } + + public void setTransformerFailover(boolean transformerFailover) + { + this.transformerFailover = transformerFailover; + } + + @Override + public void afterPropertiesSet() throws Exception + { + PropertyCheck.mandatory(this, "mimetypeService", mimetypeService); + PropertyCheck.mandatory(this, "transformerRegistry", transformerRegistry); + PropertyCheck.mandatory(this, "transformerDebug", transformerDebug); + } + + @Deprecated + public void transform(ContentReader reader, ContentWriter writer, TransformationOptions options) + throws NoTransformerException, ContentIOException + { + // check that source and target mimetypes are available + if (reader == null) + { + throw new AlfrescoRuntimeException("The content reader must be set"); + } + String sourceMimetype = reader.getMimetype(); + if (sourceMimetype == null) + { + throw new AlfrescoRuntimeException("The content reader mimetype must be set: " + reader); + } + String targetMimetype = writer.getMimetype(); + if (targetMimetype == null) + { + throw new AlfrescoRuntimeException("The content writer mimetype must be set: " + writer); + } + + long sourceSize = reader.getSize(); + try + { + // look for a transformer + transformerDebug.pushAvailable(reader.getContentUrl(), sourceMimetype, targetMimetype, options); + List transformers = getActiveTransformers(sourceMimetype, sourceSize, targetMimetype, options); + transformerDebug.availableTransformers(transformers, sourceSize, options, "ContentService.transform(...)"); + + int count = transformers.size(); + if (count == 0) + { + throw new NoTransformerException(sourceMimetype, targetMimetype); + } + + if (count == 1 || !transformerFailover) + { + ContentTransformer transformer = transformers.size() == 0 ? null : transformers.get(0); + transformer.transform(reader, writer, options); + } + else + { + failoverTransformers(reader, writer, options, targetMimetype, transformers); + } + } + finally + { + if (transformerDebug.isEnabled()) + { + transformerDebug.popAvailable(); + debugTransformations(sourceMimetype, targetMimetype, sourceSize, options); + } + } + } + + private void failoverTransformers(ContentReader reader, ContentWriter writer, + TransformationOptions options, String targetMimetype, + List transformers) + { + List exceptions = null; + boolean done = false; + try + { + // Try the best transformer and then the next if it fails + // and so on down the list + char c = 'a'; + String outputFileExt = mimetypeService.getExtension(targetMimetype); + for (ContentTransformer transformer : transformers) + { + ContentWriter currentWriter = writer; + File tempFile = null; + try + { + // We can't know in advance which of the + // available transformer will work - if any. + // We can't write into the ContentWriter stream. + // So make a temporary file writer with the + // current transformer name. + tempFile = TempFileProvider.createTempFile( + "FailoverTransformer_intermediate_" + + transformer.getClass().getSimpleName() + "_", "." + + outputFileExt); + currentWriter = new FileContentWriter(tempFile); + currentWriter.setMimetype(targetMimetype); + currentWriter.setEncoding(writer.getEncoding()); + + if (c != 'a' && transformerDebug.isEnabled()) + { + transformerDebug.debug(""); + transformerDebug.debug("Try " + c + ")"); + } + c++; + + transformer.transform(reader, currentWriter, options); + + if (tempFile != null) + { + writer.putContent(tempFile); + } + + // No need to close input or output streams + // (according + // to comment in FailoverContentTransformer) + done = true; + return; + } + catch (Exception e) + { + if (exceptions == null) + { + exceptions = new ArrayList(); + } + if (!(e instanceof AlfrescoRuntimeException)) + { + e = new AlfrescoRuntimeException(e.getMessage(), e); + } + exceptions.add((AlfrescoRuntimeException)e); + + // Set a new reader to refresh the input stream. + reader = reader.getReader(); + } + } + // Throw the exception from the first transformer. The + // others are consumed. + if (exceptions != null) + { + throw exceptions.get(0); + } + } + finally + { + // Log exceptions that we have consumed. We may have thrown the first one if + // none of the transformers worked. + if (exceptions != null) + { + boolean first = true; + for (Exception e : exceptions) + { + Throwable rootCause = (e instanceof AlfrescoRuntimeException) ? ((AlfrescoRuntimeException)e).getRootCause() : null; + String message = (rootCause == null ? null : rootCause.getMessage()); + if (done) + { + message = "Transformer succeeded after previous transformer failed"+ (message == null ? "" : ": "+message); + if (rootCause instanceof UnsupportedTransformationException || + rootCause instanceof UnimportantTransformException) + { + logger.debug(message); + } + else + { + logger.warn(message, e); + } + } + else if (!first) // The first exception is logged later + { + message = "Transformer exception"+ (message == null ? "" : ": "+message); + if (rootCause instanceof UnsupportedTransformationException || + rootCause instanceof UnimportantTransformException) + { + logger.debug(message); + } + else + { + logger.error(message, e); + } + first = false; + } + } + } + } + } + + @Deprecated + public ContentTransformer getTransformer(String sourceUrl, String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options) + { + List transformers = null; + try + { + transformerDebug.pushAvailable(sourceUrl, sourceMimetype, targetMimetype, options); + List activeTransformers = getActiveTransformers(sourceMimetype, sourceSize, targetMimetype, options); + transformerDebug.availableTransformers(activeTransformers, sourceSize, options, "ContentService.getTransformer(...)"); + transformers = activeTransformers.isEmpty() ? null : activeTransformers; + } + finally + { + transformerDebug.popAvailable(); + } + return (transformers == null) ? null : transformers.get(0); + } + + private void debugTransformations(String sourceMimetype, String targetMimetype, + long sourceSize, TransformationOptions transformOptions) + { + // check the file name + if (MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(sourceMimetype) && + MimetypeMap.MIMETYPE_IMAGE_PNG.equals(targetMimetype)) + { + String fileName = transformerDebug.getFileName(transformOptions, true, 0); + if (fileName != null && fileName.contains("debugTransformers.txt")) + { + transformerDebug.transformationsByTransformer(null, false, false, null); + transformerDebug.transformationsByExtension(null, null, false, false, false, null); + } + } + } + + @Deprecated + public List getTransformers(String sourceUrl, String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options) + { + try + { + // look for a transformer + transformerDebug.pushAvailable(sourceUrl, sourceMimetype, targetMimetype, options); + List transformers = getActiveTransformers(sourceMimetype, sourceSize, targetMimetype, options); + transformerDebug.availableTransformers(transformers, sourceSize, options, "ContentService.getTransformer(...)"); + return transformers.isEmpty() ? null : transformers; + } + finally + { + transformerDebug.popAvailable(); + } + } + + @Deprecated + public long getMaxSourceSizeBytes(String sourceMimetype, String targetMimetype, TransformationOptions options) + { + try + { + long maxSourceSize = 0; + transformerDebug.pushAvailable(null, sourceMimetype, targetMimetype, options); + List transformers = getActiveTransformers(sourceMimetype, -1, targetMimetype, options); + for (ContentTransformer transformer: transformers) + { + long maxSourceSizeKBytes = transformer.getMaxSourceSizeKBytes(sourceMimetype, targetMimetype, options); + if (maxSourceSize >= 0) + { + if (maxSourceSizeKBytes < 0) + { + maxSourceSize = -1; + } + else if (maxSourceSizeKBytes > 0 && maxSourceSize < maxSourceSizeKBytes) + { + maxSourceSize = maxSourceSizeKBytes; + } + } + // if maxSourceSizeKBytes == 0 this implies the transformation is disabled + } + if (transformerDebug.isEnabled()) + { + transformerDebug.availableTransformers(transformers, -1, options, + "ContentService.getMaxSourceSizeBytes() = "+transformerDebug.fileSize(maxSourceSize*1024)); + } + return (maxSourceSize > 0) ? maxSourceSize * 1024 : maxSourceSize; + } + finally + { + transformerDebug.popAvailable(); + } + } + + @Deprecated + public List getActiveTransformers(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options) + { + return transformerRegistry.getActiveTransformers(sourceMimetype, sourceSize, targetMimetype, options); + } +} diff --git a/src/main/java/org/alfresco/repo/rendition2/LegacySynchronousTransformClient.java b/src/main/java/org/alfresco/repo/rendition2/LegacySynchronousTransformClient.java index 6847a9deb2..c8a166dfab 100644 --- a/src/main/java/org/alfresco/repo/rendition2/LegacySynchronousTransformClient.java +++ b/src/main/java/org/alfresco/repo/rendition2/LegacySynchronousTransformClient.java @@ -27,14 +27,9 @@ package org.alfresco.repo.rendition2; import org.alfresco.repo.content.transform.ContentTransformer; import org.alfresco.service.cmr.repository.ContentReader; -import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.TransformationOptions; -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.util.Map; @@ -46,19 +41,11 @@ import java.util.Map; * @author adavis */ @Deprecated -public class LegacySynchronousTransformClient implements SynchronousTransformClient, InitializingBean +public class LegacySynchronousTransformClient extends ContentTransformServiceImpl implements SynchronousTransformClient { private static final String TRANSFORM = "Legacy synchronous transform "; - private static Log logger = LogFactory.getLog(LegacyTransformClient.class); - private ContentService contentService; private TransformationOptionsConverter converter; - private ThreadLocal transform = new ThreadLocal<>(); - - public void setContentService(ContentService contentService) - { - this.contentService = contentService; - } public void setConverter(TransformationOptionsConverter converter) { @@ -66,22 +53,15 @@ public class LegacySynchronousTransformClient implements SynchronousTransformCli } @Override - public void afterPropertiesSet() throws Exception - { - PropertyCheck.mandatory(this, "contentService", contentService); - PropertyCheck.mandatory(this, "converter", converter); - } - - @Override - public boolean isSupported(NodeRef sourceNodeRef, String sourceMimetype, long sourceSizeInBytes, String contentUrl, - String targetMimetype, Map actualOptions, String transformName) + public boolean isSupported(String sourceMimetype, long sourceSizeInBytes, String contentUrl, String targetMimetype, + Map actualOptions, String transformName, NodeRef sourceNodeRef) { String renditionName = TransformDefinition.convertToRenditionName(transformName); TransformationOptions transformationOptions = converter.getTransformationOptions(renditionName, actualOptions); transformationOptions.setSourceNodeRef(sourceNodeRef); - ContentTransformer legacyTransform = contentService.getTransformer(contentUrl, sourceMimetype, sourceSizeInBytes, targetMimetype, transformationOptions); - transform.set(legacyTransform); + ContentTransformer legacyTransform = getTransformer(contentUrl, sourceMimetype, + sourceSizeInBytes, targetMimetype, transformationOptions); if (logger.isDebugEnabled()) { @@ -93,18 +73,13 @@ public class LegacySynchronousTransformClient implements SynchronousTransformCli @Override public void transform(ContentReader reader, ContentWriter writer, Map actualOptions, - String transformName, NodeRef sourceNodeRef) throws Exception + String transformName, NodeRef sourceNodeRef) { String renditionName = TransformDefinition.convertToRenditionName(transformName); - TransformationOptions options = converter.getTransformationOptions(renditionName, actualOptions); - options.setSourceNodeRef(sourceNodeRef); - ContentTransformer legacyTransform = transform.get(); try { - if (legacyTransform == null) - { - throw new IllegalStateException("isSupported was not called prior to transform."); - } + TransformationOptions options = converter.getTransformationOptions(renditionName, actualOptions); + options.setSourceNodeRef(sourceNodeRef); if (null == reader || !reader.exists()) { @@ -116,11 +91,11 @@ public class LegacySynchronousTransformClient implements SynchronousTransformCli logger.debug(TRANSFORM + "requested " + renditionName); } - // Note: we don't call legacyTransform.transform(reader, writer, options) as the Legacy - // transforms (unlike Local and Transform Service) automatically fail over to the next - // highest priority. This was not done for the newer transforms, as a fail over can always be - // defined and that makes it simpler to understand what is going on. - contentService.transform(reader, writer, options); + // We don't obtain the Legacy transformer and then call its transform method as they unlike Local and + // Transform Service transforms automatically fail over to the next highest priority. This was not done + // for the newer transforms, as a fail over can always be defined and that makes it simpler to understand + // what is going on. + transform(reader, writer, options); if (logger.isDebugEnabled()) { diff --git a/src/main/java/org/alfresco/repo/rendition2/LegacyTransformClient.java b/src/main/java/org/alfresco/repo/rendition2/LegacyTransformClient.java index 28c9290423..541819403f 100644 --- a/src/main/java/org/alfresco/repo/rendition2/LegacyTransformClient.java +++ b/src/main/java/org/alfresco/repo/rendition2/LegacyTransformClient.java @@ -62,6 +62,7 @@ public class LegacyTransformClient implements TransformClient, InitializingBean private ContentService contentService; private RenditionService2Impl renditionService2; private TransformationOptionsConverter converter; + private LegacySynchronousTransformClient legacySynchronousTransformClient; private ExecutorService executorService; private ThreadLocal transform = new ThreadLocal<>(); @@ -86,6 +87,11 @@ public class LegacyTransformClient implements TransformClient, InitializingBean this.converter = converter; } + public void setLegacySynchronousTransformClient(LegacySynchronousTransformClient legacySynchronousTransformClient) + { + this.legacySynchronousTransformClient = legacySynchronousTransformClient; + } + public void setExecutorService(ExecutorService executorService) { this.executorService = executorService; @@ -98,6 +104,7 @@ public class LegacyTransformClient implements TransformClient, InitializingBean PropertyCheck.mandatory(this, "contentService", contentService); PropertyCheck.mandatory(this, "renditionService2", renditionService2); PropertyCheck.mandatory(this, "converter", converter); + PropertyCheck.mandatory(this, "legacySynchronousTransformClient", legacySynchronousTransformClient); if (executorService == null) { executorService = Executors.newCachedThreadPool(); @@ -114,7 +121,7 @@ public class LegacyTransformClient implements TransformClient, InitializingBean TransformationOptions transformationOptions = converter.getTransformationOptions(renditionName, options); transformationOptions.setSourceNodeRef(sourceNodeRef); - ContentTransformer legacyTransform = contentService.getTransformer(contentUrl, sourceMimetype, sourceSizeInBytes, targetMimetype, transformationOptions); + ContentTransformer legacyTransform = legacySynchronousTransformClient.getTransformer(contentUrl, sourceMimetype, sourceSizeInBytes, targetMimetype, transformationOptions); transform.set(legacyTransform); String message = TRANSFORM + renditionName + " from " + sourceMimetype + @@ -145,7 +152,7 @@ public class LegacyTransformClient implements TransformClient, InitializingBean { if (legacyTransform == null) { - throw new IllegalStateException("isSupported was not called prior to transform."); + throw new IllegalStateException("isSupported was not called prior to an asynchronous transform."); } ContentReader reader = contentService.getReader(sourceNodeRef, ContentModel.PROP_CONTENT); @@ -165,7 +172,7 @@ public class LegacyTransformClient implements TransformClient, InitializingBean // defined and that makes it simpler to understand what is going on. ContentWriter writer = contentService.getTempWriter(); writer.setMimetype(targetMimetype); - contentService.transform(reader, writer, options); + legacySynchronousTransformClient.transform(reader, writer, options); InputStream inputStream = writer.getReader().getContentInputStream(); if (logger.isDebugEnabled()) diff --git a/src/main/java/org/alfresco/repo/rendition2/LegacyTransformServiceRegistry.java b/src/main/java/org/alfresco/repo/rendition2/LegacyTransformServiceRegistry.java index 77c1bd8e39..cdbd392f26 100644 --- a/src/main/java/org/alfresco/repo/rendition2/LegacyTransformServiceRegistry.java +++ b/src/main/java/org/alfresco/repo/rendition2/LegacyTransformServiceRegistry.java @@ -43,15 +43,15 @@ import java.util.Map; @Deprecated public class LegacyTransformServiceRegistry implements InitializingBean, TransformServiceRegistry { - private ContentService contentService; + private LegacySynchronousTransformClient legacySynchronousTransformClient; private TransformationOptionsConverter converter; private boolean enabled = true; private boolean firstTime = true; private TransformerDebug transformerDebug; - public void setContentService(ContentService contentService) + public void setLegacySynchronousTransformClient(LegacySynchronousTransformClient legacySynchronousTransformClient) { - this.contentService = contentService; + this.legacySynchronousTransformClient = legacySynchronousTransformClient; } public void setConverter(TransformationOptionsConverter converter) @@ -78,7 +78,7 @@ public class LegacyTransformServiceRegistry implements InitializingBean, Transfo @Override public void afterPropertiesSet() { - PropertyCheck.mandatory(this, "contentService", contentService); + PropertyCheck.mandatory(this, "legacySynchronousTransformClient", legacySynchronousTransformClient); PropertyCheck.mandatory(this, "converter", converter); PropertyCheck.mandatory(this, "transformerDebug", transformerDebug); } @@ -99,7 +99,7 @@ public class LegacyTransformServiceRegistry implements InitializingBean, Transfo try { TransformationOptions transformationOptions = converter.getTransformationOptions(renditionName, options); - maxSize = contentService.getMaxSourceSizeBytes(sourceMimetype, targetMimetype, transformationOptions); + maxSize = legacySynchronousTransformClient.getMaxSourceSizeBytes(sourceMimetype, targetMimetype, transformationOptions); } catch (IllegalArgumentException ignore) { diff --git a/src/main/java/org/alfresco/repo/rendition2/LocalSynchronousTransformClient.java b/src/main/java/org/alfresco/repo/rendition2/LocalSynchronousTransformClient.java index 542f3508fb..3d2fdc95a5 100644 --- a/src/main/java/org/alfresco/repo/rendition2/LocalSynchronousTransformClient.java +++ b/src/main/java/org/alfresco/repo/rendition2/LocalSynchronousTransformClient.java @@ -27,6 +27,8 @@ package org.alfresco.repo.rendition2; import org.alfresco.repo.content.transform.LocalTransform; import org.alfresco.repo.content.transform.LocalTransformServiceRegistry; +import org.alfresco.repo.content.transform.TransformerDebug; +import org.alfresco.repo.content.transform.UnsupportedTransformationException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; @@ -38,20 +40,18 @@ import org.springframework.beans.factory.InitializingBean; import java.util.Map; /** - * Request synchronous transforms. Used in refactoring deprecated code, which called Legacy transforms, so that it will - * first try a Local transform, falling back to Legacy if not available. Transforms take place using transforms - * available on the local machine (based on {@link LocalTransform}). + * Request synchronous transforms. + * + * Transforms take place using transforms available on the local machine (based on {@link LocalTransform}). * * @author adavis */ -@Deprecated public class LocalSynchronousTransformClient implements SynchronousTransformClient, InitializingBean { private static final String TRANSFORM = "Local synchronous transform "; private static Log logger = LogFactory.getLog(LocalTransformClient.class); private LocalTransformServiceRegistry localTransformServiceRegistry; - private ThreadLocal transform = new ThreadLocal<>(); public void setLocalTransformServiceRegistry(LocalTransformServiceRegistry localTransformServiceRegistry) { @@ -65,46 +65,66 @@ public class LocalSynchronousTransformClient implements SynchronousTransformClie } @Override - public boolean isSupported(NodeRef sourceNodeRef, String sourceMimetype, long sourceSizeInBytes, String contentUrl, - String targetMimetype, Map actualOptions, String transformName) + public boolean isSupported(String sourceMimetype, long sourceSizeInBytes, String contentUrl, String targetMimetype, + Map actualOptions, String transformName, NodeRef sourceNodeRef) { String renditionName = TransformDefinition.convertToRenditionName(transformName); - LocalTransform localTransform = localTransformServiceRegistry.getLocalTransform(sourceMimetype, + LocalTransform transform = localTransformServiceRegistry.getLocalTransform(sourceMimetype, sourceSizeInBytes, targetMimetype, actualOptions, renditionName); - transform.set(localTransform); if (logger.isDebugEnabled()) { logger.debug(TRANSFORM + renditionName + " from " + sourceMimetype + - (localTransform == null ? " is unsupported" : " is supported")); + (transform == null ? " is unsupported" : " is supported")); } - return localTransform != null; + return transform != null; } @Override public void transform(ContentReader reader, ContentWriter writer, Map actualOptions, - String transformName, NodeRef sourceNodeRef) throws Exception + String transformName, NodeRef sourceNodeRef) { String renditionName = TransformDefinition.convertToRenditionName(transformName); - LocalTransform localTransform = transform.get(); try { - if (localTransform == null) + if (reader == null) { - throw new IllegalStateException("isSupported was not called prior to transform."); + throw new IllegalArgumentException("The content reader must be set"); } - - if (null == reader || !reader.exists()) + if (!reader.exists()) { throw new IllegalArgumentException("sourceNodeRef "+sourceNodeRef+" has no content."); } + String sourceMimetype = reader.getMimetype(); + long sourceSizeInBytes = reader.getSize(); + if (sourceMimetype == null) + { + throw new IllegalArgumentException("The content reader mimetype must be set"); + } + + String targetMimetype = writer.getMimetype(); + if (targetMimetype == null) + { + throw new IllegalArgumentException("The content writer mimetype must be set"); + } + + LocalTransform transform = localTransformServiceRegistry.getLocalTransform(sourceMimetype, + sourceSizeInBytes, targetMimetype, actualOptions, renditionName); + + if (transform == null) + { + throw new UnsupportedTransformationException("Transformation of " + sourceMimetype + + (sourceSizeInBytes > 0 ? " size "+sourceSizeInBytes : "")+ " to " + targetMimetype + + " unsupported"); + } + if (logger.isDebugEnabled()) { logger.debug(TRANSFORM + " requested " + renditionName); } - localTransform.transform(reader, writer, actualOptions, renditionName, sourceNodeRef); + transform.transform(reader, writer, actualOptions, renditionName, sourceNodeRef); if (logger.isDebugEnabled()) { diff --git a/src/main/java/org/alfresco/repo/rendition2/LocalTransformClient.java b/src/main/java/org/alfresco/repo/rendition2/LocalTransformClient.java index 4964a7035e..fc7931d06d 100644 --- a/src/main/java/org/alfresco/repo/rendition2/LocalTransformClient.java +++ b/src/main/java/org/alfresco/repo/rendition2/LocalTransformClient.java @@ -142,7 +142,7 @@ public class LocalTransformClient implements TransformClient, InitializingBean { if (localTransform == null) { - throw new IllegalStateException("isSupported was not called prior to transform."); + throw new IllegalStateException("isSupported was not called prior to an asynchronous transform."); } ContentReader reader = contentService.getReader(sourceNodeRef, ContentModel.PROP_CONTENT); diff --git a/src/main/java/org/alfresco/repo/rendition2/RenditionService2Impl.java b/src/main/java/org/alfresco/repo/rendition2/RenditionService2Impl.java index 75f122882b..57d35f9daa 100644 --- a/src/main/java/org/alfresco/repo/rendition2/RenditionService2Impl.java +++ b/src/main/java/org/alfresco/repo/rendition2/RenditionService2Impl.java @@ -86,7 +86,7 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea private static Log logger = LogFactory.getLog(RenditionService2Impl.class); // As Async transforms and renditions are so similar, this class provides a way to provide the code that is different. - private abstract static class renderOrTransformCallBack + private abstract static class RenderOrTransformCallBack { abstract String getName(); @@ -208,7 +208,7 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea @Override public void transform(NodeRef sourceNodeRef, TransformDefinition transformDefinition) { - requestAsyncTransformOrRendition(sourceNodeRef, new renderOrTransformCallBack() + requestAsyncTransformOrRendition(sourceNodeRef, new RenderOrTransformCallBack() { @Override public String getName() @@ -228,7 +228,7 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea @Override public void render(NodeRef sourceNodeRef, String renditionName) { - requestAsyncTransformOrRendition(sourceNodeRef, new renderOrTransformCallBack() + requestAsyncTransformOrRendition(sourceNodeRef, new RenderOrTransformCallBack() { @Override public String getName() @@ -278,7 +278,7 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea }); } - private void requestAsyncTransformOrRendition(NodeRef sourceNodeRef, renderOrTransformCallBack renderOrTransform) + private void requestAsyncTransformOrRendition(NodeRef sourceNodeRef, RenderOrTransformCallBack renderOrTransform) { try { diff --git a/src/main/java/org/alfresco/repo/rendition2/SwitchingSynchronousTransformClient.java b/src/main/java/org/alfresco/repo/rendition2/SwitchingSynchronousTransformClient.java index 299e1911dd..e15ba0c33b 100644 --- a/src/main/java/org/alfresco/repo/rendition2/SwitchingSynchronousTransformClient.java +++ b/src/main/java/org/alfresco/repo/rendition2/SwitchingSynchronousTransformClient.java @@ -25,9 +25,12 @@ */ package org.alfresco.repo.rendition2; +import org.alfresco.repo.content.transform.TransformerDebug; +import org.alfresco.repo.content.transform.UnsupportedTransformationException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.util.Pair; import java.util.Map; @@ -43,7 +46,8 @@ public class SwitchingSynchronousTransformClient implements SynchronousTransform { private final SynchronousTransformClient primary; private final SynchronousTransformClient secondary; - private ThreadLocal synchronousTransformClient = new ThreadLocal<>(); + + private TransformerDebug transformerDebug; public SwitchingSynchronousTransformClient(SynchronousTransformClient primary, SynchronousTransformClient secondary) { @@ -51,31 +55,47 @@ public class SwitchingSynchronousTransformClient implements SynchronousTransform this.secondary = secondary; } - @Override - public boolean isSupported(NodeRef sourceNodeRef, String sourceMimetype, long sourceSizeInBytes, String contentUrl, - String targetMimetype, Map actualOptions, String transformName) + public void setTransformerDebug(TransformerDebug transformerDebug) { - boolean supported = true; - if (primary.isSupported(sourceNodeRef, sourceMimetype, sourceSizeInBytes, contentUrl, - targetMimetype, actualOptions, transformName)) + this.transformerDebug = transformerDebug; + } + + @Override + public boolean isSupported(String sourceMimetype, long sourceSizeInBytes, String contentUrl, String targetMimetype, + Map actualOptions, String transformName, NodeRef sourceNodeRef) + { + boolean supported = + primary.isSupported(sourceMimetype, sourceSizeInBytes, contentUrl, targetMimetype, actualOptions, + transformName, sourceNodeRef) || + secondary.isSupported(sourceMimetype, sourceSizeInBytes, contentUrl, targetMimetype, actualOptions, + transformName, sourceNodeRef); + if (transformerDebug.isEnabled()) { - synchronousTransformClient.set(primary); - } - else if (secondary.isSupported(sourceNodeRef, sourceMimetype, sourceSizeInBytes, contentUrl, - targetMimetype, actualOptions, transformName)) - { - synchronousTransformClient.set(secondary); - } - else - { - supported = false; + String renditionName = TransformDefinition.convertToRenditionName(transformName); + transformerDebug.debug(sourceMimetype, targetMimetype, sourceNodeRef, sourceSizeInBytes, renditionName, + " is "+(supported ? "" : "not ")+"supported"); } return supported; } @Override - public void transform(ContentReader reader, ContentWriter writer, Map actualOptions, String transformName, NodeRef sourceNodeRef) throws Exception + public void transform(ContentReader reader, ContentWriter writer, Map actualOptions, + String transformName, NodeRef sourceNodeRef) { - synchronousTransformClient.get().transform(reader, writer, actualOptions, transformName, sourceNodeRef); + try + { + primary.transform(reader, writer, actualOptions, transformName, sourceNodeRef); + } + catch (UnsupportedTransformationException primaryException) + { + try + { + secondary.transform(reader, writer, actualOptions, transformName, sourceNodeRef); + } + catch (UnsupportedTransformationException secondaryException) + { + throw primaryException; + } + } } } diff --git a/src/main/java/org/alfresco/repo/rendition2/SwitchingTransformClient.java b/src/main/java/org/alfresco/repo/rendition2/SwitchingTransformClient.java index e0144acec0..73348c8752 100644 --- a/src/main/java/org/alfresco/repo/rendition2/SwitchingTransformClient.java +++ b/src/main/java/org/alfresco/repo/rendition2/SwitchingTransformClient.java @@ -49,13 +49,21 @@ public class SwitchingTransformClient implements TransformClient { try { - transformClient.set(primary); primary.checkSupported(sourceNodeRef, renditionDefinition, sourceMimetype, sourceSizeInBytes, contentUrl); + transformClient.set(primary); } catch (UnsupportedOperationException e) { - transformClient.set(secondary); - secondary.checkSupported(sourceNodeRef, renditionDefinition, sourceMimetype, sourceSizeInBytes, contentUrl); + try + { + secondary.checkSupported(sourceNodeRef, renditionDefinition, sourceMimetype, sourceSizeInBytes, contentUrl); + transformClient.set(secondary); + } + catch (UnsupportedOperationException e2) + { + transformClient.set(null); + throw e2; + } } } diff --git a/src/main/java/org/alfresco/repo/rendition2/SynchronousTransformClient.java b/src/main/java/org/alfresco/repo/rendition2/SynchronousTransformClient.java index 06113de327..c0952af2fc 100644 --- a/src/main/java/org/alfresco/repo/rendition2/SynchronousTransformClient.java +++ b/src/main/java/org/alfresco/repo/rendition2/SynchronousTransformClient.java @@ -26,29 +26,29 @@ package org.alfresco.repo.rendition2; import org.alfresco.model.ContentModel; +import org.alfresco.repo.content.transform.UnsupportedTransformationException; import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.TransformationOptions; import java.util.Map; /** - * Request synchronous transforms. Used in refactoring deprecated code, which called Legacy transforms, so that it will - * first try a Local transform, falling back to Legacy if not available. + * Request synchronous transforms. * * @author adavis */ -@Deprecated public interface SynchronousTransformClient { /** - * Works out if it is possible 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 - * Transformer objects registered with this class. + * Works out if it is possible to transform content of a given source mimetype and size into a target mimetype + * given a list of actual transform option names and values. Ideally, just call the transform method and catch the + * UnsupportedTransformationException to avoid extra work. * - * @param sourceNodeRef the NodeRef of the source content. Optional as it is only used in debug messages. * @param sourceMimetype the mimetype of the source content * @param sourceSizeInBytes the size in bytes of the source content. Ignored if negative. * @param contentUrl The url of the content. Optional as it is only used in debug messages. @@ -57,46 +57,14 @@ public interface SynchronousTransformClient * @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. + * @param sourceNodeRef (optional) NodeRef of the source content. Only used in debug messages. * @return {@code}true{@code} if it is supported. */ - @Deprecated - boolean isSupported(NodeRef sourceNodeRef, String sourceMimetype, long sourceSizeInBytes, String contentUrl, - String targetMimetype, Map actualOptions, String transformName); + boolean isSupported(String sourceMimetype, long sourceSizeInBytes, String contentUrl, String targetMimetype, + Map actualOptions, String transformName, NodeRef sourceNodeRef); /** - * Helper method to call {@link #isSupported(NodeRef, String, long, String, String, Map, String)}. Uses the - * {@code nodeService} and {@code sourceNodeRef} to work out the {@code sourceMimetype}, {@code sourceSizeInBytes} - * and {@code contentUrl}. - * @param sourceNodeRef the NodeRef 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. - * @param nodeService to access the sourceNodeRef content property. - * @return {@code}true{@code} if it is supported. - */ - @Deprecated - default boolean isSupported(NodeRef sourceNodeRef, String targetMimetype, - Map actualOptions, String transformName, NodeService nodeService) - { - boolean supported = false; - ContentData contentData = (ContentData) nodeService.getProperty(sourceNodeRef, ContentModel.PROP_CONTENT); - if (contentData != null && contentData.getContentUrl() != null) - { - String sourceMimetype = contentData.getMimetype(); - long sourceSizeInBytes = contentData.getSize(); - String contentUrl = contentData.getContentUrl(); - supported = isSupported(sourceNodeRef, sourceMimetype, sourceSizeInBytes, contentUrl, - targetMimetype, actualOptions, transformName); - } - return supported; - } - - /** - * Requests a synchronous transform. Not used for renditions. - * The call to this method MUST be proceeded by a successful call to - * {@link #isSupported(NodeRef, String, long, String, String, Map, String)} in the SAME Thread. + * Requests a synchronous transform. * @param reader of the source content * @param writer to the target node's content * @param actualOptions the actual name value pairs available that could be passed to the Transform Service. @@ -104,8 +72,13 @@ public interface SynchronousTransformClient * 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. * @param sourceNodeRef the source node + * @throws UnsupportedTransformationException if there is an unexpected failure to transform, normally in a + * pipeline, where an intermediate transform may not be performed after all because an intermediate + * converion is too big. + * @throws ContentIOException there is an unexpected communication or transformation failure. + * @throws UnsupportedTransformationException if isSupported has not been called and */ - @Deprecated void transform(ContentReader reader, ContentWriter writer, Map actualOptions, - String transformName, NodeRef sourceNodeRef) throws Exception; + String transformName, NodeRef sourceNodeRef) + throws UnsupportedTransformationException, ContentIOException; } diff --git a/src/main/java/org/alfresco/repo/rendition2/TransformClient.java b/src/main/java/org/alfresco/repo/rendition2/TransformClient.java index 2867abcbaa..8555a3372e 100644 --- a/src/main/java/org/alfresco/repo/rendition2/TransformClient.java +++ b/src/main/java/org/alfresco/repo/rendition2/TransformClient.java @@ -25,6 +25,8 @@ */ package org.alfresco.repo.rendition2; +import org.alfresco.repo.content.transform.UnsupportedTransformationException; +import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.NodeRef; /** @@ -57,6 +59,12 @@ public interface TransformClient * @param renditionDefinition which rendition to perform * @param user that requested the transform. * @param sourceContentHashCode the hash code of the source node's content URL. Used to check the transform result + * @throws UnsupportedTransformationException if there is an unexpected failure to transform, normally in a + * pipeline, where an intermediate transform may not be performed after all because an intermediate + * conversion is too big. + * @throws ContentIOException there is an unexpected communication or transformation failure. */ - void transform(NodeRef sourceNodeRef, RenditionDefinition2 renditionDefinition, String user, int sourceContentHashCode); + void transform(NodeRef sourceNodeRef, RenditionDefinition2 renditionDefinition, String user, + int sourceContentHashCode) + throws UnsupportedTransformationException, ContentIOException; } diff --git a/src/main/java/org/alfresco/repo/rendition2/TransformationOptionsConverter.java b/src/main/java/org/alfresco/repo/rendition2/TransformationOptionsConverter.java index e6f33462ed..83c39865e4 100644 --- a/src/main/java/org/alfresco/repo/rendition2/TransformationOptionsConverter.java +++ b/src/main/java/org/alfresco/repo/rendition2/TransformationOptionsConverter.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2018 Alfresco Software Limited + * 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 @@ -25,6 +25,7 @@ */ package org.alfresco.repo.rendition2; +import org.alfresco.repo.content.transform.RuntimeExecutableContentTransformerOptions; import org.alfresco.repo.content.transform.magick.ImageResizeOptions; import org.alfresco.repo.content.transform.magick.ImageTransformationOptions; import org.alfresco.repo.content.transform.swf.SWFTransformationOptions; @@ -35,10 +36,14 @@ import org.alfresco.service.cmr.repository.TransformationOptionLimits; import org.alfresco.service.cmr.repository.TransformationOptions; import org.alfresco.service.cmr.repository.TransformationSourceOptions; 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.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -74,7 +79,7 @@ import static org.alfresco.repo.rendition2.RenditionDefinition2.WIDTH; import static org.springframework.util.CollectionUtils.containsAny; /** - * @deprecated converts the new flat name value pair transformer options to the depreacted TransformationOptions. + * @deprecated converts the new flat name value pair transformer options to the deprecated TransformationOptions. * * @author adavis */ @@ -111,6 +116,7 @@ public class TransformationOptionsConverter implements InitializingBean IMAGE_OPTIONS.addAll(CROP_OPTIONS); IMAGE_OPTIONS.addAll(TEMPORAL_OPTIONS); IMAGE_OPTIONS.addAll(RESIZE_OPTIONS); + IMAGE_OPTIONS.add(AUTO_ORIENT); } private static Set PDF_OPTIONS = new HashSet<>(Arrays.asList(new String[] @@ -133,6 +139,8 @@ public class TransformationOptionsConverter implements InitializingBean void set(String s); } + private static Log logger = LogFactory.getLog(TransformationOptionsConverter.class); + // The default valued in the old TransformationOptionsLimits private long maxSourceSizeKBytes; private long readLimitTimeMs; @@ -233,16 +241,17 @@ public class TransformationOptionsConverter implements InitializingBean if (containsPaged || containsCrop || containsTemporal) { List sourceOptionsList = new ArrayList<>(); - opts.setSourceOptionsList(sourceOptionsList); if (containsPaged) { + // The legacy transformer options start at page 1, where as image magick and the local + // transforms start at 0; PagedSourceOptions pagedSourceOptions = new PagedSourceOptions(); sourceOptionsList.add(pagedSourceOptions); - ifSet(options, START_PAGE, (v) -> pagedSourceOptions.setStartPageNumber(Integer.parseInt(v))); - ifSet(options, END_PAGE, (v) -> pagedSourceOptions.setEndPageNumber(Integer.parseInt(v))); + ifSet(options, START_PAGE, (v) -> pagedSourceOptions.setStartPageNumber(Integer.parseInt(v) + 1)); + ifSet(options, END_PAGE, (v) -> pagedSourceOptions.setEndPageNumber(Integer.parseInt(v) + 1)); ifSet(options, PAGE, (v) -> { - int i = Integer.parseInt(v); + int i = Integer.parseInt(v) + 1; pagedSourceOptions.setStartPageNumber(i); pagedSourceOptions.setEndPageNumber(i); }); @@ -267,6 +276,7 @@ public class TransformationOptionsConverter implements InitializingBean ifSet(options, DURATION, (v) -> temporalSourceOptions.setDuration(v)); ifSet(options, OFFSET, (v) -> temporalSourceOptions.setOffset(v)); } + opts.setSourceOptionsList(sourceOptionsList); } } } @@ -321,4 +331,122 @@ public class TransformationOptionsConverter implements InitializingBean setter.set(value); } } + + public Map getOptions(TransformationOptions options) + { + Map map = new HashMap<>(); + map.put(TIMEOUT, "-1"); + if (options != null) + { + if (options instanceof ImageTransformationOptions) + { + ImageTransformationOptions opts = (ImageTransformationOptions) options; + + // TODO We don't support this any more for security reasons, however it might be possible to + // extract some of the well know values and add them to the newer ImageMagick transform options. + String commandOptions = opts.getCommandOptions(); + if (commandOptions != null && !commandOptions.isBlank()) + { + logger.error("ImageMagick commandOptions are no longer supported for security reasons: " + commandOptions); + } + + ImageResizeOptions imageResizeOptions = opts.getResizeOptions(); + if (imageResizeOptions != null) + { + int width = imageResizeOptions.getWidth(); + int height = imageResizeOptions.getHeight(); + ifSet(width != -1, map, RESIZE_WIDTH, width); + ifSet(height != -1, map, RESIZE_HEIGHT, height); + ifSet(imageResizeOptions.isResizeToThumbnail(), map, THUMBNAIL, true); + ifSet(imageResizeOptions.isPercentResize(), map, RESIZE_PERCENTAGE, true); + ifSet(!imageResizeOptions.getAllowEnlargement(), map, ALLOW_ENLARGEMENT, false); + ifSet(imageResizeOptions.isMaintainAspectRatio(), map, MAINTAIN_ASPECT_RATIO, true); + } + + ifSet(!opts.isAutoOrient(), map, AUTO_ORIENT, false); + + Collection sourceOptionsList = opts.getSourceOptionsList(); + if (sourceOptionsList != null) + { + for (TransformationSourceOptions transformationSourceOptions : sourceOptionsList) + { + if (transformationSourceOptions instanceof PagedSourceOptions) + { + PagedSourceOptions pagedSourceOptions = (PagedSourceOptions) transformationSourceOptions; + + // The legacy transformer options start at page 1, where as image magick and the local + // transforms start at 0; + Integer startPageNumber = pagedSourceOptions.getStartPageNumber() - 1; + Integer endPageNumber = pagedSourceOptions.getEndPageNumber() - 1; + if (startPageNumber == endPageNumber) + { + map.put(PAGE, Integer.toString(startPageNumber)); + } + else + { + map.put(START_PAGE, Integer.toString(startPageNumber)); + map.put(END_PAGE, Integer.toString(endPageNumber)); + } + } + else if (transformationSourceOptions instanceof CropSourceOptions) + { + CropSourceOptions cropSourceOptions = (CropSourceOptions) transformationSourceOptions; + String gravity = cropSourceOptions.getGravity(); + boolean percentageCrop = cropSourceOptions.isPercentageCrop(); + int height = cropSourceOptions.getHeight(); + int width = cropSourceOptions.getWidth(); + int xOffset = cropSourceOptions.getXOffset(); + int yOffset = cropSourceOptions.getYOffset(); + ifSet(gravity != null, map, CROP_GRAVITY, gravity); + ifSet(percentageCrop, map, CROP_PERCENTAGE, percentageCrop); + ifSet(width != -1, map, CROP_WIDTH, width); + ifSet(height != -1, map, CROP_HEIGHT, height); + ifSet(xOffset != 0, map, CROP_X_OFFSET, xOffset); + ifSet(yOffset != 0, map, CROP_Y_OFFSET, yOffset); + } + else if (transformationSourceOptions instanceof TemporalSourceOptions) + { + TemporalSourceOptions temporalSourceOptions = (TemporalSourceOptions) transformationSourceOptions; + String duration = temporalSourceOptions.getDuration(); + String offset = temporalSourceOptions.getOffset(); + ifSet(duration != null, map, DURATION, duration); + ifSet(offset != null, map, OFFSET, offset); + } + else + { + logger.error("TransformationOption sourceOptionsList contained a " + + transformationSourceOptions.getClass().getName() + + ". It is not know how to convert this into newer transform options."); + } + } + } + } + else if (options instanceof SWFTransformationOptions) + { + SWFTransformationOptions opts = (SWFTransformationOptions) options; + map.put(FLASH_VERSION, opts.getFlashVersion()); + } + else if (options instanceof RuntimeExecutableContentTransformerOptions) + { + RuntimeExecutableContentTransformerOptions opts = (RuntimeExecutableContentTransformerOptions) options; + map.putAll(opts.getPropertyValues()); + } + else if (!options.getClass().equals(TransformationOptions.class)) + { + throw new IllegalArgumentException("Unable to convert " + + options.getClass().getSimpleName() + " to new transform options held in a Map.\n" + + "The TransformOptionConverter may need to be sub classed to support this conversion."); + } + } + + return map; + } + + protected void ifSet(boolean condition, Map options, String key, Object value) + { + if (condition) + { + options.put(key, value.toString()); + } + } } diff --git a/src/main/java/org/alfresco/repo/service/ServiceDescriptorRegistry.java b/src/main/java/org/alfresco/repo/service/ServiceDescriptorRegistry.java index 38a5fa18a2..5215cc38e6 100644 --- a/src/main/java/org/alfresco/repo/service/ServiceDescriptorRegistry.java +++ b/src/main/java/org/alfresco/repo/service/ServiceDescriptorRegistry.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + * 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 @@ -37,6 +37,7 @@ import org.alfresco.repo.lock.JobLockService; import org.alfresco.repo.nodelocator.NodeLocatorService; import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.rendition2.RenditionService2; +import org.alfresco.repo.rendition2.SynchronousTransformClient; import org.alfresco.repo.search.impl.solr.facet.SolrFacetHelper; import org.alfresco.repo.search.impl.solr.facet.handler.FacetLabelDisplayHandlerRegistry; import org.alfresco.repo.transaction.RetryingTransactionHelper; @@ -161,6 +162,11 @@ public class ServiceDescriptorRegistry return (ContentService)getService(CONTENT_SERVICE); } + public SynchronousTransformClient getSynchronousTransformClient() + { + return (SynchronousTransformClient)getService(SYNCHRONOUS_TRANSFORM_CLIENT); + } + @Override public MimetypeService getMimetypeService() { diff --git a/src/main/java/org/alfresco/repo/template/BaseContentNode.java b/src/main/java/org/alfresco/repo/template/BaseContentNode.java index b7b5772b88..99745d676b 100644 --- a/src/main/java/org/alfresco/repo/template/BaseContentNode.java +++ b/src/main/java/org/alfresco/repo/template/BaseContentNode.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + * 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 @@ -28,6 +28,7 @@ package org.alfresco.repo.template; import java.io.Serializable; import java.text.MessageFormat; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -35,10 +36,12 @@ import org.alfresco.model.ApplicationModel; import org.alfresco.model.ContentModel; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.transform.UnsupportedTransformationException; +import org.alfresco.repo.rendition2.SynchronousTransformClient; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; @@ -601,6 +604,7 @@ public abstract class BaseContentNode implements TemplateContent { // get the content reader ContentService contentService = services.getContentService(); + SynchronousTransformClient synchronousTransformClient = services.getSynchronousTransformClient(); NodeRef nodeRef = getNodeRef(); ContentReader reader = contentService.getReader(nodeRef, property); if (reader == null) @@ -619,22 +623,28 @@ public abstract class BaseContentNode implements TemplateContent // try and transform the content try { - contentService.transform(reader, writer, options); - - ContentReader resultReader = writer.getReader(); - if (resultReader != null && reader.exists()) + try + { + synchronousTransformClient.transform(reader, writer, Collections.emptyMap(), null, nodeRef); + + ContentReader resultReader = writer.getReader(); + if (resultReader != null && reader.exists()) + { + if (length != -1) + { + result = resultReader.getContentString(length); + } + else + { + result = resultReader.getContentString(); + } + } + } + catch (UnsupportedTransformationException ignore) { - if (length != -1) - { - result = resultReader.getContentString(length); - } - else - { - result = resultReader.getContentString(); - } } } - catch (NoTransformerException|UnsupportedTransformationException e) + catch (NoTransformerException|UnsupportedTransformationException| ContentIOException e) { // ignore } diff --git a/src/main/java/org/alfresco/repo/thumbnail/ThumbnailRegistry.java b/src/main/java/org/alfresco/repo/thumbnail/ThumbnailRegistry.java index c21a65bb02..56dafcacc3 100644 --- a/src/main/java/org/alfresco/repo/thumbnail/ThumbnailRegistry.java +++ b/src/main/java/org/alfresco/repo/thumbnail/ThumbnailRegistry.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + * 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 @@ -31,6 +31,7 @@ import org.alfresco.repo.lock.JobLockService; import org.alfresco.repo.lock.LockAcquisitionException; import org.alfresco.repo.rendition2.RenditionDefinition2; import org.alfresco.repo.rendition2.RenditionDefinitionRegistry2; +import org.alfresco.repo.rendition2.TransformationOptionsConverter; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.tenant.Tenant; @@ -38,7 +39,6 @@ import org.alfresco.repo.tenant.TenantAdminService; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.service.cmr.rendition.RenditionDefinition; import org.alfresco.service.cmr.rendition.RenditionService; -import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.TransformationOptions; import org.alfresco.service.cmr.thumbnail.ThumbnailException; @@ -78,9 +78,6 @@ public class ThumbnailRegistry implements ApplicationContextAware, ApplicationLi /** Logger */ private static Log logger = LogFactory.getLog(ThumbnailRegistry.class); - /** Content service */ - private ContentService contentService; - /** Transaction service */ protected TransactionService transactionService; @@ -93,6 +90,10 @@ public class ThumbnailRegistry implements ApplicationContextAware, ApplicationLi private TransformServiceRegistry transformServiceRegistry; + private TransformServiceRegistry localTransformServiceRegistry; + + private TransformationOptionsConverter converter; + private RenditionDefinitionRegistry2 renditionDefinitionRegistry2; private boolean redeployStaticDefsOnStartup; @@ -118,16 +119,6 @@ public class ThumbnailRegistry implements ApplicationContextAware, ApplicationLi return thumbnailRenditionConvertor; } - /** - * Content service - * - * @param contentService content service - */ - public void setContentService(ContentService contentService) - { - this.contentService = contentService; - } - /** * Transaction service * @@ -169,6 +160,16 @@ public class ThumbnailRegistry implements ApplicationContextAware, ApplicationLi mimetypeMap.clear(); } + public void setLocalTransformServiceRegistry(TransformServiceRegistry localTransformServiceRegistry) + { + this.localTransformServiceRegistry = localTransformServiceRegistry; + } + + public void setConverter(TransformationOptionsConverter converter) + { + this.converter = converter; + } + public void setRenditionDefinitionRegistry2(RenditionDefinitionRegistry2 renditionDefinitionRegistry2) { this.renditionDefinitionRegistry2 = renditionDefinitionRegistry2; @@ -319,58 +320,6 @@ public class ThumbnailRegistry implements ApplicationContextAware, ApplicationLi return result; } - public List getThumbnailDefinitions(String sourceUrl, String mimetype, long sourceSize) - { - List thumbnailDefinitionsLimitsForMimetype = this.mimetypeMap.get(mimetype); - - if (thumbnailDefinitionsLimitsForMimetype == null) - { - boolean foundAtLeastOneTransformer = false; - thumbnailDefinitionsLimitsForMimetype = new ArrayList(7); - - for (ThumbnailDefinition thumbnailDefinition : this.thumbnailDefinitions.values()) - { - if (isThumbnailDefinitionAvailable(sourceUrl, mimetype, sourceSize, thumbnailDefinition)) - { - long maxSourceSizeBytes = getMaxSourceSizeBytes(mimetype, thumbnailDefinition); - if (maxSourceSizeBytes != 0) - { - thumbnailDefinitionsLimitsForMimetype.add(new ThumbnailDefinitionLimits(thumbnailDefinition, maxSourceSizeBytes)); - foundAtLeastOneTransformer = true; - } - } - } - - // If we have found no transformers for the given MIME type then we do - // not cache the empty list. We prevent this because we want to allow for - // transformers only coming online *during* system operation - as opposed - // to coming online during startup. - // - // An example of such a transient transformer would be those that use OpenOffice.org. - // It is possible that the system might start without OOo-based transformers - // being available. Therefore we must not cache an empty list for the relevant - // MIME types - otherwise this class would hide the fact that OOo (soffice) has - // been launched and that new transformers are available. - if (foundAtLeastOneTransformer) - { - this.mimetypeMap.put(mimetype, thumbnailDefinitionsLimitsForMimetype); - } - } - - // Only return ThumbnailDefinition for this specific source - may be limited on size. - List result = new ArrayList(thumbnailDefinitionsLimitsForMimetype.size()); - for (ThumbnailDefinitionLimits thumbnailDefinitionLimits: thumbnailDefinitionsLimitsForMimetype) - { - long maxSourceSizeBytes = thumbnailDefinitionLimits.getMaxSourceSizeBytes(); - if (sourceSize <= 0 || maxSourceSizeBytes < 0 || maxSourceSizeBytes >= sourceSize) - { - result.add(thumbnailDefinitionLimits.getThumbnailDefinition()); - } - } - - return result; - } - /** * * @param mimetype String @@ -395,8 +344,8 @@ public class ThumbnailRegistry implements ApplicationContextAware, ApplicationLi */ public boolean isThumbnailDefinitionAvailable(String sourceUrl, String sourceMimetype, long sourceSize, NodeRef sourceNodeRef, ThumbnailDefinition thumbnailDefinition) { - // Use RenditionService2 if it knows about the definition, otherwise use contentService as before. Needed as - // disabling local transforms should not disable thumbnails if they can be done remotely. + // Use RenditionService2 if it knows about the definition, otherwise use localTransformServiceRegistry. + // Needed as disabling local transforms should not disable thumbnails if they can be done remotely. boolean supported = false; String targetMimetype = thumbnailDefinition.getMimetype(); RenditionDefinition2 renditionDefinition = getEquivalentRenditionDefinition2(thumbnailDefinition); @@ -404,18 +353,19 @@ public class ThumbnailRegistry implements ApplicationContextAware, ApplicationLi { Map options = renditionDefinition.getTransformOptions(); String renditionName = renditionDefinition.getRenditionName(); - supported = transformServiceRegistry.isSupported(sourceMimetype, sourceSize, targetMimetype, options, renditionName); + supported = transformServiceRegistry.isSupported(sourceMimetype, sourceSize, targetMimetype, + options, renditionName); } else { boolean orig = TransformerDebug.setDebugOutput(false); try { - // Copy the thumbnail's TransformationOptions and set the sourceNodeRef, for use by debug. - TransformationOptions options = thumbnailDefinition.getTransformationOptions().deepCopy(); - options.setSourceNodeRef(sourceNodeRef); - supported = contentService.getTransformer(sourceUrl, sourceMimetype, sourceSize, - targetMimetype, options) != null; + TransformationOptions transformationOptions = thumbnailDefinition.getTransformationOptions(); + String renditionName = thumbnailDefinition.getName(); + Map options = converter.getOptions(transformationOptions); + supported = localTransformServiceRegistry.isSupported(sourceMimetype, sourceSize, targetMimetype, + options, renditionName); } finally { @@ -448,8 +398,8 @@ public class ThumbnailRegistry implements ApplicationContextAware, ApplicationLi */ public long getMaxSourceSizeBytes(String sourceMimetype, ThumbnailDefinition thumbnailDefinition) { - // Use RenditionService2 if it knows about the definition, otherwise use contentService as before. Needed as - // disabling local transforms should not disable thumbnails if they can be done remotely. + // Use RenditionService2 if it knows about the definition, otherwise use localTransformServiceRegistry. + // Needed as disabling local transforms should not disable thumbnails if they can be done remotely. long maxSize = 0; String targetMimetype = thumbnailDefinition.getMimetype(); RenditionDefinition2 renditionDefinition = getEquivalentRenditionDefinition2(thumbnailDefinition); @@ -464,8 +414,10 @@ public class ThumbnailRegistry implements ApplicationContextAware, ApplicationLi boolean orig = TransformerDebug.setDebugOutput(false); try { - TransformationOptions options = thumbnailDefinition.getTransformationOptions(); - maxSize = contentService.getMaxSourceSizeBytes(sourceMimetype, targetMimetype, options); + TransformationOptions transformationOptions = thumbnailDefinition.getTransformationOptions(); + String renditionName = thumbnailDefinition.getName(); + Map options = converter.getOptions(transformationOptions); + maxSize = localTransformServiceRegistry.findMaxSize(sourceMimetype, targetMimetype, options, renditionName); } finally { diff --git a/src/main/java/org/alfresco/repo/thumbnail/conditions/NodeEligibleForRethumbnailingEvaluator.java b/src/main/java/org/alfresco/repo/thumbnail/conditions/NodeEligibleForRethumbnailingEvaluator.java index 58ed854a55..edf18492cd 100644 --- a/src/main/java/org/alfresco/repo/thumbnail/conditions/NodeEligibleForRethumbnailingEvaluator.java +++ b/src/main/java/org/alfresco/repo/thumbnail/conditions/NodeEligibleForRethumbnailingEvaluator.java @@ -63,7 +63,7 @@ import org.apache.commons.logging.LogFactory; * {@link FailureHandlingOptions#getRetryCount() system.thumbnail.retryCount} times. *

  • These initial retries to produce a thumbnail will occur not more often than every * {@link FailureHandlingOptions#getRetryPeriod() system.thumbnail.retryPeriod} seconds - * and will use which ever content transformers the {@link ContentService#getTransformer(String, String) content service} gives.
  • + * and will use which ever content transformers the ContentService#getTransformer(String, String content service gives. *
  • If a thumbnail is not successfully produced for a node after these attempts then it is considered to be * a 'difficult' piece of content with respect to thumbnailing and the assumption is that a thumbnail may * never be available for it. However, in order to allow for the possibility of software upgrades or similiar, which may diff --git a/src/main/java/org/alfresco/service/ServiceRegistry.java b/src/main/java/org/alfresco/service/ServiceRegistry.java index a91c1ae863..0797adb4b9 100644 --- a/src/main/java/org/alfresco/service/ServiceRegistry.java +++ b/src/main/java/org/alfresco/service/ServiceRegistry.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + * 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 @@ -38,6 +38,7 @@ import org.alfresco.repo.lock.JobLockService; import org.alfresco.repo.nodelocator.NodeLocatorService; import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.rendition2.RenditionService2; +import org.alfresco.repo.rendition2.SynchronousTransformClient; import org.alfresco.repo.search.impl.solr.facet.SolrFacetHelper; import org.alfresco.repo.search.impl.solr.facet.handler.FacetLabelDisplayHandlerRegistry; import org.alfresco.repo.transaction.RetryingTransactionHelper; @@ -112,6 +113,7 @@ public interface ServiceRegistry static final QName DICTIONARY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "DictionaryService"); static final QName NODE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "NodeService"); static final QName CONTENT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ContentService"); + static final QName SYNCHRONOUS_TRANSFORM_CLIENT = QName.createQName(NamespaceService.ALFRESCO_URI, "synchronousTransformClient"); static final QName MIMETYPE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "MimetypeService"); static final QName CONTENT_FILTER_LANGUAGES_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ContentFilterLanguagesService"); static final QName MULTILINGUAL_CONTENT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "MultilingualContentService"); @@ -620,4 +622,13 @@ public interface ServiceRegistry */ @NotAuditable RenditionService2 getRenditionService2(); + + /** + * @return the synchronous transform client (or null, if one is not provided) + */ + @NotAuditable + default SynchronousTransformClient getSynchronousTransformClient() + { + return null; + } } diff --git a/src/main/java/org/alfresco/service/cmr/repository/ContentService.java b/src/main/java/org/alfresco/service/cmr/repository/ContentService.java index 1027fafdf2..a42781d4d4 100644 --- a/src/main/java/org/alfresco/service/cmr/repository/ContentService.java +++ b/src/main/java/org/alfresco/service/cmr/repository/ContentService.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + * 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 @@ -25,11 +25,7 @@ */ package org.alfresco.service.cmr.repository; -import java.util.List; -import java.util.Map; - import org.alfresco.api.AlfrescoPublicApi; -import org.alfresco.repo.content.transform.ContentTransformer; import org.alfresco.service.Auditable; import org.alfresco.service.cmr.dictionary.InvalidTypeException; import org.alfresco.service.namespace.QName; @@ -56,7 +52,7 @@ import org.alfresco.service.namespace.QName; * @author Derek Hulley */ @AlfrescoPublicApi -public interface ContentService +public interface ContentService extends ContentTransformService { /** * Gets the total space of the underlying content store (not exclusively Alfresco-controlled binaries). @@ -156,207 +152,4 @@ public interface ContentService */ @Auditable public ContentWriter getTempWriter(); - - /** - * Transforms the content from the reader and writes the content - * back out to the writer. - *

    - * The mimetypes used for the transformation must be set both on - * the {@link ContentAccessor#getMimetype() reader} and on the - * {@link ContentAccessor#getMimetype() writer}. - * - * @param reader the source content location and mimetype - * @param writer the target content location and mimetype - * @throws NoTransformerException if no transformer exists for the - * given source and target mimetypes of the reader and writer - * @throws ContentIOException if the transformation fails - * - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - @Auditable(parameters = {"reader", "writer"}) - public void transform(ContentReader reader, ContentWriter writer) - throws NoTransformerException, ContentIOException; - - - /** - * @see ContentService#transform(ContentReader, ContentWriter) - * @see ContentService#transform(ContentReader, ContentWriter, TransformationOptions) - * - * A map of transform options can be provided. - * - * @param reader the source content location and mimetype - * @param writer the target content location and mimetype - * @param options the options for the transformation - * @throws NoTransformerException if no transformer exists for the - * given source and target mimetypes of the reader and writer - * @throws ContentIOException if the transformation fails - * - * @deprecated - * As of release 3.0 the TransformOptions class should be used to pass transformation options - * to a transformation execution. - */ - @Deprecated - @Auditable(parameters = {"reader", "writer", "options"}) - public void transform(ContentReader reader, ContentWriter writer, Map options) - throws NoTransformerException, ContentIOException; - - /** - * @see ContentService#transform(ContentReader, ContentWriter) - * - * A transformation options can be provided. - * - * @param reader the source content location and mimetype - * @param writer the target content location and mimetype - * @param options the options for the transformation - * @throws NoTransformerException if no transformer exists for the - * given source and target mimetypes of the reader and writer - * @throws ContentIOException if the transformation fails - * - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - @Auditable(parameters = {"reader", "writer", "options"}) - public void transform(ContentReader reader, ContentWriter writer, TransformationOptions options) - throws NoTransformerException, ContentIOException; - - /** - * Fetch the transformer that is capable of transforming the content in the - * given source mimetype to the given target mimetype. - *

    - * Since no transformation options are provided only the source and destination mimetypes are - * considered when getting the correct transformer. - * - * @param sourceMimetype the source mimetype - * @param targetMimetype the target mimetype - * @return Returns a transformer that can be used, or null if one was not available - * - * @see ContentService#getTransformer(String, String, long, String, TransformationOptions) - * @see ContentAccessor#getMimetype() - * - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - @Auditable(parameters = {"sourceMimetype", "targetMimetype"}) - public ContentTransformer getTransformer(String sourceMimetype, String targetMimetype); - - /** - * Fetch the transformers that are capable of transforming the content in the - * given source mimetype to the given target mimetype with the provided transformation - * options. - *

    - * The transformation options provide a finer grain way of discovering the correct transformer, - * since the values and type of the options provided are considered by the transformer when - * deciding whether it can satisfy the transformation request. - * @param sourceUrl TODO - * @param sourceMimetype the source mimetype - * @param sourceSize the source size (bytes). Ignored if negative. - * @param targetMimetype the target mimetype - * @param options the transformation options - * - * @return ContentTransformer the transformers that can be used, or null if none are available - * - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - @Auditable(parameters = {"sourceMimetype", "sourceSize", "targetMimetype", "options"}) - public List getTransformers(String sourceUrl, String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options); - - /** - * Fetch the transformer that is capable of transforming the content in the - * given source mimetype to the given target mimetype with the provided transformation - * options. - *

    - * The transformation options provide a finer grain way of discovering the correct transformer, - * since the values and type of the options provided are considered by the transformer when - * deciding whether it can satisfy the transformation request. - * @param sourceUrl TODO - * @param sourceMimetype the source mimetype - * @param sourceSize the source size (bytes). Ignored if negative. - * @param targetMimetype the target mimetype - * @param options the transformation options - * - * @return ContentTransformer a transformer that can be used, or null if one was not available - * - * @see ContentAccessor#getMimetype() - * - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - @Auditable(parameters = {"sourceMimetype", "sourceSize", "targetMimetype", "options"}) - public ContentTransformer getTransformer(String sourceUrl, String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options); - - /** - * @deprecated use overloaded method with sourceSize parameter. - */ - @Deprecated - public ContentTransformer getTransformer(String sourceMimetype, String targetMimetype, TransformationOptions options); - - /** - * Returns the maximum source size of any content that may transformed between the supplied - * mimetypes using the supplied options. - * @param sourceMimetype source mime type - * @param targetMimetype target mime type - * @param options transformation options - * @return 0 if there are no transformers, -1 if there is no limit or if positive number the size in bytes. - * - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - @Auditable(parameters = {"sourceMimetype", "targetMimetype", "options"}) - public long getMaxSourceSizeBytes(String sourceMimetype, String targetMimetype, TransformationOptions options); - - /** - * @deprecated use {@link #getTransformers(String, String, long, String, TransformationOptions)}. - * @since 3.5 - */ - @Auditable(parameters = {"sourceMimetype", "sourceSize", "targetMimetype", "options"}) - public List getActiveTransformers(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options); - - /** - * @deprecated use {@link #getTransformers(String, String, long, String, TransformationOptions)}. - */ - public List getActiveTransformers(String sourceMimetype, String targetMimetype, TransformationOptions options); - - /** - * Fetch the transformer that is capable of transforming image content. - * - * @return Returns a transformer that can be used, or null if one was not available - * - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - @Auditable - public ContentTransformer getImageTransformer(); - - /** - * @deprecated use {@link #isTransformable(ContentReader, ContentWriter, TransformationOptions)}. - */ - @Deprecated - @Auditable(parameters = {"reader", "writer"}) - public boolean isTransformable(ContentReader reader, ContentWriter writer); - - /** - * Returns whether a transformer exists that can read the content from - * the reader and write the content back out to the writer with the - * provided tranformation options. - *

    - * If you are about to call {@link #transform(ContentReader, ContentWriter, TransformationOptions)} - * it is best NOT to call this method first as it must perform the same steps and will throw - * NoTransformerException if there are no transformers.

    - * - * The mimetypes used for the transformation must be set both on - * the {@link ContentAccessor#getMimetype() reader} and on the - * {@link ContentAccessor#getMimetype() writer}. - * - * @param reader the source content location and mimetype - * @param writer the target content location and mimetype - * @param options the transformation options - * @return boolean true if a transformer exists, false otherwise - * - * @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries. - */ - @Deprecated - @Auditable(parameters = {"reader", "writer", "options"}) - public boolean isTransformable(ContentReader reader, ContentWriter writer, TransformationOptions options); } diff --git a/src/main/java/org/alfresco/service/cmr/repository/ContentTransformService.java b/src/main/java/org/alfresco/service/cmr/repository/ContentTransformService.java new file mode 100644 index 0000000000..9f9a5cd0f2 --- /dev/null +++ b/src/main/java/org/alfresco/service/cmr/repository/ContentTransformService.java @@ -0,0 +1,134 @@ +/* + * #%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.service.cmr.repository; + +import org.alfresco.repo.content.transform.ContentTransformer; +import org.alfresco.repo.rendition2.SynchronousTransformClient; +import org.alfresco.service.Auditable; +import org.alfresco.transform.client.registry.TransformServiceRegistry; + +import java.util.List; +import java.util.Map; + +/** + * Contains deprecated code from {@link ContentService} that is used to perform Legacy transforms. + * + * @author adavis + */ +public interface ContentTransformService +{ + /** + * @deprecated use {@link SynchronousTransformClient#transform(ContentReader, ContentWriter, Map, String, NodeRef)}. + */ + @Deprecated + @Auditable(parameters = {"reader", "writer"}) + void transform(ContentReader reader, ContentWriter writer) + throws NoTransformerException, ContentIOException; + + + /** + * @deprecated use {@link SynchronousTransformClient#transform(ContentReader, ContentWriter, Map, String, NodeRef)}. + */ + @Deprecated + @Auditable(parameters = {"reader", "writer", "options"}) + void transform(ContentReader reader, ContentWriter writer, Map options) + throws NoTransformerException, ContentIOException; + + /** + * @deprecated use {@link SynchronousTransformClient#transform(ContentReader, ContentWriter, Map, String, NodeRef)}. + */ + @Deprecated + @Auditable(parameters = {"reader", "writer", "options"}) + void transform(ContentReader reader, ContentWriter writer, TransformationOptions options) + throws NoTransformerException, ContentIOException; + + /** + * @deprecated use {@link SynchronousTransformClient#isSupported(String, long, String, String, Map, String, NodeRef)}. + */ + @Deprecated + @Auditable(parameters = {"sourceMimetype", "targetMimetype"}) + ContentTransformer getTransformer(String sourceMimetype, String targetMimetype); + + /** + * @deprecated use {@link SynchronousTransformClient#isSupported(String, long, String, String, Map, String, NodeRef)}. + */ + @Deprecated + @Auditable(parameters = {"sourceMimetype", "sourceSize", "targetMimetype", "options"}) + List getTransformers(String sourceUrl, String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options); + + /** + * @deprecated use {@link SynchronousTransformClient#isSupported(String, long, String, String, Map, String, NodeRef)}. + */ + @Deprecated + @Auditable(parameters = {"sourceMimetype", "sourceSize", "targetMimetype", "options"}) + ContentTransformer getTransformer(String sourceUrl, String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options); + + /** + * @deprecated use {@link SynchronousTransformClient#isSupported(String, long, String, String, Map, String, NodeRef)}. + */ + @Deprecated + ContentTransformer getTransformer(String sourceMimetype, String targetMimetype, TransformationOptions options); + + /** + * @deprecated use {@link TransformServiceRegistry#findMaxSize(String, String, Map, String)}. + */ + @Deprecated + @Auditable(parameters = {"sourceMimetype", "targetMimetype", "options"}) + long getMaxSourceSizeBytes(String sourceMimetype, String targetMimetype, TransformationOptions options); + + /** + * @deprecated use {@link SynchronousTransformClient#isSupported(String, long, String, String, Map, String, NodeRef)}. + */ + @Auditable(parameters = {"sourceMimetype", "sourceSize", "targetMimetype", "options"}) + List getActiveTransformers(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options); + + /** + * @deprecated use {@link SynchronousTransformClient#isSupported(String, long, String, String, Map, String, NodeRef)}. + */ + List getActiveTransformers(String sourceMimetype, String targetMimetype, TransformationOptions options); + + /** + * @deprecated there is no longer a need to obtain a transformer specifically for images. + * Use {@link SynchronousTransformClient#transform(ContentReader, ContentWriter, Map, String, NodeRef)}. + */ + @Deprecated + @Auditable + ContentTransformer getImageTransformer(); + + /** + * @deprecated use {@link SynchronousTransformClient#isSupported(String, long, String, String, Map, String, NodeRef)}. + */ + @Deprecated + @Auditable(parameters = {"reader", "writer"}) + boolean isTransformable(ContentReader reader, ContentWriter writer); + + /** + * @deprecated use {@link SynchronousTransformClient#isSupported(String, long, String, String, Map, String, NodeRef)}. + */ + @Deprecated + @Auditable(parameters = {"reader", "writer", "options"}) + boolean isTransformable(ContentReader reader, ContentWriter writer, TransformationOptions options); +} diff --git a/src/main/resources/alfresco/action-services-context.xml b/src/main/resources/alfresco/action-services-context.xml index 321ee9d495..8c7f5258b4 100644 --- a/src/main/resources/alfresco/action-services-context.xml +++ b/src/main/resources/alfresco/action-services-context.xml @@ -440,6 +440,8 @@ + + {http://www.alfresco.org/model/content/1.0}content diff --git a/src/main/resources/alfresco/content-services-context.xml b/src/main/resources/alfresco/content-services-context.xml index f0e69ac5b8..d49bf8052f 100644 --- a/src/main/resources/alfresco/content-services-context.xml +++ b/src/main/resources/alfresco/content-services-context.xml @@ -148,9 +148,6 @@ - - - @@ -166,9 +163,11 @@ ${policy.content.update.ignoreEmpty} - - - + + + + + @@ -458,9 +457,7 @@ abstract="true" init-method="register" parent="baseContentTransformer"> - - - + application/pdf + diff --git a/src/main/resources/alfresco/extension/video-thumbnail-context.xml.sample b/src/main/resources/alfresco/extension/video-thumbnail-context.xml.sample index f0c1e8ffc3..30c8e48f4b 100644 --- a/src/main/resources/alfresco/extension/video-thumbnail-context.xml.sample +++ b/src/main/resources/alfresco/extension/video-thumbnail-context.xml.sample @@ -111,6 +111,7 @@ content.transformer.ffmpeg.thumbnail.extensions.wmv.jpg.supported=true image/jpeg + diff --git a/src/main/resources/alfresco/extension/xpdf-transform-context.xml.sample b/src/main/resources/alfresco/extension/xpdf-transform-context.xml.sample index c74803587c..890f3f6e4e 100644 --- a/src/main/resources/alfresco/extension/xpdf-transform-context.xml.sample +++ b/src/main/resources/alfresco/extension/xpdf-transform-context.xml.sample @@ -99,5 +99,6 @@ application/pdf + \ No newline at end of file diff --git a/src/main/resources/alfresco/public-services-security-context.xml b/src/main/resources/alfresco/public-services-security-context.xml index 77a5d66ccf..a5a2b401a6 100644 --- a/src/main/resources/alfresco/public-services-security-context.xml +++ b/src/main/resources/alfresco/public-services-security-context.xml @@ -493,11 +493,9 @@ org.alfresco.service.cmr.repository.ContentService.getRawReader=ACL_METHOD.ROLE_ADMINISTRATOR org.alfresco.service.cmr.repository.ContentService.getReader=ACL_NODE.0.sys:base.ReadContent org.alfresco.service.cmr.repository.ContentService.getWriter=ACL_NODE.0.sys:base.WriteContent - org.alfresco.service.cmr.repository.ContentService.isTransformable=ACL_ALLOW - org.alfresco.service.cmr.repository.ContentService.getTransformer=ACL_ALLOW - org.alfresco.service.cmr.repository.ContentService.getMaxSourceSizeBytes=ACL_ALLOW - org.alfresco.service.cmr.repository.ContentService.getImageTransformer=ACL_ALLOW - org.alfresco.service.cmr.repository.ContentService.transform=ACL_ALLOW + org.alfresco.service.cmr.repository.ContentTransformService.getTransformer=ACL_ALLOW + org.alfresco.service.cmr.repository.ContentTransformService.getMaxSourceSizeBytes=ACL_ALLOW + org.alfresco.service.cmr.repository.ContentTransformService.transform=ACL_ALLOW org.alfresco.service.cmr.repository.ContentService.getTempWriter=ACL_ALLOW org.alfresco.service.cmr.repository.ContentService.*=ACL_DENY diff --git a/src/main/resources/alfresco/rendition-services-context.xml b/src/main/resources/alfresco/rendition-services-context.xml index 51849d394d..d4ea1c3330 100644 --- a/src/main/resources/alfresco/rendition-services-context.xml +++ b/src/main/resources/alfresco/rendition-services-context.xml @@ -137,6 +137,12 @@ + + + + + @@ -146,12 +152,12 @@ + parent="baseTransformationRenderingEngine"> + parent="baseTransformationRenderingEngine"> diff --git a/src/main/resources/alfresco/rendition-services2-context.xml b/src/main/resources/alfresco/rendition-services2-context.xml index 72685a5d18..8265dca616 100644 --- a/src/main/resources/alfresco/rendition-services2-context.xml +++ b/src/main/resources/alfresco/rendition-services2-context.xml @@ -92,12 +92,16 @@ + + + + @@ -107,7 +111,9 @@ - + + + @@ -144,7 +150,7 @@ - + diff --git a/src/main/resources/alfresco/subsystems/Transformers/default/transformers-context.xml b/src/main/resources/alfresco/subsystems/Transformers/default/transformers-context.xml index 02e7d4145d..0f17696462 100644 --- a/src/main/resources/alfresco/subsystems/Transformers/default/transformers-context.xml +++ b/src/main/resources/alfresco/subsystems/Transformers/default/transformers-context.xml @@ -7,8 +7,8 @@ - - + + diff --git a/src/main/resources/alfresco/thumbnail-service-context.xml b/src/main/resources/alfresco/thumbnail-service-context.xml index baeef132d3..4f1020f6b2 100644 --- a/src/main/resources/alfresco/thumbnail-service-context.xml +++ b/src/main/resources/alfresco/thumbnail-service-context.xml @@ -232,12 +232,13 @@ - + + diff --git a/src/test/java/org/alfresco/MiscContextTestSuite.java b/src/test/java/org/alfresco/MiscContextTestSuite.java index 6dc71f675c..3d2c6a843d 100644 --- a/src/test/java/org/alfresco/MiscContextTestSuite.java +++ b/src/test/java/org/alfresco/MiscContextTestSuite.java @@ -88,6 +88,22 @@ import org.springframework.context.ApplicationContext; org.alfresco.repo.content.metadata.MappingMetadataExtracterTest.class, + // ---------------------------------------------------------------------- + // Transformer/Rendition contexts + // + // The following tests can be extracted in a separate test suite + // if/when we decide to move the transformations in a separate component + // ---------------------------------------------------------------------- + + // [classpath:alfresco/application-context.xml, classpath:org/alfresco/repo/thumbnail/test-thumbnail-context.xml] + // some tests fail locally - on windows + org.alfresco.repo.thumbnail.ThumbnailServiceImplTest.class, + + // [classpath:/test/alfresco/test-renditions-context.xml, classpath:alfresco/application-context.xml, + // classpath:alfresco/test/global-integration-test-context.xml] + // this does NOT passes locally + org.alfresco.repo.rendition.RenditionServicePermissionsTest.class, + // ---------------------------------------------------------------------- // Misc contexts // ---------------------------------------------------------------------- @@ -122,22 +138,6 @@ import org.springframework.context.ApplicationContext; // [module/module-component-test-beans.xml] org.alfresco.repo.module.ComponentsTest.class, - // ---------------------------------------------------------------------- - // Transformer/Rendition contexts - // - // The following tests can be extracted in a separate test suite - // if/when we decide to move the transformations in a separate component - // ---------------------------------------------------------------------- - - // [classpath:alfresco/application-context.xml, classpath:org/alfresco/repo/thumbnail/test-thumbnail-context.xml] - // some tests fail locally - on windows - org.alfresco.repo.thumbnail.ThumbnailServiceImplTest.class, - - // [classpath:/test/alfresco/test-renditions-context.xml, classpath:alfresco/application-context.xml, - // classpath:alfresco/test/global-integration-test-context.xml] - // this does NOT passes locally - org.alfresco.repo.rendition.RenditionServicePermissionsTest.class, - // [ibatis/hierarchy-test/hierarchy-test-context.xml] org.alfresco.ibatis.HierarchicalSqlSessionFactoryBeanTest.class }) diff --git a/src/test/java/org/alfresco/repo/content/AbstractJodConverterBasedTest.java b/src/test/java/org/alfresco/repo/content/AbstractJodConverterBasedTest.java index da51bfc819..0a1523d53d 100644 --- a/src/test/java/org/alfresco/repo/content/AbstractJodConverterBasedTest.java +++ b/src/test/java/org/alfresco/repo/content/AbstractJodConverterBasedTest.java @@ -27,6 +27,7 @@ package org.alfresco.repo.content; import java.io.File; import java.io.Serializable; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; @@ -38,6 +39,7 @@ import org.alfresco.repo.content.transform.AbstractContentTransformerTest; import org.alfresco.repo.content.transform.ContentTransformer; import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; import org.alfresco.repo.model.Repository; +import org.alfresco.repo.rendition2.SynchronousTransformClient; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.ServiceRegistry; @@ -128,17 +130,9 @@ public abstract class AbstractJodConverterBasedTest */ protected boolean isOpenOfficeAvailable() { - ContentTransformer transformer = contentService.getTransformer(null, MimetypeMap.MIMETYPE_WORD, -1, MimetypeMap.MIMETYPE_PDF, new TransformationOptions()); - - // A transformer may not be returned here if it is unavailable. - if (transformer == null) - { - return false; - } - - // Maybe it's non-null, but not available. - boolean isTransformable = transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, -1, MimetypeMap.MIMETYPE_PDF, null); - return isTransformable; + SynchronousTransformClient synchronousTransformClient = serviceRegistry.getSynchronousTransformClient(); + return synchronousTransformClient.isSupported(MimetypeMap.MIMETYPE_WORD, -1, null, + MimetypeMap.MIMETYPE_PDF, Collections.emptyMap(), null, null); } @Before diff --git a/src/test/java/org/alfresco/repo/content/transform/ArchiveContentTransformerTest.java b/src/test/java/org/alfresco/repo/content/transform/ArchiveContentTransformerTest.java index 3c2d1b5440..55565ef544 100644 --- a/src/test/java/org/alfresco/repo/content/transform/ArchiveContentTransformerTest.java +++ b/src/test/java/org/alfresco/repo/content/transform/ArchiveContentTransformerTest.java @@ -2,7 +2,8 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + + * 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 @@ -27,11 +28,13 @@ package org.alfresco.repo.content.transform; import java.io.File; import java.io.IOException; +import java.util.Collections; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.filestore.FileContentReader; import org.alfresco.repo.content.filestore.FileContentWriter; import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; +import org.alfresco.repo.rendition2.SynchronousTransformClient; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; diff --git a/src/test/java/org/alfresco/repo/content/transform/EMLTransformerTest.java b/src/test/java/org/alfresco/repo/content/transform/EMLTransformerTest.java index d0161da515..965d78156d 100644 --- a/src/test/java/org/alfresco/repo/content/transform/EMLTransformerTest.java +++ b/src/test/java/org/alfresco/repo/content/transform/EMLTransformerTest.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + * 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 @@ -26,18 +26,20 @@ package org.alfresco.repo.content.transform; -import java.io.File; - import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.filestore.FileContentReader; import org.alfresco.repo.content.filestore.FileContentWriter; import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; +import org.alfresco.repo.rendition2.SynchronousTransformClient; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.TransformationOptions; import org.alfresco.util.TempFileProvider; +import java.io.File; +import java.util.Collections; + /** * @see org.alfresco.repo.content.transform.EMLTransformer * @@ -65,6 +67,7 @@ public class EMLTransformerTest extends AbstractContentTransformerTest private EMLTransformer transformer; private ContentTransformerRegistry registry; + private SynchronousTransformClient synchronousTransformClient; @Override public void setUp() throws Exception @@ -77,6 +80,7 @@ public class EMLTransformerTest extends AbstractContentTransformerTest transformer.setTransformerConfig(transformerConfig); registry = (ContentTransformerRegistry) ctx.getBean("contentTransformerRegistry"); + synchronousTransformClient = (SynchronousTransformClient) ctx.getBean("synchronousTransformClient"); } @Override @@ -136,8 +140,7 @@ public class EMLTransformerTest extends AbstractContentTransformerTest } AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName()); - ContentTransformer transformer = serviceRegistry.getContentService().getTransformer(sourceMimetype, targetMimetype); - assertNotNull(transformer); + assertTrue(synchronousTransformClient.isSupported(sourceMimetype, -1, null, targetMimetype, Collections.emptyMap(), null, null)); String sourceExtension = mimetypeService.getExtension(sourceMimetype); String targetExtension = mimetypeService.getExtension(targetMimetype); @@ -153,7 +156,7 @@ public class EMLTransformerTest extends AbstractContentTransformerTest // do the transformation sourceReader.setMimetype(sourceMimetype); targetWriter.setMimetype(targetMimetype); - transformer.transform(sourceReader.getReader(), targetWriter); + synchronousTransformClient.transform(sourceReader, targetWriter, Collections.emptyMap(), null, null); ContentReader targetReader = new FileContentReader(targetFile); assertTrue(targetReader.getSize() > 0); diff --git a/src/test/java/org/alfresco/repo/content/transform/RemoteTransformerClientTest.java b/src/test/java/org/alfresco/repo/content/transform/RemoteTransformerClientTest.java index db574bf756..2887a48b41 100644 --- a/src/test/java/org/alfresco/repo/content/transform/RemoteTransformerClientTest.java +++ b/src/test/java/org/alfresco/repo/content/transform/RemoteTransformerClientTest.java @@ -168,7 +168,7 @@ public class RemoteTransformerClientTest Pair available = remoteTransformerClient.check(mockLogger); assertFalse("Any failure should result in false", available.getFirst()); - assertEquals("Remote TRANSFORMER check returned a 1234 status AN ERROR MESSAGE http://localhost:1234/test/version", + assertEquals("TRANSFORMER check returned a 1234 status AN ERROR MESSAGE http://localhost:1234/test/version", getMessage(available.getSecond())); } @@ -178,7 +178,7 @@ public class RemoteTransformerClientTest when(mockStatusLine.getStatusCode()).thenReturn(1234); doReturn("\"message\":\"AN ERROR MESSAGE\",\"path\":").when(remoteTransformerClient).getContent(any()); - assertRequestTransformError("Remote TRANSFORMER returned a 1234 status AN ERROR MESSAGE http://localhost:1234/test/transform"); + assertRequestTransformError("TRANSFORMER returned a 1234 status AN ERROR MESSAGE http://localhost:1234/test/transform"); } @Test @@ -190,7 +190,7 @@ public class RemoteTransformerClientTest Pair available = remoteTransformerClient.check(mockLogger); assertFalse("Any failure should result in false", available.getFirst()); - assertEquals("Remote TRANSFORMER check failed to connect or to read the response", + assertEquals("TRANSFORMER check failed to connect or to read the response", getMessage(available.getSecond())); assertTransformerBecomesAvailableAgainAfterFailure(); @@ -204,7 +204,7 @@ public class RemoteTransformerClientTest // Mock a connection failure, check the error and reset the mock doThrow(IOException.class).when(remoteTransformerClient).execute(any(), any(HttpPost.class)); - assertRequestTransformError("Remote TRANSFORMER failed to connect or to read the response"); + assertRequestTransformError("TRANSFORMER failed to connect or to read the response"); assertFalse(remoteTransformerClient.isAvailable()); doReturn(mockHttpResponse).when(remoteTransformerClient).execute(any(), any(HttpPost.class)); diff --git a/src/test/java/org/alfresco/repo/content/transform/TransformerConfigDynamicTransformersTest.java b/src/test/java/org/alfresco/repo/content/transform/TransformerConfigDynamicTransformersTest.java index 499c96a661..bc0c4a8a9d 100644 --- a/src/test/java/org/alfresco/repo/content/transform/TransformerConfigDynamicTransformersTest.java +++ b/src/test/java/org/alfresco/repo/content/transform/TransformerConfigDynamicTransformersTest.java @@ -32,9 +32,9 @@ import static org.mockito.Mockito.when; import java.util.Properties; +import org.alfresco.repo.rendition2.LegacySynchronousTransformClient; import org.alfresco.service.cmr.module.ModuleDetails; import org.alfresco.service.cmr.module.ModuleService; -import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.MimetypeService; import org.alfresco.service.cmr.repository.TransformationOptions; import org.alfresco.service.descriptor.Descriptor; @@ -64,7 +64,7 @@ public class TransformerConfigDynamicTransformersTest private MimetypeService mimetypeService; @Mock - private ContentService contentService; + private LegacySynchronousTransformClient legacySynchronousTransformClient; @Mock private TransformerDebug transformerDebug; @@ -118,7 +118,7 @@ public class TransformerConfigDynamicTransformersTest mockProperties(transformerProperties, "content.transformer.transformerA.pipeline", "transformer1|pdf|transformer2|png|transformer3"); - assertEquals(0, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + assertEquals(0, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, null, null).getErrorCount()); assertEquals(4, transformerRegistry.getAllTransformers().size()); @@ -149,7 +149,7 @@ public class TransformerConfigDynamicTransformersTest mockProperties(transformerProperties, "content.transformer.transformerA.pipeline", "transformer1|pdf"); - assertEquals(1, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + assertEquals(1, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, null, null).getErrorCount()); } @@ -160,7 +160,7 @@ public class TransformerConfigDynamicTransformersTest mockProperties(transformerProperties, "content.transformer.transformerA.pipeline", "transformer1|pdf|transformer2|png"); - assertEquals(1, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + assertEquals(1, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, null, null).getErrorCount()); } @@ -171,7 +171,7 @@ public class TransformerConfigDynamicTransformersTest mockProperties(transformerProperties, "content.transformer.transformer3.pipeline", "transformer1|pdf|transformer2"); - assertEquals(1, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + assertEquals(1, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, null, null).getErrorCount()); } @@ -182,7 +182,7 @@ public class TransformerConfigDynamicTransformersTest mockProperties(transformerProperties, "content.transformer.transformerA.pipeline", "transformer1|*|transformer2|png|transformer3"); - new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, null, null); transformerRegistry.getTransformer("transformer.transformerA"); @@ -195,7 +195,7 @@ public class TransformerConfigDynamicTransformersTest mockProperties(transformerProperties, "content.transformer.transformerA.pipeline", "transformer1|pdf|*|png|transformer3"); - new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, null, null); transformerRegistry.getTransformer("transformer.transformerA"); @@ -208,7 +208,7 @@ public class TransformerConfigDynamicTransformersTest mockProperties(transformerProperties, "content.transformer.transformerA.pipeline", "unknown1|pdf|unknown2|png|unknown3"); - assertEquals(1, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + assertEquals(1, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, null, null).getErrorCount()); } @@ -220,7 +220,7 @@ public class TransformerConfigDynamicTransformersTest "content.transformer.transformerA.pipeline", "transformer1|pdf|transformer2|png|transformer3", "content.transformer.transformerA.available", "false"); - new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, null, null); assertEquals(4, transformerRegistry.getAllTransformers().size()); @@ -238,7 +238,7 @@ public class TransformerConfigDynamicTransformersTest mockProperties(transformerProperties, "content.transformer.transformerA.failover", "transformer1|transformer2|transformer3"); - assertEquals(0, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + assertEquals(0, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, null, null).getErrorCount()); assertEquals(4, transformerRegistry.getAllTransformers().size()); @@ -255,7 +255,7 @@ public class TransformerConfigDynamicTransformersTest mockProperties(transformerProperties, "content.transformer.transformerA.failover", "transformer1"); - assertEquals(1, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + assertEquals(1, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, null, null).getErrorCount()); } @@ -266,7 +266,7 @@ public class TransformerConfigDynamicTransformersTest mockProperties(transformerProperties, "content.transformer.transformer3.failover", "transformer1|transformer2"); - assertEquals(1, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + assertEquals(1, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, null, null).getErrorCount()); } @@ -277,7 +277,7 @@ public class TransformerConfigDynamicTransformersTest mockProperties(transformerProperties, "content.transformer.transformerA.failover", "transformer1|*|transformer3"); - new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, null, null); transformerRegistry.getTransformer("transformer.transformerA"); @@ -290,7 +290,7 @@ public class TransformerConfigDynamicTransformersTest mockProperties(transformerProperties, "content.transformer.transformerA.failover", "unknown1|unknown2|unknown3"); - assertEquals(1, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + assertEquals(1, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, null, null).getErrorCount()); } @@ -302,7 +302,7 @@ public class TransformerConfigDynamicTransformersTest "content.transformer.transformerA.failover", "transformer1|transformer2|transformer3", "content.transformer.transformerA.available", "false"); - new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, null, null); assertEquals(4, transformerRegistry.getAllTransformers().size()); @@ -322,7 +322,7 @@ public class TransformerConfigDynamicTransformersTest "content.transformer.transformerD.failover", "transformer1|transformerE", "content.transformer.transformerE.failover", "transformer1|transformer1"); - new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, null, null); assertEquals(5, transformerRegistry.getTransformers().size()); @@ -341,7 +341,7 @@ public class TransformerConfigDynamicTransformersTest "content.transformer.transformerD.failover", "transformer1|transformerE", "content.transformer.transformerE.failover", "transformer1|transformerC"); - new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, null, null); assertEquals(2, transformerRegistry.getTransformers().size()); @@ -358,7 +358,7 @@ public class TransformerConfigDynamicTransformersTest "content.transformer.transformerA.failover", "transformer1|transformer2|transformer3", "content.transformer.transformerA.edition", "Enterprise"); - new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, descriptorService, null); } @@ -370,7 +370,7 @@ public class TransformerConfigDynamicTransformersTest "content.transformer.transformerA.failover", "transformer1|transformer2|transformer3", "content.transformer.transformerA.amp", moduleId); - new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, moduleService, null, null); } @@ -477,7 +477,7 @@ public class TransformerConfigDynamicTransformersTest mockProperties(transformerProperties, transformerNamesAndValues); - assertEquals(0, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, contentService, + assertEquals(0, new TransformerConfigDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient, transformerRegistry, transformerDebug, null, null, properties).getErrorCount()); // Throws an exception if it does not exist diff --git a/src/test/java/org/alfresco/repo/content/transform/TransformerDebugTest.java b/src/test/java/org/alfresco/repo/content/transform/TransformerDebugTest.java index e6e0940300..6cdf92c3dc 100644 --- a/src/test/java/org/alfresco/repo/content/transform/TransformerDebugTest.java +++ b/src/test/java/org/alfresco/repo/content/transform/TransformerDebugTest.java @@ -170,9 +170,9 @@ public class TransformerDebugTest assertDebugEntriesEquals(new String[] { "0 pdf txt 1.5 MB ContentService.transform(...) NO transformers\n"+ - "0 --a) [---] transformer1<> > 50 KB\n"+ - "0 --b) [---] transformer3<> > 50 KB\n"+ - "0 --c) [---] transformer4<> > 50 KB\n"+ + "0 --a) [---] Legacy:transformer1<> > 50 KB\n"+ + "0 --b) [---] Legacy:transformer3<> > 50 KB\n"+ + "0 --c) [---] Legacy:transformer4<> > 50 KB\n"+ "0 Finished in NN ms Just checking if a transformer is available"}, unnumbered(untimed(debug.getEntries(10)))); assertArrayEquals(new String[] { "0 pdf txt WARN 1.5 MB NN ms No transformers as file is > 50 KB"}, unnumbered(untimed(stripDateStamp(log.getEntries(10))))); diff --git a/src/test/java/org/alfresco/repo/rendition/MockedTestServiceRegistry.java b/src/test/java/org/alfresco/repo/rendition/MockedTestServiceRegistry.java index 64f5458cd8..c2f81c16f8 100644 --- a/src/test/java/org/alfresco/repo/rendition/MockedTestServiceRegistry.java +++ b/src/test/java/org/alfresco/repo/rendition/MockedTestServiceRegistry.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + * 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 @@ -90,11 +90,6 @@ import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.service.transaction.TransactionService; -/** - * - * @deprecated We are introducing the new async RenditionService2. - */ -@Deprecated public class MockedTestServiceRegistry implements ServiceRegistry { private final ActionService actionService = mock(ActionService.class); diff --git a/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionIntegrationTest.java b/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionIntegrationTest.java index efd5066195..719234cedd 100644 --- a/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionIntegrationTest.java +++ b/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionIntegrationTest.java @@ -115,6 +115,9 @@ public abstract class AbstractRenditionIntegrationTest extends BaseSpringTest @Autowired protected LegacyTransformServiceRegistry legacyTransformServiceRegistry; + @Autowired + protected TransformationOptionsConverter converter; + static String PASSWORD = "password"; protected static final String ADMIN = "admin"; @@ -207,6 +210,8 @@ public abstract class AbstractRenditionIntegrationTest extends BaseSpringTest renditionDefinitionRegistry2.afterPropertiesSet(); thumbnailRegistry.setTransformServiceRegistry(transformServiceRegistry); + thumbnailRegistry.setLocalTransformServiceRegistry(localTransformServiceRegistry); + thumbnailRegistry.setConverter(converter); } @After diff --git a/src/test/java/org/alfresco/repo/rendition2/LocalSynchronousTransformClientIntegrationTest.java b/src/test/java/org/alfresco/repo/rendition2/LocalSynchronousTransformClientIntegrationTest.java index 68bd3eb536..a5cde83a8f 100644 --- a/src/test/java/org/alfresco/repo/rendition2/LocalSynchronousTransformClientIntegrationTest.java +++ b/src/test/java/org/alfresco/repo/rendition2/LocalSynchronousTransformClientIntegrationTest.java @@ -25,7 +25,9 @@ */ package org.alfresco.repo.rendition2; +import org.alfresco.model.ContentModel; import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; @@ -35,7 +37,13 @@ import org.junit.BeforeClass; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import static org.alfresco.model.ContentModel.PROP_CONTENT; @@ -86,6 +94,23 @@ public class LocalSynchronousTransformClientIntegrationTest extends AbstractRend checkTransform("quick.docx", "doclib", true); } + @Test + public void testParallelTransforms() throws Exception + { + Collection> transforms = new ArrayList<>(); + ExecutorService executorService = Executors.newWorkStealingPool(10); + for (int i=0; i<50; i++) + { + Callable callable = () -> + { + checkTransform("quick.txt", "text/plain", Collections.emptyMap(), true); + return null; + }; + transforms.add(callable); + } + executorService.invokeAll(transforms); + } + @Test public void testTransformDocxJpegImgpreview() throws Exception { @@ -136,16 +161,21 @@ public class LocalSynchronousTransformClientIntegrationTest extends AbstractRend { if (expectedToPass) { - NodeRef sourceNode = transactionService.getRetryingTransactionHelper().doInTransaction(() -> - createContentNodeFromQuickFile(testFileName)); - RenditionDefinition2 renditionDefinition = renditionDefinitionRegistry2.getRenditionDefinition(renditionDefinitionName); String targetMimetype = renditionDefinition.getTargetMimetype(); Map actualOptions = renditionDefinition.getTransformOptions(); - synchronousTransformClient.isSupported(sourceNode, targetMimetype, actualOptions, null, nodeService); + checkTransform(testFileName, targetMimetype, actualOptions, expectedToPass); + } + } + private void checkTransform(String testFileName, String targetMimetype, Map actualOptions, boolean expectedToPass) + { + if (expectedToPass) + { + NodeRef sourceNode = transactionService.getRetryingTransactionHelper().doInTransaction(() -> + createContentNodeFromQuickFile(testFileName)); ContentReader reader = contentService.getReader(sourceNode, PROP_CONTENT); ContentWriter writer = contentService.getTempWriter(); writer.setMimetype(targetMimetype); @@ -154,7 +184,7 @@ public class LocalSynchronousTransformClientIntegrationTest extends AbstractRend ContentReader transformReader = writer.getReader(); String content = transformReader == null ? null : transformReader.getContentString(); content = content == null || content.isEmpty() ? null : content; - assertNotNull("The synchronous transform similar to "+renditionDefinitionName+" resulted in no content", content); + assertNotNull("The synchronous transform resulted in no content", content); } } } diff --git a/src/test/java/org/alfresco/repo/rendition2/LocalTransformServiceRegistryIntegrationTest.java b/src/test/java/org/alfresco/repo/rendition2/LocalTransformServiceRegistryIntegrationTest.java index c858058a23..f70b02d6d5 100644 --- a/src/test/java/org/alfresco/repo/rendition2/LocalTransformServiceRegistryIntegrationTest.java +++ b/src/test/java/org/alfresco/repo/rendition2/LocalTransformServiceRegistryIntegrationTest.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2018 Alfresco Software Limited + * 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 @@ -27,14 +27,11 @@ package org.alfresco.repo.rendition2; import org.alfresco.repo.content.transform.LocalTransformServiceRegistry; 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; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.quartz.CronExpression; import org.springframework.beans.factory.annotation.Autowired; import java.util.HashMap; diff --git a/src/test/java/org/alfresco/repo/rendition2/RenditionDefinitionTest.java b/src/test/java/org/alfresco/repo/rendition2/RenditionDefinitionTest.java index 96883f007e..c79eea9138 100644 --- a/src/test/java/org/alfresco/repo/rendition2/RenditionDefinitionTest.java +++ b/src/test/java/org/alfresco/repo/rendition2/RenditionDefinitionTest.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2018 Alfresco Software Limited + * 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 @@ -118,6 +118,7 @@ public class RenditionDefinitionTest extends BaseSpringTest RenditionDefinition2 definition2 = renditionDefinitionRegistry2.getRenditionDefinition(renditionName); Map options = definition2.getTransformOptions(); TransformationOptions transformationOptions2 = transformationOptionsConverter.getTransformationOptions(renditionName, options); + Map options2 = transformationOptionsConverter.getOptions(transformationOptions2); transformationOptions2.setUse(null); // The use is not set in the original until much later // The original pdf and webpreview thumbnails are wrong, as they don't include the 'limits' and in the @@ -127,6 +128,8 @@ public class RenditionDefinitionTest extends BaseSpringTest { assertEquals("The TransformationOptions used in transforms for " + renditionName + " should be the same", transformationOptions.toStringAll(), transformationOptions2.toStringAll()); + assertEquals("The transformationOptionsConverter back to the newer format was not the same for " + + renditionName, options, options2); } else { diff --git a/src/test/java/org/alfresco/repo/rule/RuleServiceCoverageTest.java b/src/test/java/org/alfresco/repo/rule/RuleServiceCoverageTest.java index f7d913e081..aa038af72e 100644 --- a/src/test/java/org/alfresco/repo/rule/RuleServiceCoverageTest.java +++ b/src/test/java/org/alfresco/repo/rule/RuleServiceCoverageTest.java @@ -1,28 +1,28 @@ -/* - * #%L - * Alfresco Repository - * %% - * Copyright (C) 2005 - 2016 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% - */ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2005 - 2016 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.rule; import java.io.File; @@ -1076,14 +1076,6 @@ public class RuleServiceCoverageTest extends TestCase */ public void testTransformAction() throws Throwable { - ContentTransformer transformer = transformerRegistry.getTransformer( - MimetypeMap.MIMETYPE_EXCEL, -1, - MimetypeMap.MIMETYPE_TEXT_PLAIN, - new TransformationOptions()); - if (transformer == null) - { - return; - } Map params = new HashMap(1); params.put(TransformActionExecuter.PARAM_MIME_TYPE, MimetypeMap.MIMETYPE_TEXT_PLAIN); params.put(TransformActionExecuter.PARAM_DESTINATION_FOLDER, this.rootNodeRef); @@ -1157,14 +1149,6 @@ public class RuleServiceCoverageTest extends TestCase */ public void testImageTransformAction() throws Throwable { - ContentTransformer transformer = transformerRegistry.getTransformer( - MimetypeMap.MIMETYPE_IMAGE_GIF, -1, - MimetypeMap.MIMETYPE_IMAGE_JPEG, - new TransformationOptions()); - if (transformer == null) - { - return; - } Map params = new HashMap(1); params.put(ImageTransformActionExecuter.PARAM_DESTINATION_FOLDER, this.rootNodeRef); params.put(ImageTransformActionExecuter.PARAM_ASSOC_TYPE_QNAME, ContentModel.ASSOC_CHILDREN); @@ -1993,59 +1977,56 @@ public class RuleServiceCoverageTest extends TestCase public void testAsyncExecutionWithPotentialLoop() { - if (this.transformerRegistry.getTransformer(MimetypeMap.MIMETYPE_EXCEL, -1, MimetypeMap.MIMETYPE_TEXT_PLAIN, new TransformationOptions()) != null) + try { - try - { - Map params = new HashMap(1); - params.put(TransformActionExecuter.PARAM_MIME_TYPE, MimetypeMap.MIMETYPE_TEXT_PLAIN); - params.put(TransformActionExecuter.PARAM_DESTINATION_FOLDER, this.nodeRef); - params.put(TransformActionExecuter.PARAM_ASSOC_TYPE_QNAME, ContentModel.ASSOC_CONTAINS); - params.put(TransformActionExecuter.PARAM_ASSOC_QNAME, QName.createQName(TEST_NAMESPACE, "transformed")); - - Rule rule = createRule( - RuleType.INBOUND, - TransformActionExecuter.NAME, - params, - NoConditionEvaluator.NAME, - null); - rule.setExecuteAsynchronously(true); - rule.setTitle("Transform document to text"); - - UserTransaction tx0 = transactionService.getUserTransaction(); - tx0.begin(); - this.ruleService.saveRule(this.nodeRef, rule); - tx0.commit(); - - UserTransaction tx = transactionService.getUserTransaction(); - tx.begin(); - - Map props =new HashMap(1); - props.put(ContentModel.PROP_NAME, "test.xls"); - - // Create the node at the root - NodeRef newNodeRef = this.nodeService.createNode( - this.nodeRef, - ContentModel.ASSOC_CHILDREN, - QName.createQName(TEST_NAMESPACE, "origional"), - ContentModel.TYPE_CONTENT, - props).getChildRef(); - - // Set some content on the origional - ContentWriter contentWriter = this.contentService.getWriter(newNodeRef, ContentModel.PROP_CONTENT, true); - contentWriter.setMimetype(MimetypeMap.MIMETYPE_EXCEL); - File testFile = AbstractContentTransformerTest.loadQuickTestFile("xls"); - contentWriter.putContent(testFile); - - tx.commit(); - - // Sleep to ensure work is done b4 execution is canceled - Thread.sleep(10000); - } - catch (Exception exception) - { - throw new RuntimeException(exception); - } + Map params = new HashMap(1); + params.put(TransformActionExecuter.PARAM_MIME_TYPE, MimetypeMap.MIMETYPE_TEXT_PLAIN); + params.put(TransformActionExecuter.PARAM_DESTINATION_FOLDER, this.nodeRef); + params.put(TransformActionExecuter.PARAM_ASSOC_TYPE_QNAME, ContentModel.ASSOC_CONTAINS); + params.put(TransformActionExecuter.PARAM_ASSOC_QNAME, QName.createQName(TEST_NAMESPACE, "transformed")); + + Rule rule = createRule( + RuleType.INBOUND, + TransformActionExecuter.NAME, + params, + NoConditionEvaluator.NAME, + null); + rule.setExecuteAsynchronously(true); + rule.setTitle("Transform document to text"); + + UserTransaction tx0 = transactionService.getUserTransaction(); + tx0.begin(); + this.ruleService.saveRule(this.nodeRef, rule); + tx0.commit(); + + UserTransaction tx = transactionService.getUserTransaction(); + tx.begin(); + + Map props =new HashMap(1); + props.put(ContentModel.PROP_NAME, "test.xls"); + + // Create the node at the root + NodeRef newNodeRef = this.nodeService.createNode( + this.nodeRef, + ContentModel.ASSOC_CHILDREN, + QName.createQName(TEST_NAMESPACE, "origional"), + ContentModel.TYPE_CONTENT, + props).getChildRef(); + + // Set some content on the origional + ContentWriter contentWriter = this.contentService.getWriter(newNodeRef, ContentModel.PROP_CONTENT, true); + contentWriter.setMimetype(MimetypeMap.MIMETYPE_EXCEL); + File testFile = AbstractContentTransformerTest.loadQuickTestFile("xls"); + contentWriter.putContent(testFile); + + tx.commit(); + + // Sleep to ensure work is done b4 execution is canceled + Thread.sleep(10000); + } + catch (Exception exception) + { + throw new RuntimeException(exception); } } } diff --git a/src/test/java/org/alfresco/repo/thumbnail/ThumbnailServiceImplTest.java b/src/test/java/org/alfresco/repo/thumbnail/ThumbnailServiceImplTest.java index da4b2759d4..8ce6cd2eea 100644 --- a/src/test/java/org/alfresco/repo/thumbnail/ThumbnailServiceImplTest.java +++ b/src/test/java/org/alfresco/repo/thumbnail/ThumbnailServiceImplTest.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + * 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 @@ -26,22 +26,11 @@ package org.alfresco.repo.thumbnail; -import java.io.File; -import java.io.IOException; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.alfresco.model.ContentModel; import org.alfresco.model.RenditionModel; import org.alfresco.repo.action.evaluator.NoConditionEvaluator; import org.alfresco.repo.action.executer.AddFeaturesActionExecuter; import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.repo.content.transform.AbstractContentTransformer2; import org.alfresco.repo.content.transform.AbstractContentTransformerTest; import org.alfresco.repo.content.transform.ContentTransformer; import org.alfresco.repo.content.transform.magick.ImageResizeOptions; @@ -51,6 +40,8 @@ import org.alfresco.repo.domain.dialect.Oracle9Dialect; import org.alfresco.repo.domain.dialect.SQLServerDialect; import org.alfresco.repo.jscript.ClasspathScriptLocation; import org.alfresco.repo.model.Repository; +import org.alfresco.repo.rendition2.SynchronousTransformClient; +import org.alfresco.repo.rendition2.TransformationOptionsConverter; import org.alfresco.repo.thumbnail.script.ScriptThumbnailService; import org.alfresco.repo.transaction.AlfrescoTransactionSupport; import org.alfresco.repo.transaction.RetryingTransactionHelper; @@ -64,7 +55,6 @@ import org.alfresco.service.cmr.lock.LockType; import org.alfresco.service.cmr.rendition.RenditionService; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ContentData; -import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentServiceTransientException; import org.alfresco.service.cmr.repository.ContentWriter; @@ -88,8 +78,10 @@ import org.alfresco.service.namespace.QNamePattern; import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.service.transaction.TransactionService; import org.alfresco.test_category.OwnJVMTestsCategory; +import org.alfresco.transform.client.registry.TransformServiceRegistry; import org.alfresco.util.BaseAlfrescoSpringTest; import org.alfresco.util.GUID; +import org.alfresco.util.Pair; import org.alfresco.util.TempFileProvider; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -105,6 +97,16 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.transaction.TestTransaction; import org.springframework.transaction.annotation.Transactional; +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * Thumbnail service implementation unit test * @@ -135,6 +137,8 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest private PermissionService permissionService; private LockService lockService; private CopyService copyService; + private SynchronousTransformClient synchronousTransformClient; + private TransformationOptionsConverter converter; private NodeRef folder; private static final String TEST_FAILING_MIME_TYPE = "application/vnd.alfresco.test.transientfailure"; @@ -161,6 +165,8 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest this.permissionService = (PermissionService) applicationContext.getBean("PermissionService"); this.lockService = (LockService) applicationContext.getBean("lockService"); this.copyService = (CopyService) applicationContext.getBean("CopyService"); + synchronousTransformClient = (SynchronousTransformClient) applicationContext.getBean("synchronousTransformClient"); + converter = (TransformationOptionsConverter) applicationContext.getBean("transformOptionsConverter"); // Create a folder and some content Map folderProps = new HashMap(1); @@ -172,13 +178,8 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest private void checkTransformer() { - ContentTransformer transformer = this.contentService.getImageTransformer(); - assertNotNull("No transformer returned for 'getImageTransformer'", transformer); - - // Check that it is working - ImageTransformationOptions imageTransformationOptions = new ImageTransformationOptions(); - if (!transformer.isTransformable(MimetypeMap.MIMETYPE_IMAGE_JPEG, -1, MimetypeMap.MIMETYPE_IMAGE_JPEG, - imageTransformationOptions)) + if (!synchronousTransformClient.isSupported(MimetypeMap.MIMETYPE_IMAGE_JPEG, -1, null, + MimetypeMap.MIMETYPE_IMAGE_JPEG, Collections.emptyMap(), null, null)) { fail("Image transformer is not working. Please check your image conversion command setup."); } @@ -551,10 +552,17 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest final NodeRef testNode = this.secureNodeService.createNode(folder, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "transientThumbnail.transientThumbnail"), ContentModel.TYPE_CONTENT, props).getChildRef(); - + + // Modified test to add content. Having no content was failing to find a transformer with Legacy, but now + // does not with both Legacy and Local transforms. As a result the test was passing for the wrong reason. secureNodeService.setProperty(testNode, ContentModel.PROP_CONTENT, new ContentData(null, TEST_FAILING_MIME_TYPE, 0L, null)); - // We don't need to write any content into this node, as our test transformer will fail immediately. + File testFile = AbstractContentTransformerTest.loadNamedQuickTestFile("quick.pdf"); + assertNotNull("Failed to load required test file.", testFile); + ContentWriter writer = contentService.getWriter(testNode, ContentModel.PROP_CONTENT, true); + writer.setMimetype(TEST_FAILING_MIME_TYPE); + writer.setEncoding("UTF-8"); + writer.putContent(testFile); logger.debug("Running failing thumbnail on " + testNode); @@ -1118,10 +1126,12 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest { NodeRef nodeRef = createOriginalContent(this.folder, MimetypeMap.MIMETYPE_HTML); ThumbnailDefinition def = this.thumbnailService.getThumbnailRegistry().getThumbnailDefinition("medium"); - - ContentTransformer transformer = this.contentService.getTransformer(null, MimetypeMap.MIMETYPE_HTML, -1, def - .getMimetype(), def.getTransformationOptions()); - if (transformer != null) + TransformationOptions transformationOptions = def.getTransformationOptions(); + Map options = converter.getOptions(transformationOptions); + String targetMimetype = def.getMimetype(); + boolean supported = synchronousTransformClient.isSupported(MimetypeMap.MIMETYPE_HTML, -1, null, + targetMimetype, options, null, null); + if (supported) { NodeRef thumb = this.thumbnailService.createThumbnail(nodeRef, ContentModel.PROP_CONTENT, def.getMimetype(), def.getTransformationOptions(), def.getName()); @@ -1133,7 +1143,7 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest } def = this.thumbnailService.getThumbnailRegistry().getThumbnailDefinition("webpreview"); - if (transformer != null) + if (supported) { NodeRef thumb = this.thumbnailService.createThumbnail(nodeRef, ContentModel.PROP_CONTENT, def.getMimetype(), def.getTransformationOptions(), def.getName()); @@ -1183,27 +1193,8 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest checkRendition("smallPng", thumbnail1); outputThumbnailTempContentLocation(thumbnail1, "png", "smallPng - 64x64, marked as thumbnail"); - // Create thumbnail - different content property - // TODO - - // Create thumbnail - different command options - // We'll pass illegal command options to ImageMagick in order to trigger an exception - Exception x = null; - try - { - imageTransformationOptions.setCommandOptions("-noSuchOption"); - thumbnail1 = this.thumbnailService.createThumbnail(jpgOrig, ContentModel.PROP_CONTENT, - MimetypeMap.MIMETYPE_IMAGE_PNG, imageTransformationOptions, "smallCO"); - } catch (ContentIOException ciox) - { - x = ciox; - ciox.printStackTrace(); - } - assertNotNull("Expected exception from ImageMagick due to invalid option", x); - // Reset the command options - imageTransformationOptions.setCommandOptions(""); - - +// Removd code: We now automatically discard all extra command options for security reasons. + // Create thumbnail - different target assoc details ThumbnailParentAssociationDetails tpad = new ThumbnailParentAssociationDetails(otherFolder, @@ -1224,7 +1215,7 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest MimetypeMap.MIMETYPE_IMAGE_PNG, imageTransformationOptions, null); assertNotNull(thumbnail1); checkRenditioned(jpgOrig, - Collections.singletonList(new ExpectedAssoc(RegexQNamePattern.MATCH_ALL, null, 5))); + Collections.singletonList(new ExpectedAssoc(RegexQNamePattern.MATCH_ALL, null, 4))); checkRendition(null, thumbnail1); outputThumbnailTempContentLocation(thumbnail1, "png", "'null' - 64x64, marked as thumbnail"); } @@ -1304,11 +1295,6 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest try { - // Reset our transformer count for each test - LongRunningTransformer transformer = (LongRunningTransformer) contentService - .getTransformer(TEST_LONG_RUNNING_MIME_TYPE, MimetypeMap.MIMETYPE_IMAGE_JPEG); - transformer.setTransformCount(0); - Map props = new HashMap(1); props.put(ContentModel.PROP_NAME, "original.test"); final NodeRef source = secureNodeService.createNode(folder, ContentModel.ASSOC_CONTAINS, @@ -1500,68 +1486,90 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest performLongRunningThumbnailTest(expectedThumbnails, expectedAssocs, new EmptyLongRunningConcurrentWork(), 1, 1); } - - /** - * Test transformer. - * - * @since 4.0.1 - */ - private static class TransientFailTransformer extends AbstractContentTransformer2 + + public static class TestTransformServiceRegistry implements TransformServiceRegistry { - public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options) + private TransformServiceRegistry delegate; + + public TestTransformServiceRegistry(TransformServiceRegistry delegate) { - return sourceMimetype.equals(MimetypeMap.MIMETYPE_PDF) && targetMimetype.equals(TEST_FAILING_MIME_TYPE); + this.delegate = delegate; } - - protected void transformInternal(ContentReader reader, ContentWriter writer, TransformationOptions options) throws Exception + + @Override + public boolean isSupported(String sourceMimetype, long sourceSizeInBytes, String targetMimetype, + Map actualOptions, String transformName) { - // fail every time. - throw new ContentServiceTransientException("Transformation intentionally failed for test purposes."); + return sourceMimetype.equals(TEST_FAILING_MIME_TYPE) || sourceMimetype.equals(TEST_LONG_RUNNING_MIME_TYPE) + ? true + : delegate.isSupported(sourceMimetype, sourceSizeInBytes, targetMimetype, actualOptions, transformName); + } + + @Override + public long findMaxSize(String sourceMimetype, String targetMimetype, Map actualOptions, String transformName) + { + return sourceMimetype.equals(TEST_FAILING_MIME_TYPE) || sourceMimetype.equals(TEST_LONG_RUNNING_MIME_TYPE) + ? -1 + : delegate.findMaxSize(sourceMimetype, targetMimetype, actualOptions, transformName); + } + + @Override + public String findTransformerName(String sourceMimetype, long sourceSizeInBytes, + String targetMimetype, Map actualOptions, String renditionName) + { + throw new UnsupportedOperationException("not implemented"); } } - - /** - * Bogus transformer that simulates a somewhat longer running transformation - */ - private static class LongRunningTransformer extends AbstractContentTransformer2 + + public static class TestSynchronousTransformClient implements SynchronousTransformClient { - private int transformCount = 0; + private SynchronousTransformClient delegate; - @Override - public void register() + public TestSynchronousTransformClient(SynchronousTransformClient delegate) { - super.register(); - setStrictMimeTypeCheck(false); - } - - public void setTransformCount(int transformCount) - { - this.transformCount = transformCount; - } - - public int getTransformCount() - { - return transformCount; - } - - @Override - public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options) - { - return sourceMimetype.equals(TEST_LONG_RUNNING_MIME_TYPE) && - (targetMimetype.equals(MimetypeMap.MIMETYPE_IMAGE_JPEG) || - targetMimetype.equals(MimetypeMap.MIMETYPE_IMAGE_PNG)); + this.delegate = delegate; } @Override - protected void transformInternal(ContentReader reader, ContentWriter writer, TransformationOptions options) - throws Exception + public boolean isSupported(String sourceMimetype, long sourceSizeInBytes, String contentUrl, String targetMimetype, + Map actualOptions, String transformName, NodeRef sourceNodeRef) { - Thread.sleep(TEST_LONG_RUNNING_TRANSFORM_TIME); - writer.putContent("SUCCESS"); - transformCount++; + boolean supported = true; + if (!sourceMimetype.equals(TEST_FAILING_MIME_TYPE) && !sourceMimetype.equals(TEST_LONG_RUNNING_MIME_TYPE)) + { + supported = delegate.isSupported(sourceMimetype, sourceSizeInBytes, contentUrl, targetMimetype, actualOptions, + transformName, sourceNodeRef); + } + return supported; + } + + @Override + public void transform(ContentReader reader, ContentWriter writer, Map actualOptions, String transformName, NodeRef sourceNodeRef) + { + String sourceMimetype = reader.getMimetype(); + if (sourceMimetype.equals(TEST_FAILING_MIME_TYPE)) + { + throw new ContentServiceTransientException("Transformation intentionally failed for test purposes."); + } + else if (sourceMimetype.equals(TEST_LONG_RUNNING_MIME_TYPE)) + { + try + { + Thread.sleep(TEST_LONG_RUNNING_TRANSFORM_TIME); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + writer.putContent("SUCCESS"); + } + else + { + delegate.transform(reader, writer, actualOptions, transformName, sourceNodeRef); + } } } - + /** * Defines the work to be done while long running transformations are being performed * and the means to verify that work completed successfully. diff --git a/src/test/java/org/alfresco/repo/version/ContentServiceImplTest.java b/src/test/java/org/alfresco/repo/version/ContentServiceImplTest.java index 6981801fba..6bf24565f6 100644 --- a/src/test/java/org/alfresco/repo/version/ContentServiceImplTest.java +++ b/src/test/java/org/alfresco/repo/version/ContentServiceImplTest.java @@ -30,8 +30,6 @@ import org.alfresco.model.ContentModel; import org.alfresco.repo.content.EmptyContentReader; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.MimetypeMapTest; -import org.alfresco.repo.content.transform.ContentTransformer; -import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; @@ -44,7 +42,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; -import java.util.HashMap; import org.springframework.transaction.annotation.Transactional; /** @@ -114,12 +111,6 @@ public class ContentServiceImplTest extends BaseVersionStoreTest ContentReader contentReader = this.contentService.getReader(versionableNode, ContentModel.PROP_CONTENT); ContentWriter contentWriter = this.contentService.getWriter(versionableNode, ContentModel.PROP_CONTENT, false); - //Call deprecated methods - assertTrue(this.contentService.isTransformable(contentReader, contentWriter)); - this.contentService.transform(contentReader, contentWriter, new HashMap()); - assertNotNull(this.contentService.getActiveTransformers(contentReader.getMimetype(), contentWriter.getMimetype(), new TransformationOptions())); - assertNull(this.contentService.getTransformer(MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_IMAGE_PNG, new TransformationOptions())); - // this.nodeService.setProperty(versionableNode, ContentModel.PROP_NAME, "for debugTransformers.txt"); try { @@ -133,7 +124,7 @@ public class ContentServiceImplTest extends BaseVersionStoreTest try { - this.contentService.transform(null, null); + this.contentService.transform(null, null, new TransformationOptions()); fail("Should throw exception"); } catch (AlfrescoRuntimeException are) @@ -144,17 +135,7 @@ public class ContentServiceImplTest extends BaseVersionStoreTest ContentReader empty = new EmptyContentReader("empty.txt"); try { - this.contentService.transform(empty, null); - fail("Should throw exception"); - } - catch (AlfrescoRuntimeException are) - { - are.getMessage().contains("The content reader mimetype must be set"); - } - - try - { - this.contentService.isTransformable(empty, null, new TransformationOptions()); + this.contentService.transform(empty, null, new TransformationOptions()); fail("Should throw exception"); } catch (AlfrescoRuntimeException are) @@ -165,18 +146,7 @@ public class ContentServiceImplTest extends BaseVersionStoreTest try { contentWriter.setMimetype(null); - this.contentService.transform(contentReader, contentWriter); - fail("Should throw exception"); - } - catch (AlfrescoRuntimeException are) - { - are.getMessage().contains("The content writer mimetype must be set"); - } - - try - { - contentWriter.setMimetype(null); - this.contentService.isTransformable(contentReader, contentWriter, new TransformationOptions()); + this.contentService.transform(contentReader, contentWriter, new TransformationOptions()); fail("Should throw exception"); } catch (AlfrescoRuntimeException are) 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 b014111a1a..ee5c53d135 100644 --- a/src/test/java/org/alfresco/transform/client/registry/LocalTransformServiceRegistryConfigTest.java +++ b/src/test/java/org/alfresco/transform/client/registry/LocalTransformServiceRegistryConfigTest.java @@ -29,13 +29,11 @@ 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; diff --git a/src/test/resources/alfresco-global.properties b/src/test/resources/alfresco-global.properties index 4cd14982c1..ea7ea2d5ad 100644 --- a/src/test/resources/alfresco-global.properties +++ b/src/test/resources/alfresco-global.properties @@ -47,5 +47,8 @@ identity-service.client-socket-timeout=1000 identity-service.client-connection-timeout=3000 identity-service.authentication.enable-username-password-authentication=false -# In the past so it data is read straight away rather than being scheduled for the first time in a few milliseconds +# Use a date in the past, so data is read straight away rather than being scheduled in tests. A few ms is too late. mimetype.config.cronExpression=0 0 0 ? JAN * 1970 +rendition.config.cronExpression=0 0 0 ? JAN * 1970 +local.transform.service.cronExpression=0 0 0 ? JAN * 1970 +transform.service.cronExpression=0 0 0 ? JAN * 1970 \ No newline at end of file diff --git a/src/test/resources/org/alfresco/repo/thumbnail/test-thumbnail-context.xml b/src/test/resources/org/alfresco/repo/thumbnail/test-thumbnail-context.xml index e65ff7bd4a..0571cf9ad4 100644 --- a/src/test/resources/org/alfresco/repo/thumbnail/test-thumbnail-context.xml +++ b/src/test/resources/org/alfresco/repo/thumbnail/test-thumbnail-context.xml @@ -1,13 +1,16 @@ - - - + + + + - + + + + \ No newline at end of file diff --git a/src/test/resources/test/alfresco/test-renditions-context.xml b/src/test/resources/test/alfresco/test-renditions-context.xml index 0c717a0dcd..0f83e5eb4a 100644 --- a/src/test/resources/test/alfresco/test-renditions-context.xml +++ b/src/test/resources/test/alfresco/test-renditions-context.xml @@ -5,7 +5,21 @@ + parent="baseTransformationRenderingEngine"> + + + + + + + + + + + + + + \ No newline at end of file