diff --git a/config/alfresco/hibernate-context.xml b/config/alfresco/hibernate-context.xml index ad2bee4771..d2ca9e4580 100644 --- a/config/alfresco/hibernate-context.xml +++ b/config/alfresco/hibernate-context.xml @@ -388,6 +388,9 @@ + + + diff --git a/config/alfresco/thumbnail-service-context.xml b/config/alfresco/thumbnail-service-context.xml index a2f299c338..869ae35519 100644 --- a/config/alfresco/thumbnail-service-context.xml +++ b/config/alfresco/thumbnail-service-context.xml @@ -38,9 +38,11 @@ - - + + + + diff --git a/source/java/org/alfresco/repo/domain/AuditableProperties.java b/source/java/org/alfresco/repo/domain/AuditableProperties.java index c7bb5a2e59..8ef5179485 100644 --- a/source/java/org/alfresco/repo/domain/AuditableProperties.java +++ b/source/java/org/alfresco/repo/domain/AuditableProperties.java @@ -208,6 +208,65 @@ public class AuditableProperties auditModified = dateStr; } + /** + * Set all cm:auditable parameters as required, giving precedence to the supplied + * property map. + * + * @param user the username + * @param date the creation or modification date + * @param properties the properties to override the user and date + */ + public void setAuditValues(String user, Date date, Map properties) + { + String dateStr = DefaultTypeConverter.INSTANCE.convert(String.class, date); + if (properties.containsKey(ContentModel.PROP_CREATOR)) + { + auditCreator = DefaultTypeConverter.INSTANCE.convert( + String.class, + properties.get(ContentModel.PROP_CREATOR)); + } + else if (auditCreator == null) + { + auditCreator = user; + } + if (properties.containsKey(ContentModel.PROP_MODIFIER)) + { + auditModifier = DefaultTypeConverter.INSTANCE.convert( + String.class, + properties.get(ContentModel.PROP_MODIFIER)); + } + else if (auditModifier == null) + { + auditModifier = user; + } + if (properties.containsKey(ContentModel.PROP_CREATED)) + { + auditCreated = DefaultTypeConverter.INSTANCE.convert( + String.class, + properties.get(ContentModel.PROP_CREATED)); + } + else if (auditCreated == null) + { + auditCreated = dateStr; + } + if (properties.containsKey(ContentModel.PROP_MODIFIED)) + { + auditModified = DefaultTypeConverter.INSTANCE.convert( + String.class, + properties.get(ContentModel.PROP_MODIFIED)); + } + else if (auditModified == null) + { + auditModified = dateStr; + } + if (properties.containsKey(ContentModel.PROP_ACCESSED)) + { + auditAccessed = DefaultTypeConverter.INSTANCE.convert( + String.class, + properties.get(ContentModel.PROP_ACCESSED)); + } + } + /** * For persistance use */ diff --git a/source/java/org/alfresco/repo/importer/ImporterComponentTest.java b/source/java/org/alfresco/repo/importer/ImporterComponentTest.java index 6cd5ded04c..ee9dd3cf8e 100644 --- a/source/java/org/alfresco/repo/importer/ImporterComponentTest.java +++ b/source/java/org/alfresco/repo/importer/ImporterComponentTest.java @@ -26,14 +26,25 @@ package org.alfresco.repo.importer; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import org.alfresco.model.ContentModel; import org.alfresco.repo.security.authentication.AuthenticationComponent; +import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.view.ImporterService; import org.alfresco.service.cmr.view.Location; import org.alfresco.service.cmr.view.ImporterBinding.UUID_BINDING; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.util.BaseSpringTest; import org.alfresco.util.debug.NodeStoreInspector; @@ -71,8 +82,7 @@ public class ImporterComponentTest extends BaseSpringTest } - public void testImport() - throws Exception + public void testImport() throws Exception { InputStream test = getClass().getClassLoader().getResourceAsStream("org/alfresco/repo/importer/importercomponent_test.xml"); InputStreamReader testReader = new InputStreamReader(test, "UTF-8"); @@ -81,6 +91,56 @@ public class ImporterComponentTest extends BaseSpringTest System.out.println(NodeStoreInspector.dumpNodeStore(nodeService, storeRef)); } + public void testImportWithAuditableProperties() throws Exception + { + InputStream test = getClass().getClassLoader().getResourceAsStream("org/alfresco/repo/importer/importercomponent_test.xml"); + InputStreamReader testReader = new InputStreamReader(test, "UTF-8"); + Location location = new Location(storeRef); + try + { + importerService.importView( + testReader, + location, + null, + new ImportTimerProgress()); + } + finally + { + testReader.close(); + } + + NodeRef rootNodeRef = nodeService.getRootNode(storeRef); + List childAssocs = nodeService.getChildAssocs( + rootNodeRef, + RegexQNamePattern.MATCH_ALL, + new RegexQNamePattern(NamespaceService.CONTENT_MODEL_1_0_URI, "SpaceWith.*")); +// QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "SpaceWithAuditable")); + assertEquals("'SpaceWith*' path not found", 2, childAssocs.size()); + + NodeRef nodeRef = childAssocs.get(0).getChildRef(); + Map nodeProps = nodeService.getProperties(nodeRef); + String createdDate = DefaultTypeConverter.INSTANCE.convert(String.class, nodeProps.get(ContentModel.PROP_CREATED)); + String creator = DefaultTypeConverter.INSTANCE.convert(String.class, nodeProps.get(ContentModel.PROP_CREATOR)); + String modifiedDate = DefaultTypeConverter.INSTANCE.convert(String.class, nodeProps.get(ContentModel.PROP_MODIFIED)); + String modifier = DefaultTypeConverter.INSTANCE.convert(String.class, nodeProps.get(ContentModel.PROP_MODIFIER)); + // Check that the cm:auditable properties are correct + assertEquals("cm:created not preserved during import", "2009-05-01T00:00:00.000+01:00", createdDate); + assertEquals("cm:creator not preserved during import", "Import Creator", creator); + assertEquals("cm:modified not preserved during import", "2009-05-02T00:00:00.000+01:00", modifiedDate); + assertEquals("cm:modifier not preserved during import", "Import Modifier", modifier); + + nodeRef = childAssocs.get(1).getChildRef(); + nodeProps = nodeService.getProperties(nodeRef); + createdDate = DefaultTypeConverter.INSTANCE.convert(String.class, nodeProps.get(ContentModel.PROP_CREATED)); + creator = DefaultTypeConverter.INSTANCE.convert(String.class, nodeProps.get(ContentModel.PROP_CREATOR)); + modifiedDate = DefaultTypeConverter.INSTANCE.convert(String.class, nodeProps.get(ContentModel.PROP_MODIFIED)); + modifier = DefaultTypeConverter.INSTANCE.convert(String.class, nodeProps.get(ContentModel.PROP_MODIFIER)); + // Check that the cm:auditable properties are correct + assertEquals("cm:created not preserved during import", "2009-05-01T00:00:00.000+01:00", createdDate); + assertEquals("cm:creator not preserved during import", "Import Creator", creator); + assertEquals("cm:modifier not preserved during import", AuthenticationUtil.getSystemUserName(), modifier); + } + public void testImportWithUuidBinding() throws Exception { Location location = new Location(storeRef); diff --git a/source/java/org/alfresco/repo/importer/importercomponent_test.xml b/source/java/org/alfresco/repo/importer/importercomponent_test.xml index f7837d4202..fef8f73c56 100644 --- a/source/java/org/alfresco/repo/importer/importercomponent_test.xml +++ b/source/java/org/alfresco/repo/importer/importercomponent_test.xml @@ -78,6 +78,26 @@ contentUrl=classpath:org/alfresco/repo/importer/importercomponent_testfile.txt|mimetype=text|size=|encoding= + + + + + SpaceWithAuditable + 2009-05-01T00:00:00.000+01:00 + Import Creator + 2009-05-02T00:00:00.000+01:00 + Import Modifier + + + + + + + SpaceWithPartialAuditable" + 2009-05-01T00:00:00.000+01:00 + Import Creator + + diff --git a/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java b/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java index 025f712796..5019460b90 100644 --- a/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java +++ b/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java @@ -73,6 +73,7 @@ import org.alfresco.repo.domain.hibernate.SessionSizeResourceManager; import org.alfresco.repo.domain.hibernate.StoreImpl; import org.alfresco.repo.domain.hibernate.TransactionImpl; import org.alfresco.repo.node.db.NodeDaoService; +import org.alfresco.repo.policy.BehaviourFilter; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.permissions.ACLType; import org.alfresco.repo.security.permissions.AccessControlListProperties; @@ -191,6 +192,7 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements private DictionaryService dictionaryService; private boolean enableTimestampPropagation; private RetryingTransactionHelper auditableTransactionHelper; + private BehaviourFilter behaviourFilter; /** A cache mapping StoreRef and NodeRef instances to the entity IDs (primary key) */ private SimpleCache storeAndNodeIdCache; /** A cache for more performant lookups of the parent associations */ @@ -311,6 +313,16 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements this.auditableTransactionHelper = auditableTransactionHelper; } + /** + * Set the component to determine the correct aspect behaviours. This applies + * particularly to the cm:auditable case, where the setting of values + * is done automatically except when the behaviour is disabled. + */ + public void setBehaviourFilter(BehaviourFilter behaviourFilter) + { + this.behaviourFilter = behaviourFilter; + } + /** * Ste the transaction-aware cache to store Store and Root Node IDs by Store Reference * @@ -839,21 +851,56 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements } } + /** + * Record the node update, setting the node's cm:auditable properties. + * The cm:auditable properties set implicity if the automatic behaviour + * {@link BehaviourFilter#isEnabled(NodeRef, QName) behaviour} is enabled. + * + * @see #recordNodeUpdate(Node, Map) + */ private void recordNodeUpdate(Node node) + { + recordNodeUpdate(node, null); + } + + /** + * Record the node update, setting the node's cm:auditable properties. + * The cm:auditable properties set implicity if the automatic behaviour + * {@link BehaviourFilter#isEnabled(NodeRef, QName) behaviour} is enabled, + * otherwise the properties are extracted from the properties passed in. + * + * @param node the node to operate on + * @param properties the node properties from which cm:auditable properties + * may be extracted + */ + private void recordNodeUpdate(Node node, Map properties) { updateNodeStatus(node, false); // Handle cm:auditable if (hasNodeAspect(node, ContentModel.ASPECT_AUDITABLE)) { - String currentUser = getCurrentUser(); - Date currentDate = new Date(); + NodeRef nodeRef = node.getNodeRef(); AuditableProperties auditableProperties = node.getAuditableProperties(); if (auditableProperties == null) { auditableProperties = new AuditableProperties(); node.setAuditableProperties(auditableProperties); } - auditableProperties.setAuditValues(currentUser, currentDate, false); + String currentUser = getCurrentUser(); + Date currentDate = new Date(); + // Check if the cm:auditable aspect behaviour is enabled + if (behaviourFilter.isEnabled(nodeRef, ContentModel.ASPECT_AUDITABLE)) + { + // Automatic cm:auditable behaviour + auditableProperties.setAuditValues(currentUser, currentDate, false); + } + else if (properties != null) + { + // Manual cm:auditable behaviour + node.getAuditableProperties().setAuditValues(currentUser, currentDate, properties); + } + // else + // there are no properties, so there is nothing to set } // Propagate timestamps propagateTimestamps(node); @@ -1398,7 +1445,9 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements addNodePropertyImpl(node, qname, propertyValue, localeId); // Record change ID - recordNodeUpdate(node); + recordNodeUpdate( + node, + Collections.singletonMap(qname, propertyValue)); } @SuppressWarnings("unchecked") @@ -1410,12 +1459,16 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements for (Map.Entry entry : properties.entrySet()) { QName qname = entry.getKey(); + if (AuditableProperties.isAuditableProperty(qname)) + { + continue; + } Serializable value = entry.getValue(); addNodePropertyImpl(node, qname, value, localeId); } // Record change ID - recordNodeUpdate(node); + recordNodeUpdate(node, properties); } public void setNodeProperties(Long nodeId, Map propertiesIncl) @@ -1477,7 +1530,7 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements } // Record change ID - recordNodeUpdate(node); + recordNodeUpdate(node, propertiesIncl); } public void removeNodeProperties(Long nodeId, Set propertyQNamesIncl) diff --git a/source/java/org/alfresco/repo/thumbnail/ThumbnailServiceImpl.java b/source/java/org/alfresco/repo/thumbnail/ThumbnailServiceImpl.java index 8e90806702..01b498a6b7 100644 --- a/source/java/org/alfresco/repo/thumbnail/ThumbnailServiceImpl.java +++ b/source/java/org/alfresco/repo/thumbnail/ThumbnailServiceImpl.java @@ -33,6 +33,9 @@ import java.util.Map; import org.alfresco.model.ContentModel; import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.policy.BehaviourFilter; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.ContentReader; @@ -41,6 +44,8 @@ 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 org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.thumbnail.ThumbnailException; import org.alfresco.service.cmr.thumbnail.ThumbnailParentAssociationDetails; import org.alfresco.service.cmr.thumbnail.ThumbnailService; @@ -71,9 +76,15 @@ public class ThumbnailServiceImpl implements ThumbnailService /** Content service */ private ContentService contentService; + /** Permission service */ + private PermissionService permissionService; + /** Mimetype map */ private MimetypeMap mimetypeMap; + /** Behaviour filter */ + private BehaviourFilter behaviourFilter; + /** Thumbnail registry */ private ThumbnailRegistry thumbnailRegistry; @@ -97,6 +108,14 @@ public class ThumbnailServiceImpl implements ThumbnailService this.contentService = contentService; } + /** + * @param permissionService permission service + */ + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + /** * Sets the mimetype map * @@ -107,6 +126,14 @@ public class ThumbnailServiceImpl implements ThumbnailService this.mimetypeMap = mimetypeMap; } + /** + * @param behaviourFilter policy behaviour filter + */ + public void setBehaviourFilter(BehaviourFilter behaviourFilter) + { + this.behaviourFilter = behaviourFilter; + } + /** * Set thumbnail registry * @@ -136,7 +163,8 @@ public class ThumbnailServiceImpl implements ThumbnailService /** * @see org.alfresco.service.cmr.thumbnail.ThumbnailService#createThumbnail(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.lang.String, org.alfresco.service.cmr.repository.TransformationOptions, java.lang.String, org.alfresco.service.cmr.thumbnail.ThumbnailParentAssociationDetails) */ - public NodeRef createThumbnail(NodeRef node, QName contentProperty, String mimetype, TransformationOptions transformationOptions, String thumbnailName, ThumbnailParentAssociationDetails assocDetails) + public NodeRef createThumbnail(final NodeRef node, final QName contentProperty, final String mimetype, + final TransformationOptions transformationOptions, final String thumbnailName, final ThumbnailParentAssociationDetails assocDetails) { // Parameter check ParameterCheck.mandatory("node", node); @@ -149,7 +177,10 @@ public class ThumbnailServiceImpl implements ThumbnailService logger.debug("Creating thumbnail (node=" + node.toString() + "; contentProperty=" + contentProperty.toString() + "; mimetype=" + mimetype); } - NodeRef thumbnail = null; + if (!permissionService.hasPermission(node, PermissionService.READ_PROPERTIES).equals(AccessStatus.ALLOWED)) + { + throw new AccessDeniedException("Access Denied"); + } // Check for duplicate names if (thumbnailName != null && getThumbnailByName(node, contentProperty, thumbnailName) != null) @@ -163,79 +194,99 @@ public class ThumbnailServiceImpl implements ThumbnailService throw new ThumbnailException(ERR_DUPLICATE_NAME); } - // Apply the thumbnailed aspect to the node if it doesn't already have it - if (this.nodeService.hasAspect(node, ContentModel.ASPECT_THUMBNAILED) == false) + NodeRef thumbnail = AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() { - this.nodeService.addAspect(node, ContentModel.ASPECT_THUMBNAILED, null); - } - - // Get the name of the thumbnail and add to properties map - Map properties = new HashMap(2); - if (thumbnailName == null || thumbnailName.length() == 0) - { - thumbnailName = GUID.generate(); - } - else - { - String thumbnailFileName = generateThumbnailFileName(thumbnailName, mimetype); - properties.put(ContentModel.PROP_NAME, thumbnailFileName); - } - properties.put(ContentModel.PROP_THUMBNAIL_NAME, thumbnailName); - - // Add the name of the content property - properties.put(ContentModel.PROP_CONTENT_PROPERTY_NAME, contentProperty); - - // See if parent association details have been specified for the thumbnail - if (assocDetails == null) - { - // Create the thumbnail using the thumbnails child association - thumbnail = this.nodeService.createNode( - node, - ContentModel.ASSOC_THUMBNAILS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, thumbnailName), - ContentModel.TYPE_THUMBNAIL, - properties).getChildRef(); - } - else - { - // Create the thumbnail using the specified parent assoc details - thumbnail = this.nodeService.createNode( - assocDetails.getParent(), - assocDetails.getAssociationType(), - assocDetails.getAssociationName(), - ContentModel.TYPE_THUMBNAIL, - properties).getChildRef(); - - // Associate the new thumbnail to the source - this.nodeService.addChild( - node, - thumbnail, - ContentModel.ASSOC_THUMBNAILS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, thumbnailName)); - } - - // Get the content reader and writer for content nodes - ContentReader reader = this.contentService.getReader(node, contentProperty); - ContentWriter writer = this.contentService.getWriter(thumbnail, ContentModel.PROP_CONTENT, true); - writer.setMimetype(mimetype); - writer.setEncoding(reader.getEncoding()); - - // Catch the failure to create the thumbnail - if (this.contentService.isTransformable(reader, writer, transformationOptions) == false) - { - if (logger.isDebugEnabled() == true) + public NodeRef doWork() throws Exception { - logger.debug("Creating thumbnail: There is no transformer to generate the thumbnail required (node=" + node.toString() + "; contentProperty=" + contentProperty.toString() + "; mimetype=" + mimetype + ")"); + NodeRef thumbnail; + + // Apply the thumbnailed aspect to the node if it doesn't already have it + if (nodeService.hasAspect(node, ContentModel.ASPECT_THUMBNAILED) == false) + { + // Ensure we do not update the 'modifier' due to thumbnail addition + behaviourFilter.disableBehaviour(node, ContentModel.ASPECT_AUDITABLE); + try + { + nodeService.addAspect(node, ContentModel.ASPECT_THUMBNAILED, null); + } + finally + { + behaviourFilter.enableBehaviour(node, ContentModel.ASPECT_AUDITABLE); + } + } + + // Get the name of the thumbnail and add to properties map + String thumbName = thumbnailName; + Map properties = new HashMap(4); + if (thumbName == null || thumbName.length() == 0) + { + thumbName = GUID.generate(); + } + else + { + String thumbnailFileName = generateThumbnailFileName(thumbName, mimetype); + properties.put(ContentModel.PROP_NAME, thumbnailFileName); + } + properties.put(ContentModel.PROP_THUMBNAIL_NAME, thumbName); + + // Add the name of the content property + properties.put(ContentModel.PROP_CONTENT_PROPERTY_NAME, contentProperty); + + // See if parent association details have been specified for the thumbnail + if (assocDetails == null) + { + // Create the thumbnail using the thumbnails child association + thumbnail = nodeService.createNode( + node, + ContentModel.ASSOC_THUMBNAILS, + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, thumbName), + ContentModel.TYPE_THUMBNAIL, + properties).getChildRef(); + } + else + { + // Create the thumbnail using the specified parent assoc details + thumbnail = nodeService.createNode( + assocDetails.getParent(), + assocDetails.getAssociationType(), + assocDetails.getAssociationName(), + ContentModel.TYPE_THUMBNAIL, + properties).getChildRef(); + + // Associate the new thumbnail to the source + nodeService.addChild( + node, + thumbnail, + ContentModel.ASSOC_THUMBNAILS, + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, thumbName)); + } + + // Get the content reader and writer for content nodes + ContentReader reader = contentService.getReader(node, contentProperty); + ContentWriter writer = contentService.getWriter(thumbnail, ContentModel.PROP_CONTENT, true); + writer.setMimetype(mimetype); + writer.setEncoding(reader.getEncoding()); + + // Catch the failure to create the thumbnail + if (contentService.isTransformable(reader, writer, transformationOptions) == false) + { + if (logger.isDebugEnabled() == true) + { + logger.debug("Creating thumbnail: There is no transformer to generate the thumbnail required (node=" + node.toString() + "; contentProperty=" + contentProperty.toString() + "; mimetype=" + mimetype + ")"); + } + + // Throw exception indicating that the thumbnail could not be created + throw new ThumbnailException(MessageFormat.format(ERR_NO_CREATE, reader.getMimetype(), writer.getMimetype())); + } + else + { + // Do the thumbnail transformation + contentService.transform(reader, writer, transformationOptions); + } + + return thumbnail; } - - // Throw exception indicating that the thumbnail could not be created - throw new ThumbnailException(MessageFormat.format(ERR_NO_CREATE, reader.getMimetype(), writer.getMimetype())); - } - else - { - // Do the thumbnail transformation - this.contentService.transform(reader, writer, transformationOptions); - } + }, AuthenticationUtil.getSystemUserName()); // Return the created thumbnail return thumbnail; @@ -256,70 +307,82 @@ public class ThumbnailServiceImpl implements ThumbnailService /** * @see org.alfresco.service.cmr.thumbnail.ThumbnailService#updateThumbnail(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.TransformationOptions) */ - public void updateThumbnail(NodeRef thumbnail, TransformationOptions transformationOptions) + public void updateThumbnail(final NodeRef thumbnail, final TransformationOptions transformationOptions) { if (logger.isDebugEnabled() == true) { logger.debug("Updating thumbnail (thumbnail=" + thumbnail.toString() + ")"); } - // First check that we are dealing with a thumbnail - if (ContentModel.TYPE_THUMBNAIL.equals(this.nodeService.getType(thumbnail)) == true) - { - // Get the node that is the source of the thumbnail - NodeRef node = null; - List parents = this.nodeService.getParentAssocs(thumbnail, ContentModel.ASSOC_THUMBNAILS, RegexQNamePattern.MATCH_ALL); - if (parents.size() == 0) - { - if (logger.isDebugEnabled() == true) - { - logger.debug("Updating thumbnail: The thumbnails parent cannot be found (thumbnail=" + thumbnail.toString() + ")"); - } - - throw new ThumbnailException(ERR_NO_PARENT); - } - else - { - node = parents.get(0).getParentRef(); - } - - // Get the content property - QName contentProperty = (QName)this.nodeService.getProperty(thumbnail, ContentModel.PROP_CONTENT_PROPERTY_NAME); - - // Get the reader and writer - ContentReader reader = this.contentService.getReader(node, contentProperty); - ContentWriter writer = this.contentService.getWriter(thumbnail, ContentModel.PROP_CONTENT, true); - - // Set the basic detail of the transformation options - transformationOptions.setSourceNodeRef(node); - transformationOptions.setSourceContentProperty(contentProperty); - transformationOptions.setTargetNodeRef(thumbnail); - transformationOptions.setTargetContentProperty(ContentModel.PROP_CONTENT); - - // Catch the failure to create the thumbnail - if (this.contentService.isTransformable(reader, writer, transformationOptions) == false) - { - if (logger.isDebugEnabled() == true) - { - logger.debug("Updating thumbnail: there is not transformer to update the thumbnail with (thumbnail=" + thumbnail.toString() + ")"); - } - - // Throw exception indicating that the thumbnail could not be created - throw new ThumbnailException(MessageFormat.format(ERR_NO_CREATE, reader.getMimetype(), writer.getMimetype())); - } - else - { - // Do the thumbnail transformation - this.contentService.transform(reader, writer, transformationOptions); - } - } - else + if (!permissionService.hasPermission(thumbnail, PermissionService.READ_PROPERTIES).equals(AccessStatus.ALLOWED)) { - if (logger.isDebugEnabled() == true) - { - logger.debug("Updating thumbnail: cannot update a thumbnail node that isn't the correct thumbnail type (thumbnail=" + thumbnail.toString() + ")"); - } + throw new AccessDeniedException("Access Denied"); } + + AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() + { + public Object doWork() throws Exception + { + // First check that we are dealing with a thumbnail + if (ContentModel.TYPE_THUMBNAIL.equals(nodeService.getType(thumbnail)) == true) + { + // Get the node that is the source of the thumbnail + NodeRef node = null; + List parents = nodeService.getParentAssocs(thumbnail, ContentModel.ASSOC_THUMBNAILS, RegexQNamePattern.MATCH_ALL); + if (parents.size() == 0) + { + if (logger.isDebugEnabled() == true) + { + logger.debug("Updating thumbnail: The thumbnails parent cannot be found (thumbnail=" + thumbnail.toString() + ")"); + } + + throw new ThumbnailException(ERR_NO_PARENT); + } + else + { + node = parents.get(0).getParentRef(); + } + + // Get the content property + QName contentProperty = (QName)nodeService.getProperty(thumbnail, ContentModel.PROP_CONTENT_PROPERTY_NAME); + + // Get the reader and writer + ContentReader reader = contentService.getReader(node, contentProperty); + ContentWriter writer = contentService.getWriter(thumbnail, ContentModel.PROP_CONTENT, true); + + // Set the basic detail of the transformation options + transformationOptions.setSourceNodeRef(node); + transformationOptions.setSourceContentProperty(contentProperty); + transformationOptions.setTargetNodeRef(thumbnail); + transformationOptions.setTargetContentProperty(ContentModel.PROP_CONTENT); + + // Catch the failure to create the thumbnail + if (contentService.isTransformable(reader, writer, transformationOptions) == false) + { + if (logger.isDebugEnabled() == true) + { + logger.debug("Updating thumbnail: there is not transformer to update the thumbnail with (thumbnail=" + thumbnail.toString() + ")"); + } + + // Throw exception indicating that the thumbnail could not be created + throw new ThumbnailException(MessageFormat.format(ERR_NO_CREATE, reader.getMimetype(), writer.getMimetype())); + } + else + { + // Do the thumbnail transformation + contentService.transform(reader, writer, transformationOptions); + } + } + else + { + if (logger.isDebugEnabled() == true) + { + logger.debug("Updating thumbnail: cannot update a thumbnail node that isn't the correct thumbnail type (thumbnail=" + thumbnail.toString() + ")"); + } + } + return null; + } + }, AuthenticationUtil.getSystemUserName()); } /** @@ -341,6 +404,11 @@ public class ThumbnailServiceImpl implements ThumbnailService logger.debug("Getting thumbnail by name (nodeRef=" + node.toString() + "; contentProperty=" + contentProperty.toString() + "; thumbnailName=" + thumbnailName + ")"); } + if (!permissionService.hasPermission(node, PermissionService.READ_PROPERTIES).equals(AccessStatus.ALLOWED)) + { + throw new AccessDeniedException("Access Denied"); + } + // Check that the node has the thumbnailed aspect applied if (nodeService.hasAspect(node, ContentModel.ASPECT_THUMBNAILED) == true) { @@ -381,6 +449,11 @@ public class ThumbnailServiceImpl implements ThumbnailService logger.debug("Getting thumbnails (nodeRef=" + node.toString() + "; contentProperty=" + contentProperty.toString() + "; mimetype=" + mimetype + ")"); } + if (!permissionService.hasPermission(node, PermissionService.READ_PROPERTIES).equals(AccessStatus.ALLOWED)) + { + throw new AccessDeniedException("Access Denied"); + } + // Check that the node has the thumbnailed aspect applied if (nodeService.hasAspect(node, ContentModel.ASPECT_THUMBNAILED) == true) {