From 5e60154bf541cbef22d4a5bc3a1109cd5e2ebcae Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Mon, 9 Jun 2008 10:10:16 +0000 Subject: [PATCH] Thumbnail Service: support for asyn creation of thumbnails (unit test's included) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@9428 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/thumbnail-service-context.xml | 15 ++- .../org/alfresco/repo/jscript/ScriptNode.java | 57 ++++++-- .../CreateThumbnailActionExecuter.java | 123 ++++++++++++++++++ .../repo/thumbnail/ThumbnailRegistry.java | 25 ---- .../thumbnail/ThumbnailServiceImplTest.java | 20 +++ .../thumbnail/script/test_thumbnailAPI.js | 31 +++++ .../cmr/thumbnail/ThumbnailService.java | 22 ++++ 7 files changed, 259 insertions(+), 34 deletions(-) create mode 100644 source/java/org/alfresco/repo/thumbnail/CreateThumbnailActionExecuter.java create mode 100644 source/java/org/alfresco/repo/thumbnail/script/test_thumbnailAPI.js diff --git a/config/alfresco/thumbnail-service-context.xml b/config/alfresco/thumbnail-service-context.xml index c543fe2ab7..c11d55ac52 100644 --- a/config/alfresco/thumbnail-service-context.xml +++ b/config/alfresco/thumbnail-service-context.xml @@ -80,6 +80,19 @@ - + + + + + + false + + + + + + + + diff --git a/source/java/org/alfresco/repo/jscript/ScriptNode.java b/source/java/org/alfresco/repo/jscript/ScriptNode.java index 705d1c166f..b3ed3e3362 100644 --- a/source/java/org/alfresco/repo/jscript/ScriptNode.java +++ b/source/java/org/alfresco/repo/jscript/ScriptNode.java @@ -40,11 +40,14 @@ import org.alfresco.model.ContentModel; import org.alfresco.repo.action.executer.TransformActionExecuter; import org.alfresco.repo.content.transform.magick.ImageTransformationOptions; import org.alfresco.repo.search.QueryParameterDefImpl; +import org.alfresco.repo.thumbnail.CreateThumbnailActionExecuter; import org.alfresco.repo.thumbnail.ThumbnailDetails; import org.alfresco.repo.thumbnail.ThumbnailRegistry; import org.alfresco.repo.thumbnail.script.ScriptThumbnail; import org.alfresco.repo.version.VersionModel; +import org.alfresco.scripts.ScriptException; import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.lock.LockStatus; @@ -1905,23 +1908,57 @@ public class ScriptNode implements Serializable, Scopeable */ public ScriptThumbnail createThumbnail(String thumbnailName) { + return createThumbnail(thumbnailName, false); + } + + /** + * Creates a thumbnail for the content property of the node. + * + * The thumbnail name correspionds to pre-set thumbnail details stored in the + * repository. + * + * If the thumbnail is created asynchronously then the result will be null and creation + * of the thumbnail will occure at some point in the background. + * + * @param thumbnailName the name of the thumbnail + * @param async indicates whether the thumbnail is create asynchronously or not + * @return ScriptThumbnail the newly create thumbnail node or null if async creation occures + */ + public ScriptThumbnail createThumbnail(String thumbnailName, boolean async) + { + ScriptThumbnail result = null; + // Use the thumbnail registy to get the details of the thumbail ThumbnailRegistry registry = this.services.getThumbnailService().getThumbnailRegistry(); ThumbnailDetails details = registry.getThumbnailDetails(thumbnailName); if (details == null) { // Throw exception + throw new ScriptException("The thumbnail name '" + thumbnailName + "' is not registered"); } - NodeRef thumbnailNodeRef = this.services.getThumbnailService().createThumbnail( - this.nodeRef, - ContentModel.PROP_CONTENT, - details.getMimetype(), - details.getTransformationOptions(), - details.getName()); + if (async == false) + { + // Create the thumbnail + NodeRef thumbnailNodeRef = this.services.getThumbnailService().createThumbnail( + this.nodeRef, + ContentModel.PROP_CONTENT, + details.getMimetype(), + details.getTransformationOptions(), + details.getName()); + + // Create the thumbnail script object + result = new ScriptThumbnail(thumbnailNodeRef, this.services, this.scope); + } + else + { + // Queue async creation of thumbnail + Action action = this.services.getActionService().createAction(CreateThumbnailActionExecuter.NAME); + action.setParameterValue(CreateThumbnailActionExecuter.PARAM_THUMBANIL_NAME, thumbnailName); + this.services.getActionService().executeAction(action, this.nodeRef, false, true); + } - // Return thumbnail - return new ScriptThumbnail(thumbnailNodeRef, this.services, this.scope); + return result; } /** @@ -1944,6 +1981,10 @@ public class ScriptNode implements Serializable, Scopeable return result; } + /** + * + * @return + */ public ScriptableHashMap getThumbnails() { return null; diff --git a/source/java/org/alfresco/repo/thumbnail/CreateThumbnailActionExecuter.java b/source/java/org/alfresco/repo/thumbnail/CreateThumbnailActionExecuter.java new file mode 100644 index 0000000000..0ce9795362 --- /dev/null +++ b/source/java/org/alfresco/repo/thumbnail/CreateThumbnailActionExecuter.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.thumbnail; + +import java.util.List; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.action.ParameterDefinitionImpl; +import org.alfresco.repo.action.executer.ActionExecuterAbstractBase; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.action.ParameterDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.thumbnail.ThumbnailService; +import org.alfresco.service.namespace.QName; + +/** + * Create thumbnail action executer. + * + * NOTE: This action is used to facilitate the async creation of thumbnails. It is not intended for genereral useage. + * + * @author Roy Wetherall + */ +public class CreateThumbnailActionExecuter extends ActionExecuterAbstractBase +{ + /** Thumbnail Service */ + private ThumbnailService thumbnailService; + + /** Node Service */ + private NodeService nodeService; + + /** Action name and parameters */ + public static final String NAME = "create-thumbnail"; + public static final String PARAM_CONTENT_PROPERTY = "content-property"; + public static final String PARAM_THUMBANIL_NAME = "thumbnail-name"; + + /** + * Set the thumbnail service + * + * @param thumbnailService the thumbnail service + */ + public void setThumbnailService(ThumbnailService thumbnailService) + { + this.thumbnailService = thumbnailService; + } + + /** + * Set the node service + * + * @param nodeService node service + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + /** + * @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef) + */ + @Override + protected void executeImpl(Action action, NodeRef actionedUponNodeRef) + { + if (this.nodeService.exists(actionedUponNodeRef) == true) + { + // Get the thumbnail Name + String thumbnailName = (String)action.getParameterValue(PARAM_THUMBANIL_NAME); + + // Get the details of the thumbnail + ThumbnailRegistry registry = this.thumbnailService.getThumbnailRegistry(); + ThumbnailDetails details = registry.getThumbnailDetails(thumbnailName); + if (details == null) + { + // Throw exception + throw new AlfrescoRuntimeException("The thumbnail name '" + thumbnailName + "' is not registered"); + } + + // Get the content property + QName contentProperty = (QName)action.getParameterValue(PARAM_CONTENT_PROPERTY); + if (contentProperty == null) + { + contentProperty = ContentModel.PROP_CONTENT; + } + + // Create the thumbnail + this.thumbnailService.createThumbnail(actionedUponNodeRef, contentProperty, details.getMimetype(), details.getTransformationOptions(), thumbnailName, null); + } + } + + /** + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) + */ + @Override + protected void addParameterDefinitions(List paramList) + { + paramList.add(new ParameterDefinitionImpl(PARAM_THUMBANIL_NAME, DataTypeDefinition.TEXT, true, getParamDisplayLabel(PARAM_THUMBANIL_NAME))); + paramList.add(new ParameterDefinitionImpl(PARAM_CONTENT_PROPERTY, DataTypeDefinition.QNAME, false, getParamDisplayLabel(PARAM_CONTENT_PROPERTY))); + } + +} diff --git a/source/java/org/alfresco/repo/thumbnail/ThumbnailRegistry.java b/source/java/org/alfresco/repo/thumbnail/ThumbnailRegistry.java index e1c0d565ef..2e2b9c9bef 100644 --- a/source/java/org/alfresco/repo/thumbnail/ThumbnailRegistry.java +++ b/source/java/org/alfresco/repo/thumbnail/ThumbnailRegistry.java @@ -77,29 +77,4 @@ public class ThumbnailRegistry { return this.thumbnailDetails.get(thumbnailName); } - -// /** -// * -// * @param node -// * @param contentProperty -// * @param thumbnailName -// * @return -// */ -// public NodeRef createThumbnail(NodeRef node, QName contentProperty, String thumbnailName) -// { -// // Check to see if we have details of the thumbnail in our list -// ThumbnailDetails details = getThumbnailDetails(thumbnailName); -// if (details == null) -// { -// throw new ThumbnailException("The thumbnail name '" + thumbnailName + "' is not recognised"); -// } -// -// // Create the thumbnail -// return this.thumbnailService.createThumbnail( -// node, -// contentProperty, -// details.getMimetype(), -// details.getTransformationOptions(), -// thumbnailName); -// } } diff --git a/source/java/org/alfresco/repo/thumbnail/ThumbnailServiceImplTest.java b/source/java/org/alfresco/repo/thumbnail/ThumbnailServiceImplTest.java index e05f0e1379..be905ea5fd 100644 --- a/source/java/org/alfresco/repo/thumbnail/ThumbnailServiceImplTest.java +++ b/source/java/org/alfresco/repo/thumbnail/ThumbnailServiceImplTest.java @@ -36,10 +36,13 @@ import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.transform.AbstractContentTransformerTest; import org.alfresco.repo.content.transform.magick.ImageResizeOptions; import org.alfresco.repo.content.transform.magick.ImageTransformationOptions; +import org.alfresco.repo.jscript.ClasspathScriptLocation; import org.alfresco.service.cmr.repository.ChildAssociationRef; 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.ScriptLocation; +import org.alfresco.service.cmr.repository.ScriptService; import org.alfresco.service.cmr.repository.TransformationOptions; import org.alfresco.service.cmr.thumbnail.ThumbnailException; import org.alfresco.service.cmr.thumbnail.ThumbnailService; @@ -56,6 +59,7 @@ import org.alfresco.util.BaseAlfrescoSpringTest; public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest { private ThumbnailService thumbnailService; + private ScriptService scriptService; private MimetypeMap mimetypeMap; private NodeRef folder; @@ -69,6 +73,7 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest // Get the required services this.thumbnailService = (ThumbnailService)this.applicationContext.getBean("ThumbnailService"); this.mimetypeMap = (MimetypeMap)this.applicationContext.getBean("mimetypeService"); + this.scriptService = (ScriptService)this.applicationContext.getBean("ScriptService"); // Create a folder and some content Map folderProps = new HashMap(1); @@ -340,5 +345,20 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest return node; } + + // == Test the JavaScript API == + + public void testJSAPI() throws Exception + { + NodeRef jpgOrig = createOrigionalContent(this.folder, MimetypeMap.MIMETYPE_IMAGE_JPEG); + NodeRef gifOrig = createOrigionalContent(this.folder, MimetypeMap.MIMETYPE_IMAGE_GIF); + + Map model = new HashMap(2); + model.put("jpgOrig", jpgOrig); + model.put("gifOrig", gifOrig); + + ScriptLocation location = new ClasspathScriptLocation("org/alfresco/repo/thumbnail/script/test_thumbnailAPI.js"); + this.scriptService.executeScript(location, model); + } } diff --git a/source/java/org/alfresco/repo/thumbnail/script/test_thumbnailAPI.js b/source/java/org/alfresco/repo/thumbnail/script/test_thumbnailAPI.js new file mode 100644 index 0000000000..f5df4760ae --- /dev/null +++ b/source/java/org/alfresco/repo/thumbnail/script/test_thumbnailAPI.js @@ -0,0 +1,31 @@ +function testCreateThumbnail() +{ + // Create a thumbnail + var thumbnail = jpgOrig.createThumbnail("medium"); + test.assertNotNull(thumbnail); + + // Create async thumbnail +// var thumbnail2 = gifOrig.createThumbnail("medium", true); +// test.assertNull(thumbnail2); + + // Try and get the created thumbnail +// var count = 0; +// while (true) +// { +// thumbnail2 = gifOrig.getThumbnail("medium"); + +// if (thumbnail2 != null) +// { +// break; +// } + //else if (count > 1000) + //{ + // test.fail("Async thumbanil wasn't created"); + //} + +// count++; +// } +} + +// Execute the tests +testCreateThumbnail(); \ No newline at end of file diff --git a/source/java/org/alfresco/service/cmr/thumbnail/ThumbnailService.java b/source/java/org/alfresco/service/cmr/thumbnail/ThumbnailService.java index a7f3a23544..8b0b148689 100644 --- a/source/java/org/alfresco/service/cmr/thumbnail/ThumbnailService.java +++ b/source/java/org/alfresco/service/cmr/thumbnail/ThumbnailService.java @@ -28,6 +28,7 @@ import java.util.List; import org.alfresco.repo.thumbnail.ThumbnailRegistry; import org.alfresco.service.Auditable; +import org.alfresco.service.NotAuditable; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.TransformationOptions; import org.alfresco.service.namespace.QName; @@ -39,6 +40,12 @@ import org.alfresco.service.namespace.QName; */ public interface ThumbnailService { + /** + * Gets the thumbnail registry + * + * @return {@link ThumbnailRegistry} thumbnail registry + */ + @NotAuditable ThumbnailRegistry getThumbnailRegistry(); /** @@ -68,6 +75,21 @@ public interface ThumbnailService @Auditable(key = Auditable.Key.ARG_0, parameters = {"node", "contentProperty", "mimetype", "transformationOptions", "name"}) NodeRef createThumbnail(NodeRef node, QName contentProperty, String mimetype, TransformationOptions transformationOptions, String name); + /** + * @see ThumbnailService#createThumbnail(NodeRef, QName, String, TransformationOptions, String) + * + * If parent association details are specified then the thumbnail is created as a child of the specified parent and linked + * via a non-primary association to the origional content node. + * + * @param node the source content node + * @param contentProperty the content property + * @param mimetype the thumbnail mimetype + * @param transformationOptions the thumbnail transformation options + * @param name the name of the thumbnail (optional, pass null for unnamed thumbnail) + * @param assocDetails the thumbnail parent association details + * @return NodeRef node reference to the newly created thumbnail + */ + @Auditable(key = Auditable.Key.ARG_0, parameters = {"node", "contentProperty", "mimetype", "transformationOptions", "name", "assocDetails"}) NodeRef createThumbnail(NodeRef node, QName contentProperty, String mimetype, TransformationOptions transformationOptions, String name, ThumbnailParentAssociationDetails assocDetails); /**