From 52dc95264c54193df5c1512621fa2f88ce66499a Mon Sep 17 00:00:00 2001 From: Neil McErlean Date: Mon, 8 Mar 2010 17:18:40 +0000 Subject: [PATCH] RenditionService. Reintroduced the spring-based configuration of ThumbnailDefinitions. Major overhaul to the ThumbnailDefinition - RenditionDefinition conversion code. Removed the imported rendition definitions acp, replacing it with the original rendering_actions_space xml. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@19129 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../bootstrap/renderingActionSpace.xml | 18 +++ .../bootstrap/systemRenditionDefinitions.acp | Bin 4152 -> 0 bytes config/alfresco/import-export-context.xml | 2 +- .../alfresco/patch/patch-services-context.xml | 2 +- config/alfresco/thumbnail-service-context.xml | 102 ++++++++++++- .../RenditionServiceIntegrationTest.java | 34 +++-- .../repo/thumbnail/ThumbnailDefinition.java | 15 +- .../repo/thumbnail/ThumbnailRegistry.java | 142 ++++++++++++------ .../ThumbnailRenditionConvertor.java | 94 +++++++++++- .../repo/thumbnail/ThumbnailServiceImpl.java | 26 ++-- 10 files changed, 344 insertions(+), 91 deletions(-) create mode 100644 config/alfresco/bootstrap/renderingActionSpace.xml delete mode 100644 config/alfresco/bootstrap/systemRenditionDefinitions.acp diff --git a/config/alfresco/bootstrap/renderingActionSpace.xml b/config/alfresco/bootstrap/renderingActionSpace.xml new file mode 100644 index 0000000000..d2b6fe9563 --- /dev/null +++ b/config/alfresco/bootstrap/renderingActionSpace.xml @@ -0,0 +1,18 @@ + + + + + + workspace + SpacesStore + rendering_actions_space + ${spaces.rendition.rendering_actions.name} + ${spaces.rendition.rendering_actions.name} + ${spaces.rendition.rendering_actions.description} + + + + + \ No newline at end of file diff --git a/config/alfresco/bootstrap/systemRenditionDefinitions.acp b/config/alfresco/bootstrap/systemRenditionDefinitions.acp deleted file mode 100644 index 6637b71576f8e45ddeda308fa86a7b6863236798..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4152 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 diff --git a/config/alfresco/import-export-context.xml b/config/alfresco/import-export-context.xml index 0ecf791056..371a3f0410 100644 --- a/config/alfresco/import-export-context.xml +++ b/config/alfresco/import-export-context.xml @@ -569,7 +569,7 @@ /${spaces.company_home.childname}/${spaces.dictionary.childname} - alfresco/bootstrap/systemRenditionDefinitions.acp + alfresco/bootstrap/renderingActionSpace.xml alfresco/messages/bootstrap-spaces diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml index 172849a217..be14ae1154 100644 --- a/config/alfresco/patch/patch-services-context.xml +++ b/config/alfresco/patch/patch-services-context.xml @@ -2036,7 +2036,7 @@ /${spaces.company_home.childname}/${spaces.dictionary.childname} - alfresco/bootstrap/systemRenditionDefinitions.acp + alfresco/bootstrap/renderingActionSpace.xml diff --git a/config/alfresco/thumbnail-service-context.xml b/config/alfresco/thumbnail-service-context.xml index 668c0f8700..61c02df622 100644 --- a/config/alfresco/thumbnail-service-context.xml +++ b/config/alfresco/thumbnail-service-context.xml @@ -48,19 +48,107 @@ - + + + - + - medium - doclib - webpreview - imgpreview - avatar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/java/org/alfresco/repo/rendition/RenditionServiceIntegrationTest.java b/source/java/org/alfresco/repo/rendition/RenditionServiceIntegrationTest.java index 7e6be85894..ebddb7325f 100644 --- a/source/java/org/alfresco/repo/rendition/RenditionServiceIntegrationTest.java +++ b/source/java/org/alfresco/repo/rendition/RenditionServiceIntegrationTest.java @@ -59,6 +59,7 @@ 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.StoreRef; +import org.alfresco.service.cmr.thumbnail.ThumbnailService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.RegexQNamePattern; @@ -331,7 +332,7 @@ public class RenditionServiceIntegrationTest extends BaseAlfrescoSpringTest }); // Sleep to let the asynchronous action queue perform the updates to the renditions. // TODO Is there a better way? - Thread.sleep(20000); + Thread.sleep(30000); // Get the renditions and check their content for the new title transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() @@ -1612,24 +1613,27 @@ public class RenditionServiceIntegrationTest extends BaseAlfrescoSpringTest /** * This test method ensures that all the 'built-in' renditionDefinitions are - * available after startup. + * available after startup and that their configuration is correct. * * @throws Exception */ - public void testEnsureBuiltinRenditionDefinitionsAvailable() throws Exception + public void testBuiltinRenditionDefinitions() throws Exception { - final List renditionLocalNames = Arrays.asList(new String[] { "medium", "doclib", "imgpreview", - "webpreview", "avatar" }); - for (String renditionLocalName : renditionLocalNames) - { - validateRenditionDefinition(renditionLocalName); - } + final RenditionDefinition mediumRenditionDef = loadAndValidateRenditionDefinition("medium"); + final RenditionDefinition doclibRenditionDef = loadAndValidateRenditionDefinition("doclib"); + final RenditionDefinition imgpreviewRenditionDef = loadAndValidateRenditionDefinition("imgpreview"); + final RenditionDefinition webpreviewRenditionDef = loadAndValidateRenditionDefinition("webpreview"); + final RenditionDefinition avatarRenditionDef = loadAndValidateRenditionDefinition("avatar"); + + assertEquals(MimetypeMap.MIMETYPE_IMAGE_JPEG, mediumRenditionDef.getParameterValue(AbstractRenderingEngine.PARAM_MIME_TYPE)); + assertEquals(MimetypeMap.MIMETYPE_IMAGE_PNG, doclibRenditionDef.getParameterValue(AbstractRenderingEngine.PARAM_MIME_TYPE)); + assertEquals(MimetypeMap.MIMETYPE_IMAGE_PNG, imgpreviewRenditionDef.getParameterValue(AbstractRenderingEngine.PARAM_MIME_TYPE)); + assertEquals(MimetypeMap.MIMETYPE_FLASH, webpreviewRenditionDef.getParameterValue(AbstractRenderingEngine.PARAM_MIME_TYPE)); + assertEquals(MimetypeMap.MIMETYPE_IMAGE_PNG, avatarRenditionDef.getParameterValue(AbstractRenderingEngine.PARAM_MIME_TYPE)); } - private void validateRenditionDefinition(String renditionLocalName) + private RenditionDefinition loadAndValidateRenditionDefinition(String renditionLocalName) { - System.out.println("Validating rendition definition: " + renditionLocalName); - QName renditionQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, renditionLocalName); RenditionDefinition renditionDefinition = renditionService.loadRenditionDefinition(renditionQName); assertNotNull("'" + renditionLocalName + "' rendition definition was missing.", renditionDefinition); @@ -1639,8 +1643,10 @@ public class RenditionServiceIntegrationTest extends BaseAlfrescoSpringTest assertNotNull("'" + renditionLocalName + "' renditionDefinition had null renderingActionName parameter", renditionDefinition.getParameterValue("renderingActionName")); - assertEquals("RunAs param was wrong for " + renditionLocalName, AuthenticationUtil.getSystemUserName(), - renditionDefinition.getParameterValue(AbstractRenderingEngine.PARAM_RUN_AS)); + // All builtin renditions should be "runas" system + assertEquals(AuthenticationUtil.getSystemUserName(), renditionDefinition.getParameterValue(AbstractRenderingEngine.PARAM_RUN_AS)); + + return renditionDefinition; } /** diff --git a/source/java/org/alfresco/repo/thumbnail/ThumbnailDefinition.java b/source/java/org/alfresco/repo/thumbnail/ThumbnailDefinition.java index fae722e433..9f45220f97 100644 --- a/source/java/org/alfresco/repo/thumbnail/ThumbnailDefinition.java +++ b/source/java/org/alfresco/repo/thumbnail/ThumbnailDefinition.java @@ -39,6 +39,9 @@ public class ThumbnailDefinition /** Path to placeholder thumbnail */ private String placeHolderResourcePath; + /** Username to run the thumbnailrendition as */ + private String runAs; + /** * Default constructor */ @@ -141,7 +144,17 @@ public class ThumbnailDefinition public String getName() { return name; - } + } + + public void setRunAs(String runAs) + { + this.runAs = runAs; + } + + public String getRunAs() + { + return this.runAs; + } /** * diff --git a/source/java/org/alfresco/repo/thumbnail/ThumbnailRegistry.java b/source/java/org/alfresco/repo/thumbnail/ThumbnailRegistry.java index 917bdf02b8..556eeaef73 100644 --- a/source/java/org/alfresco/repo/thumbnail/ThumbnailRegistry.java +++ b/source/java/org/alfresco/repo/thumbnail/ThumbnailRegistry.java @@ -23,13 +23,19 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.alfresco.repo.rendition.executer.AbstractRenderingEngine; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; 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.thumbnail.ThumbnailException; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ApplicationContextEvent; +import org.springframework.extensions.surf.util.AbstractLifecycleBean; /** * Registry of all the thumbnail details available @@ -37,7 +43,7 @@ import org.alfresco.service.namespace.QName; * @author Roy Wetherall * @author Neil McErlean */ -public class ThumbnailRegistry +public class ThumbnailRegistry implements ApplicationContextAware, ApplicationListener { /** Content service */ private ContentService contentService; @@ -45,11 +51,6 @@ public class ThumbnailRegistry /** Rendition service */ private RenditionService renditionService; - private List thumbnails; - - /** This flag indicates whether the thumbnail definitions have been lazily loaded or not. */ - private boolean thumbnailDefinitionsInited = false; - /** Map of thumbnail definition */ private Map thumbnailDefinitions = new HashMap(); @@ -58,6 +59,8 @@ public class ThumbnailRegistry private ThumbnailRenditionConvertor thumbnailRenditionConvertor; + private RegistryLifecycle lifecycle = new RegistryLifecycle(); + public void setThumbnailRenditionConvertor( ThumbnailRenditionConvertor thumbnailRenditionConvertor) { @@ -89,12 +92,47 @@ public class ThumbnailRegistry this.renditionService = renditionService; } - public void setThumbnails(final List thumbnails) + /** + * This method is used to inject the thumbnail definitions. + * @param thumbnailDefinitions + */ + public void setThumbnailDefinitions(final List thumbnailDefinitions) { - this.thumbnails = thumbnails; + for (ThumbnailDefinition td : thumbnailDefinitions) + { + String thumbnailName = td.getName(); + if (thumbnailName == null) + { + throw new ThumbnailException("When adding a thumbnail details object make sure the name is set."); + } - // We'll not populate the data fields in the ThumbnailRegistry here, instead preferring - // to do it lazily later. + this.thumbnailDefinitions.put(thumbnailName, td); + } + } + + /** + * Those thumbnail definitions that are injected by Spring are converted + * to rendition definitions and saved. + */ + private void initThumbnailDefinitions() + { + AuthenticationUtil.runAs(new RunAsWork() { + public Void doWork() throws Exception + { + for (String thumbnailDefName : thumbnailDefinitions.keySet()) + { + final ThumbnailDefinition thumbnailDefinition = thumbnailDefinitions.get(thumbnailDefName); + + // Built-in thumbnailDefinitions do not provide any non-standard values + // for the ThumbnailParentAssociationDetails object. Hence the null + RenditionDefinition renditionDef = thumbnailRenditionConvertor.convert(thumbnailDefinition, null); + + renditionService.saveRenditionDefinition(renditionDef); + } + + return null; + } + }, AuthenticationUtil.getSystemUserName()); } /** @@ -104,36 +142,11 @@ public class ThumbnailRegistry */ public List getThumbnailDefinitions() { - if (thumbnailDefinitionsInited == false) - { - this.initThumbnailDefinitions(); - thumbnailDefinitionsInited = true; - } return new ArrayList(this.thumbnailDefinitions.values()); } - private void initThumbnailDefinitions() - { - for (String thumbnailDefinitionName : this.thumbnails) - { - QName qName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, thumbnailDefinitionName); - RenditionDefinition rAction = renditionService - .loadRenditionDefinition(qName); - - ThumbnailDefinition thDefn = thumbnailRenditionConvertor.convert(rAction); - - thumbnailDefinitions.put(thumbnailDefinitionName, thDefn); - } - } - public List getThumbnailDefinitions(String mimetype) { - if (thumbnailDefinitionsInited == false) - { - this.initThumbnailDefinitions(); - thumbnailDefinitionsInited = true; - } - List result = this.mimetypeMap.get(mimetype); if (result == null) @@ -163,6 +176,7 @@ public class ThumbnailRegistry * @return * @deprecated Use {@link #getThumbnailDefinitions(String)} instead. */ + @Deprecated public List getThumnailDefintions(String mimetype) { return this.getThumbnailDefinitions(mimetype); @@ -175,11 +189,6 @@ public class ThumbnailRegistry */ public void addThumbnailDefinition(ThumbnailDefinition thumbnailDetails) { - if (thumbnailDefinitionsInited == false) - { - this.initThumbnailDefinitions(); - thumbnailDefinitionsInited = true; - } String thumbnailName = thumbnailDetails.getName(); if (thumbnailName == null) { @@ -197,11 +206,48 @@ public class ThumbnailRegistry */ public ThumbnailDefinition getThumbnailDefinition(String thumbnailName) { - if (thumbnailDefinitionsInited == false) - { - this.initThumbnailDefinitions(); - thumbnailDefinitionsInited = true; - } return this.thumbnailDefinitions.get(thumbnailName); } + + /* (non-Javadoc) + * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) + */ + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException + { + lifecycle.setApplicationContext(applicationContext); + } + + /* (non-Javadoc) + * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent) + */ + public void onApplicationEvent(ApplicationContextEvent event) + { + lifecycle.onApplicationEvent(event); + } + + /** + * This class hooks in to the spring application lifecycle and ensures that any + * ThumbnailDefinitions injected by spring are converted to RenditionDefinitions + * and saved. + */ + private class RegistryLifecycle extends AbstractLifecycleBean + { + /* (non-Javadoc) + * @see org.alfresco.util.AbstractLifecycleBean#onBootstrap(org.springframework.context.ApplicationEvent) + */ + @Override + protected void onBootstrap(ApplicationEvent event) + { + initThumbnailDefinitions(); + } + + /* (non-Javadoc) + * @see org.alfresco.util.AbstractLifecycleBean#onShutdown(org.springframework.context.ApplicationEvent) + */ + @Override + protected void onShutdown(ApplicationEvent event) + { + // Intentionally empty + } + } } diff --git a/source/java/org/alfresco/repo/thumbnail/ThumbnailRenditionConvertor.java b/source/java/org/alfresco/repo/thumbnail/ThumbnailRenditionConvertor.java index a5685b055a..235914b22d 100644 --- a/source/java/org/alfresco/repo/thumbnail/ThumbnailRenditionConvertor.java +++ b/source/java/org/alfresco/repo/thumbnail/ThumbnailRenditionConvertor.java @@ -32,19 +32,104 @@ import org.alfresco.service.cmr.rendition.RenditionDefinition; import org.alfresco.service.cmr.rendition.RenditionService; import org.alfresco.service.cmr.repository.TransformationOptions; import org.alfresco.service.cmr.thumbnail.ThumbnailParentAssociationDetails; +import org.alfresco.service.cmr.thumbnail.ThumbnailService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; /** - * A helper class to convert {@link TransformationOptions transformationOptions} (a thumbnail-specific - * class) to rendition-specific parameters and vice versa. + * A helper class to convert {@link ThumbnailDefinition thumbnail definition} and + * {@link TransformationOptions transformationOptions} (thumbnail-specific + * classes) to rendition-specific parameters and vice versa. + * + * The Thumbnail Service exposes parameters as simple data types on its various method + * signatures. See for example ThumbnailDefinition.createThumbnail(...) or updateThumbnail(...). + * The RenditionService replaces this approach with one based on the ActionService where + * parameters are added as a Map on the Action/RenditionDefinition object. + * + * @see ThumbnailService#createThumbnail(org.alfresco.service.cmr.repository.NodeRef, QName, String, TransformationOptions, String) + * @see ThumbnailService#createThumbnail(org.alfresco.service.cmr.repository.NodeRef, QName, String, TransformationOptions, String, ThumbnailParentAssociationDetails) + * @see ThumbnailService#updateThumbnail(org.alfresco.service.cmr.repository.NodeRef, TransformationOptions) + * @see RenditionDefinition * * @author Neil McErlean */ public class ThumbnailRenditionConvertor { + private RenditionService renditionService; + + public void setRenditionService(RenditionService renditionService) + { + this.renditionService = renditionService; + } + + /** Given the specified {@link ThumbnailDefinition thumbnailDefinition} and + * {@link ThumbnailParentAssociationDetails assocDetails}, + * create and return an equivalent {@link RenditionDefinition} object. + * + * @param thumbnailDefinition + * @param assocDetails + * @return + */ + public RenditionDefinition convert(ThumbnailDefinition thumbnailDefinition, ThumbnailParentAssociationDetails assocDetails) + { + // We must always have a valid name for a thumbnail definition + if (thumbnailDefinition == null || thumbnailDefinition.getName() == null + || thumbnailDefinition.getName().trim().length() == 0) + { + throw new IllegalArgumentException("Thumbnail Definition and Name must be non-null and non-empty."); + } + + TransformationOptions transformationOptions = thumbnailDefinition.getTransformationOptions(); + Map parameters = this.convert(transformationOptions, assocDetails); + + // Extract parameters defined directly within the ThumbnailDefinition object. + putParameterIfNotNull(AbstractRenderingEngine.PARAM_MIME_TYPE, thumbnailDefinition.getMimetype(), parameters); + putParameterIfNotNull(AbstractRenderingEngine.PARAM_PLACEHOLDER_RESOURCE_PATH, thumbnailDefinition.getPlaceHolderResourcePath(), parameters); + putParameterIfNotNull(AbstractRenderingEngine.PARAM_RUN_AS, thumbnailDefinition.getRunAs(), parameters); + + QName namespacedRenditionName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, thumbnailDefinition.getName()); + + // The built-in RenditionDefinitions are all non-composites. + // They are either "imageRenderingEngine" or "reformat" + boolean isImageThumbnail = isImageBasedRendition(thumbnailDefinition); + + String renderingEngineName = isImageThumbnail ? ImageRenderingEngine.NAME : ReformatRenderingEngine.NAME; + + RenditionDefinition renditionDef = renditionService.createRenditionDefinition(namespacedRenditionName, renderingEngineName); + for (String paramName : parameters.keySet()) + { + renditionDef.setParameterValue(paramName, parameters.get(paramName)); + } + + return renditionDef; + } + + /** + * This method examines the various data values on the thumbnail definition and + * works out if it is an 'image' rendition or a 'reformat' rendition + * @param thumbnailDefinition + * @return true for an image-based RenditionDefinition, else false + */ + private boolean isImageBasedRendition(ThumbnailDefinition thumbnailDefinition) + { + final TransformationOptions transformationOptions = thumbnailDefinition.getTransformationOptions(); + + return transformationOptions != null && transformationOptions instanceof ImageTransformationOptions; + } + + /** Given the specified {@link TransformationOptions transformationOptions} and + * {@link ThumbnailParentAssociationDetails assocDetails}, + * create and return a parameter Map which contains the equivalent {@link RenditionDefinition} + * configuration. + * + * @param transformationOptions + * @param assocDetails + * @return + */ public Map convert(TransformationOptions transformationOptions, ThumbnailParentAssociationDetails assocDetails) { Map parameters = new HashMap(); - + // parameters common to all transformations putParameterIfNotNull(AbstractRenderingEngine.PARAM_SOURCE_CONTENT_PROPERTY, transformationOptions.getSourceContentProperty(), parameters); putParameterIfNotNull(AbstractRenderingEngine.PARAM_TARGET_CONTENT_PROPERTY, transformationOptions.getTargetContentProperty(), parameters); @@ -111,8 +196,6 @@ public class ThumbnailRenditionConvertor thDefn.setPlaceHolderResourcePath((String)placeHolderResourcePathParam); } - //TODO src/target contentProp & nodeRef - TransformationOptions transformationOptions = null; Serializable flashVersion = renditionDefinition.getParameterValue(ReformatRenderingEngine.PARAM_FLASH_VERSION); if (flashVersion != null) @@ -132,7 +215,6 @@ public class ThumbnailRenditionConvertor Serializable xsize = renditionDefinition.getParameterValue(ImageRenderingEngine.PARAM_RESIZE_WIDTH); if (xsize != null) { - // Saved actions with int parameters seem to be coming back as Longs. TODO Investigate resizeOptions.setWidth(((Long) xsize).intValue()); } diff --git a/source/java/org/alfresco/repo/thumbnail/ThumbnailServiceImpl.java b/source/java/org/alfresco/repo/thumbnail/ThumbnailServiceImpl.java index dc4bcc01ca..01575ba27d 100644 --- a/source/java/org/alfresco/repo/thumbnail/ThumbnailServiceImpl.java +++ b/source/java/org/alfresco/repo/thumbnail/ThumbnailServiceImpl.java @@ -28,6 +28,7 @@ import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.transform.magick.ImageTransformationOptions; import org.alfresco.repo.content.transform.swf.SWFTransformationOptions; import org.alfresco.repo.policy.BehaviourFilter; +import org.alfresco.repo.rendition.executer.AbstractRenderingEngine; import org.alfresco.repo.rendition.executer.ImageRenderingEngine; import org.alfresco.repo.rendition.executer.ReformatRenderingEngine; import org.alfresco.repo.security.authentication.AuthenticationUtil; @@ -202,20 +203,19 @@ public class ThumbnailServiceImpl implements ThumbnailService // We're prepending the cm namespace here. QName thumbnailQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, localThumbnailName); - - RenditionDefinition renderingAction = renditionService.loadRenditionDefinition(thumbnailQName); - if (renderingAction == null) - { - // If the provided thumbnailName does not map to a built-in rendition definition - // then we must create a dynamic rendition definition for this thumbnail. - // To do this we must have a renderingEngineName. - // - // The transformation will either be a imageRenderingEngine or a reformat (pdf2swf) - String renderingEngineName = getRenderingEngineNameFor(transformationOptions); - - renderingAction = renditionService.createRenditionDefinition(thumbnailQName, renderingEngineName); - } + + // Convert the TransformationOptions and ThumbnailParentAssocDetails to + // rendition-style parameters Map params = thumbnailRegistry.getThumbnailRenditionConvertor().convert(transformationOptions, assocDetails); + // Add the other parameters given in this method signature. + params.put(AbstractRenderingEngine.PARAM_SOURCE_CONTENT_PROPERTY, contentProperty); + params.put(AbstractRenderingEngine.PARAM_MIME_TYPE, mimetype); + + // Create the renditionDefinition + String renderingEngineName = getRenderingEngineNameFor(transformationOptions); + RenditionDefinition renderingAction = renditionService.createRenditionDefinition(thumbnailQName, renderingEngineName); + + // Set the parameters for (String key : params.keySet()) { renderingAction.setParameterValue(key, params.get(key));