mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
REPO-4099 Change of mimetype to unsupported rendition hangs Share (#298)
An exception was being thrown if there was no supported rendition. In the case where a rendition already existed, RenditionService2 should have removed the content and hashcode on the rendition node and updated the source nodes thumbnailLastModified value. This is what happens if there is a transform failure when there is a rendition available. Also found that changing the mimetype nut not the content was not resulting in a new rendition as the hashcode did not include the mimetype.
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -38,7 +38,7 @@
|
||||
<dependency.alfresco-legacy-lucene.version>6.2</dependency.alfresco-legacy-lucene.version>
|
||||
<dependency.alfresco-core.version>7.5</dependency.alfresco-core.version>
|
||||
<dependency.alfresco-greenmail.version>6.1</dependency.alfresco-greenmail.version>
|
||||
<dependency.alfresco-data-model.version>8.22</dependency.alfresco-data-model.version>
|
||||
<dependency.alfresco-data-model.version>8.25</dependency.alfresco-data-model.version>
|
||||
<dependency.alfresco-jlan.version>7.1</dependency.alfresco-jlan.version>
|
||||
<dependency.alfresco-pdf-renderer.version>1.1</dependency.alfresco-pdf-renderer.version>
|
||||
<dependency.alfresco-hb-data-sender.version>1.0.9</dependency.alfresco-hb-data-sender.version>
|
||||
|
@@ -271,6 +271,7 @@ public class RenditionServiceImpl implements
|
||||
public ChildAssociationRef render(NodeRef sourceNode, RenditionDefinition definition)
|
||||
{
|
||||
checkSourceNodeForPreventionClass(sourceNode);
|
||||
log.debug("Original RenditionService render no callback START");
|
||||
|
||||
ChildAssociationRef result = executeRenditionAction(sourceNode, definition, false);
|
||||
|
||||
@@ -279,6 +280,7 @@ public class RenditionServiceImpl implements
|
||||
log.debug("Produced rendition " + result);
|
||||
}
|
||||
|
||||
log.debug("Original RenditionService render no callback END");
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -286,14 +288,14 @@ public class RenditionServiceImpl implements
|
||||
RenderCallback callback)
|
||||
{
|
||||
checkSourceNodeForPreventionClass(sourceNode);
|
||||
log.debug("Original RenditionService render callback START");
|
||||
|
||||
// The asynchronous render can't return a ChildAssociationRef as it is created
|
||||
// asynchronously after this method returns.
|
||||
definition.setCallback(callback);
|
||||
|
||||
executeRenditionAction(sourceNode, definition, true);
|
||||
|
||||
return;
|
||||
log.debug("Original RenditionService render callback END");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -128,7 +128,7 @@ public class LegacyLocalTransformClient extends AbstractTransformClient implemen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(NodeRef sourceNodeRef, RenditionDefinition2 renditionDefinition, String user, int sourceContentUrlHashCode)
|
||||
public void transform(NodeRef sourceNodeRef, RenditionDefinition2 renditionDefinition, String user, int sourceContentHashCode)
|
||||
{
|
||||
executorService.submit(() ->
|
||||
{
|
||||
@@ -155,7 +155,7 @@ public class LegacyLocalTransformClient extends AbstractTransformClient implemen
|
||||
contentService.transform(reader, writer, transformationOptions);
|
||||
|
||||
InputStream inputStream = writer.getReader().getContentInputStream();
|
||||
renditionService2.consume(sourceNodeRef, inputStream, renditionDefinition, sourceContentUrlHashCode);
|
||||
renditionService2.consume(sourceNodeRef, inputStream, renditionDefinition, sourceContentHashCode);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -164,7 +164,7 @@ public class LegacyLocalTransformClient extends AbstractTransformClient implemen
|
||||
String renditionName = renditionDefinition.getRenditionName();
|
||||
logger.debug("Rendition of "+renditionName+" failed", e);
|
||||
}
|
||||
renditionService2.failure(sourceNodeRef, renditionDefinition, sourceContentUrlHashCode);
|
||||
renditionService2.failure(sourceNodeRef, renditionDefinition, sourceContentHashCode);
|
||||
throw e;
|
||||
}
|
||||
return null;
|
||||
|
@@ -61,9 +61,10 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static org.alfresco.model.ContentModel.PROP_CONTENT;
|
||||
import static org.alfresco.model.RenditionModel.PROP_RENDITION_CONTENT_URL_HASH_CODE;
|
||||
import static org.alfresco.model.RenditionModel.PROP_RENDITION_CONTENT_HASH_CODE;
|
||||
import static org.alfresco.service.namespace.QName.createQName;
|
||||
|
||||
/**
|
||||
@@ -209,39 +210,68 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
||||
logger.debug("Request transform for rendition " + renditionName + " on " +sourceNodeRef);
|
||||
}
|
||||
|
||||
AtomicBoolean supported = new AtomicBoolean(true);
|
||||
ContentData contentData = (ContentData) nodeService.getProperty(sourceNodeRef, ContentModel.PROP_CONTENT);
|
||||
if (contentData != null && contentData.getContentUrl() != null)
|
||||
{
|
||||
String contentUrl = contentData.getContentUrl();
|
||||
String sourceMimetype = contentData.getMimetype();
|
||||
long size = contentData.getSize();
|
||||
transformClient.checkSupported(sourceNodeRef, renditionDefinition, sourceMimetype, size, contentUrl);
|
||||
try
|
||||
{
|
||||
transformClient.checkSupported(sourceNodeRef, renditionDefinition, sourceMimetype, size, contentUrl);
|
||||
}
|
||||
catch (UnsupportedOperationException e)
|
||||
{
|
||||
NodeRef renditionNode = getRenditionNode(sourceNodeRef, renditionName);
|
||||
if (renditionNode == null)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
supported.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
String user = AuthenticationUtil.getRunAsUser();
|
||||
RetryingTransactionHelper.RetryingTransactionCallback callback = () ->
|
||||
{
|
||||
// Avoid doing extra transforms that have already been done.
|
||||
int sourceContentUrlHashCode = getSourceContentUrlHashCode(sourceNodeRef);
|
||||
NodeRef renditionNode = getRenditionNode(sourceNodeRef, renditionName);
|
||||
int renditionContentUrlHashCode = getRenditionContentUrlHashCode(renditionNode);
|
||||
if (renditionContentUrlHashCode == sourceContentUrlHashCode)
|
||||
{
|
||||
throw new IllegalStateException("The rendition " + renditionName + " has already been created.");
|
||||
}
|
||||
|
||||
// If source node has content
|
||||
if (sourceContentUrlHashCode != SOURCE_HAS_NO_CONTENT)
|
||||
{
|
||||
transformClient.transform(sourceNodeRef, renditionDefinition, user, sourceContentUrlHashCode);
|
||||
}
|
||||
else
|
||||
int sourceContentHashCode = getSourceContentHashCode(sourceNodeRef);
|
||||
if (!supported.get())
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Rendition of "+renditionName+" had no content.");
|
||||
logger.debug("Rendition of " + renditionName + " is no longer supported. " +
|
||||
"The mimetype might have changed or the content is now too big.");
|
||||
}
|
||||
failure(sourceNodeRef, renditionDefinition, sourceContentHashCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Avoid doing extra transforms that have already been done.
|
||||
NodeRef renditionNode = getRenditionNode(sourceNodeRef, renditionName);
|
||||
int renditionContentHashCode = getRenditionContentHashCode(renditionNode);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Render: Source " + sourceContentHashCode + " rendition " + renditionContentHashCode+ " hashCodes");
|
||||
}
|
||||
if (renditionContentHashCode == sourceContentHashCode)
|
||||
{
|
||||
throw new IllegalStateException("The rendition " + renditionName + " has already been created.");
|
||||
}
|
||||
|
||||
// If source node has content
|
||||
if (sourceContentHashCode != SOURCE_HAS_NO_CONTENT)
|
||||
{
|
||||
transformClient.transform(sourceNodeRef, renditionDefinition, user, sourceContentHashCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Rendition of " + renditionName + " had no content.");
|
||||
}
|
||||
failure(sourceNodeRef, renditionDefinition, sourceContentHashCode);
|
||||
}
|
||||
failure(sourceNodeRef, renditionDefinition, sourceContentUrlHashCode);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -254,13 +284,13 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
||||
}
|
||||
}
|
||||
|
||||
public void failure(NodeRef sourceNodeRef, RenditionDefinition2 renditionDefinition, int transformContentUrlHashCode)
|
||||
public void failure(NodeRef sourceNodeRef, RenditionDefinition2 renditionDefinition, int transformContentHashCode)
|
||||
{
|
||||
// The original transaction may have already have failed
|
||||
AuthenticationUtil.runAsSystem((AuthenticationUtil.RunAsWork<Void>) () ->
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(() ->
|
||||
{
|
||||
consume(sourceNodeRef, null, renditionDefinition, transformContentUrlHashCode);
|
||||
consume(sourceNodeRef, null, renditionDefinition, transformContentHashCode);
|
||||
return null;
|
||||
}, false, true));
|
||||
}
|
||||
@@ -271,12 +301,15 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
||||
* If the transformInputStream is null, this is taken to be a transform failure.
|
||||
*/
|
||||
public void consume(NodeRef sourceNodeRef, InputStream transformInputStream, RenditionDefinition2 renditionDefinition,
|
||||
int transformContentUrlHashCode)
|
||||
int transformContentHashCode)
|
||||
{
|
||||
String renditionName = renditionDefinition.getRenditionName();
|
||||
int sourceContentUrlHashCode = getSourceContentUrlHashCode(sourceNodeRef);
|
||||
|
||||
if (transformContentUrlHashCode != sourceContentUrlHashCode)
|
||||
int sourceContentHashCode = getSourceContentHashCode(sourceNodeRef);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Consume: Source " + sourceContentHashCode + " and transform's source " + transformContentHashCode+" hashcodes");
|
||||
}
|
||||
if (transformContentHashCode != sourceContentHashCode)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
@@ -321,7 +354,11 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
||||
logger.debug("Added rendition2 aspect to rendition " + renditionName + " on " + sourceNodeRef);
|
||||
}
|
||||
}
|
||||
nodeService.setProperty(renditionNode, RenditionModel.PROP_RENDITION_CONTENT_URL_HASH_CODE, transformContentUrlHashCode);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Set rendition hashcode " + transformContentHashCode + " and ThumbnailLastModified for " + renditionName);
|
||||
}
|
||||
nodeService.setProperty(renditionNode, RenditionModel.PROP_RENDITION_CONTENT_HASH_CODE, transformContentHashCode);
|
||||
setThumbnailLastModified(sourceNodeRef, renditionName);
|
||||
|
||||
if (transformInputStream != null)
|
||||
@@ -348,6 +385,11 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
||||
if (content != null)
|
||||
{
|
||||
nodeService.removeProperty(renditionNode, PROP_CONTENT);
|
||||
nodeService.removeProperty(renditionNode, PROP_RENDITION_CONTENT_HASH_CODE);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Cleared rendition content and hashcode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,16 +487,17 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
||||
* Returns the hash code of the source node's content url. As transformations may be returned in a different
|
||||
* sequences to which they were requested, this is used work out if a rendition should be replaced.
|
||||
*/
|
||||
private int getSourceContentUrlHashCode(NodeRef sourceNodeRef)
|
||||
private int getSourceContentHashCode(NodeRef sourceNodeRef)
|
||||
{
|
||||
int hashCode = SOURCE_HAS_NO_CONTENT;
|
||||
ContentData contentData = DefaultTypeConverter.INSTANCE.convert(ContentData.class, nodeService.getProperty(sourceNodeRef, PROP_CONTENT));
|
||||
if (contentData != null)
|
||||
{
|
||||
String contentUrl = contentData.getContentUrl();
|
||||
if (contentUrl != null)
|
||||
// Originally we used the contentData URL, but that is not enough if the mimetype changes.
|
||||
String contentString = contentData.toString();
|
||||
if (contentString != null)
|
||||
{
|
||||
hashCode = contentUrl.hashCode();
|
||||
hashCode = contentString.hashCode();
|
||||
}
|
||||
}
|
||||
return hashCode;
|
||||
@@ -463,13 +506,19 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
||||
/**
|
||||
* Returns the hash code of source node's content url on the rendition node (node may be null) if it does not exist.
|
||||
* Used work out if a rendition should be replaced. {@code -2} is returned if the rendition does not exist or was
|
||||
* not created by RenditionService2.
|
||||
* not created by RenditionService2. {@code -1} is returned if there was no source content or the rendition failed.
|
||||
*/
|
||||
private int getRenditionContentUrlHashCode(NodeRef renditionNode)
|
||||
private int getRenditionContentHashCode(NodeRef renditionNode)
|
||||
{
|
||||
return renditionNode == null || !nodeService.hasAspect(renditionNode, RenditionModel.ASPECT_RENDITION2)
|
||||
? RENDITION2_DOES_NOT_EXIST
|
||||
: (int)nodeService.getProperty(renditionNode, PROP_RENDITION_CONTENT_URL_HASH_CODE);
|
||||
if ( renditionNode == null || !nodeService.hasAspect(renditionNode, RenditionModel.ASPECT_RENDITION2))
|
||||
{
|
||||
return RENDITION2_DOES_NOT_EXIST;
|
||||
}
|
||||
|
||||
Serializable hashCode = nodeService.getProperty(renditionNode, PROP_RENDITION_CONTENT_HASH_CODE);
|
||||
return hashCode == null
|
||||
? SOURCE_HAS_NO_CONTENT
|
||||
: (int)hashCode;
|
||||
}
|
||||
|
||||
private NodeRef getRenditionNode(NodeRef sourceNodeRef, String renditionName)
|
||||
@@ -567,7 +616,7 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
||||
|
||||
/**
|
||||
* Indicates if the rendition is available. Failed renditions (there was an error) don't have a contentUrl
|
||||
* and out of date renditions or those still being created don't have a matching contentUrlHashCode.
|
||||
* and out of date renditions or those still being created don't have a matching contentHashCode.
|
||||
*/
|
||||
public boolean isRenditionAvailable(NodeRef sourceNodeRef, NodeRef renditionNode)
|
||||
{
|
||||
@@ -581,9 +630,13 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
||||
}
|
||||
else
|
||||
{
|
||||
int sourceContentUrlHashCode = getSourceContentUrlHashCode(sourceNodeRef);
|
||||
int renditionContentUrlHashCode = getRenditionContentUrlHashCode(renditionNode);
|
||||
if (sourceContentUrlHashCode != renditionContentUrlHashCode)
|
||||
int sourceContentHashCode = getSourceContentHashCode(sourceNodeRef);
|
||||
int renditionContentHashCode = getRenditionContentHashCode(renditionNode);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("isRenditionAvailable source " + sourceContentHashCode + " and rendition " + renditionContentHashCode+" hashcodes");
|
||||
}
|
||||
if (sourceContentHashCode != renditionContentHashCode)
|
||||
{
|
||||
available = false;
|
||||
}
|
||||
|
@@ -62,15 +62,15 @@ public class SwitchingTransformClient implements TransformClient
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(NodeRef sourceNodeRef, RenditionDefinition2 renditionDefinition, String user, int sourceContentUrlHashCode)
|
||||
public void transform(NodeRef sourceNodeRef, RenditionDefinition2 renditionDefinition, String user, int sourceContentHashCode)
|
||||
{
|
||||
if (usePrimary.get())
|
||||
{
|
||||
primary.transform(sourceNodeRef, renditionDefinition, user, sourceContentUrlHashCode);
|
||||
primary.transform(sourceNodeRef, renditionDefinition, user, sourceContentHashCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
secondary.transform(sourceNodeRef, renditionDefinition, user, sourceContentUrlHashCode);
|
||||
secondary.transform(sourceNodeRef, renditionDefinition, user, sourceContentHashCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -53,7 +53,7 @@ public interface TransformClient
|
||||
* @param sourceNodeRef the source node
|
||||
* @param renditionDefinition which rendition to perform
|
||||
* @param user that requested the transform.
|
||||
* @param sourceContentUrlHashCode the hash code of the source node's content URL. Used to check the transform result
|
||||
* @param sourceContentHashCode the hash code of the source node's content URL. Used to check the transform result
|
||||
*/
|
||||
void transform(NodeRef sourceNodeRef, RenditionDefinition2 renditionDefinition, String user, int sourceContentUrlHashCode);
|
||||
void transform(NodeRef sourceNodeRef, RenditionDefinition2 renditionDefinition, String user, int sourceContentHashCode);
|
||||
}
|
||||
|
@@ -153,7 +153,7 @@ public abstract class AbstractRenditionIntegrationTest extends BaseSpringTest
|
||||
{
|
||||
NodeRef sourceNodeRef = createSource(ADMIN, testFileName);
|
||||
render(ADMIN, sourceNodeRef, renditionName);
|
||||
waitForRendition(ADMIN, sourceNodeRef, renditionName);
|
||||
waitForRendition(ADMIN, sourceNodeRef, renditionName, true);
|
||||
if (!expectedToPass)
|
||||
{
|
||||
fail("The " + renditionName + " rendition should NOT be supported for " + testFileName);
|
||||
@@ -241,11 +241,11 @@ public abstract class AbstractRenditionIntegrationTest extends BaseSpringTest
|
||||
}
|
||||
|
||||
// As a given user waitForRendition for a rendition to appear. Creates new transactions to do this.
|
||||
protected NodeRef waitForRendition(String user, NodeRef sourceNodeRef, String renditionName) throws AssertionFailedError
|
||||
protected NodeRef waitForRendition(String user, NodeRef sourceNodeRef, String renditionName, boolean shouldExist) throws AssertionFailedError
|
||||
{
|
||||
try
|
||||
{
|
||||
return AuthenticationUtil.runAs(() -> waitForRendition(sourceNodeRef, renditionName), user);
|
||||
return AuthenticationUtil.runAs(() -> waitForRendition(sourceNodeRef, renditionName, shouldExist), user);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
@@ -259,7 +259,7 @@ public abstract class AbstractRenditionIntegrationTest extends BaseSpringTest
|
||||
}
|
||||
|
||||
// As the current user waitForRendition for a rendition to appear. Creates new transactions to do this.
|
||||
private NodeRef waitForRendition(NodeRef sourceNodeRef, String renditionName) throws InterruptedException
|
||||
private NodeRef waitForRendition(NodeRef sourceNodeRef, String renditionName, boolean shouldExist) throws InterruptedException
|
||||
{
|
||||
long maxMillis = 10000;
|
||||
ChildAssociationRef assoc = null;
|
||||
@@ -275,8 +275,16 @@ public abstract class AbstractRenditionIntegrationTest extends BaseSpringTest
|
||||
logger.debug("RenditionService2.getRenditionByName(...) sleep "+i);
|
||||
sleep(1000);
|
||||
}
|
||||
assertNotNull("Rendition " + renditionName + " failed", assoc);
|
||||
return assoc.getChildRef();
|
||||
if (shouldExist)
|
||||
{
|
||||
assertNotNull("Rendition " + renditionName + " failed", assoc);
|
||||
return assoc.getChildRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
assertNull("Rendition " + renditionName + " did not fail", assoc);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected String getTestFileName(String sourceMimetype) throws FileNotFoundException
|
||||
|
@@ -137,10 +137,10 @@ public class LegacyLocalTransformClientIntegrationTest extends AbstractRendition
|
||||
// split into separate transactions as the client is async
|
||||
NodeRef sourceNode = transactionService.getRetryingTransactionHelper().doInTransaction(() ->
|
||||
createContentNodeFromQuickFile(testFileName));
|
||||
int sourceContentUrlHash = DefaultTypeConverter.INSTANCE.convert(
|
||||
int sourceContentHashCode = DefaultTypeConverter.INSTANCE.convert(
|
||||
ContentData.class,
|
||||
nodeService.getProperty(sourceNode, PROP_CONTENT))
|
||||
.getContentUrl().hashCode();
|
||||
.toString().hashCode();
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(() ->
|
||||
{
|
||||
RenditionDefinition2 renditionDefinition =
|
||||
@@ -149,7 +149,7 @@ public class LegacyLocalTransformClientIntegrationTest extends AbstractRendition
|
||||
sourceNode,
|
||||
renditionDefinition,
|
||||
AuthenticationUtil.getAdminUserName(),
|
||||
sourceContentUrlHash);
|
||||
sourceContentHashCode);
|
||||
return null;
|
||||
});
|
||||
ChildAssociationRef childAssociationRef = null;
|
||||
|
@@ -25,36 +25,23 @@
|
||||
*/
|
||||
package org.alfresco.repo.rendition2;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.model.RenditionModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.repo.thumbnail.ThumbnailRegistry;
|
||||
import org.alfresco.service.cmr.rendition.RenditionService;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.List;
|
||||
|
||||
import static java.lang.Thread.sleep;
|
||||
import static org.alfresco.model.ContentModel.PROP_CONTENT;
|
||||
import static org.alfresco.repo.content.MimetypeMap.EXTENSION_BINARY;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link RenditionService2}
|
||||
@@ -148,7 +135,7 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
|
||||
{
|
||||
NodeRef sourceNodeRef = createSource(ADMIN, "quick.jpg");
|
||||
render(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
waitForRendition(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -156,12 +143,13 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
|
||||
{
|
||||
NodeRef sourceNodeRef = createSource(ADMIN, "quick.jpg");
|
||||
render(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
waitForRendition(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, true);
|
||||
|
||||
clearContent(ADMIN, sourceNodeRef);
|
||||
render(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
ChildAssociationRef assoc = AuthenticationUtil.runAs(() ->
|
||||
renditionService2.getRenditionByName(sourceNodeRef, DOC_LIB), ADMIN);
|
||||
waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, false);
|
||||
assertNull("There should be no rendition as there was no content", assoc);
|
||||
}
|
||||
|
||||
@@ -170,16 +158,35 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
|
||||
{
|
||||
NodeRef sourceNodeRef = createSource(ADMIN, "quick.jpg");
|
||||
render(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
waitForRendition(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
NodeRef rendition1 = waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, true);
|
||||
ContentData contentData1 = DefaultTypeConverter.INSTANCE.convert(ContentData.class, nodeService.getProperty(rendition1, PROP_CONTENT));
|
||||
|
||||
updateContent(ADMIN, sourceNodeRef, "quick.png");
|
||||
render(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
NodeRef rendition2 = waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, true);
|
||||
ContentData contentData2 = DefaultTypeConverter.INSTANCE.convert(ContentData.class, nodeService.getProperty(rendition2, PROP_CONTENT));
|
||||
|
||||
assertEquals("The rendition node should not change", rendition1, rendition2);
|
||||
assertNotEquals("The content should have change", contentData1.toString(), contentData2.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void changedSourceFromNull()
|
||||
{
|
||||
NodeRef sourceNodeRef = createSource(ADMIN, "quick.jpg");
|
||||
render(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, true);
|
||||
|
||||
clearContent(ADMIN, sourceNodeRef);
|
||||
render(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
ChildAssociationRef assoc = AuthenticationUtil.runAs(() ->
|
||||
renditionService2.getRenditionByName(sourceNodeRef, DOC_LIB), ADMIN);
|
||||
waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, false);
|
||||
assertNull("There should be no rendition as there was no content", assoc);
|
||||
|
||||
updateContent(ADMIN, sourceNodeRef, "quick.png");
|
||||
waitForRendition(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
render(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -188,7 +195,7 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
|
||||
String userName = createRandomUser();
|
||||
NodeRef sourceNodeRef = createSource(userName, "quick.jpg");
|
||||
render(userName, sourceNodeRef, DOC_LIB);
|
||||
NodeRef renditionNodeRef = waitForRendition(userName, sourceNodeRef, DOC_LIB);
|
||||
NodeRef renditionNodeRef = waitForRendition(userName, sourceNodeRef, DOC_LIB, true);
|
||||
assertNotNull("The rendition was not generated for non-admin user", renditionNodeRef);
|
||||
}
|
||||
|
||||
@@ -204,9 +211,9 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
|
||||
return null;
|
||||
});
|
||||
render(ownerUserName, sourceNodeRef, DOC_LIB);
|
||||
NodeRef renditionNodeRef = waitForRendition(ownerUserName, sourceNodeRef, DOC_LIB);
|
||||
NodeRef renditionNodeRef = waitForRendition(ownerUserName, sourceNodeRef, DOC_LIB, true);
|
||||
assertNotNull("The rendition is not visible for owner of source node", renditionNodeRef);
|
||||
renditionNodeRef = waitForRendition(otherUserName, sourceNodeRef, DOC_LIB);
|
||||
renditionNodeRef = waitForRendition(otherUserName, sourceNodeRef, DOC_LIB, true);
|
||||
assertNotNull("The rendition is not visible for non-owner user with read permissions", renditionNodeRef);
|
||||
assertEquals("The creator of the rendition is not correct",
|
||||
ownerUserName, nodeService.getProperty(sourceNodeRef, ContentModel.PROP_CREATOR));
|
||||
@@ -224,9 +231,9 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
|
||||
return null;
|
||||
});
|
||||
render(otherUserName, sourceNodeRef, DOC_LIB);
|
||||
NodeRef renditionNodeRef = waitForRendition(ownerUserName, sourceNodeRef, DOC_LIB);
|
||||
NodeRef renditionNodeRef = waitForRendition(ownerUserName, sourceNodeRef, DOC_LIB, true);
|
||||
assertNotNull("The rendition is not visible for owner of source node", renditionNodeRef);
|
||||
renditionNodeRef = waitForRendition(otherUserName, sourceNodeRef, DOC_LIB);
|
||||
renditionNodeRef = waitForRendition(otherUserName, sourceNodeRef, DOC_LIB, true);
|
||||
assertNotNull("The rendition is not visible for owner of rendition node", renditionNodeRef);
|
||||
assertEquals("The creator of the rendition is not correct",
|
||||
ownerUserName, nodeService.getProperty(sourceNodeRef, ContentModel.PROP_CREATOR));
|
||||
@@ -246,7 +253,7 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
|
||||
});
|
||||
try
|
||||
{
|
||||
waitForRendition(noPermissionsUser, sourceNodeRef, DOC_LIB);
|
||||
waitForRendition(noPermissionsUser, sourceNodeRef, DOC_LIB, true);
|
||||
fail("The rendition should not be visible for user with no permissions");
|
||||
}
|
||||
catch (AccessDeniedException ade)
|
||||
@@ -272,7 +279,7 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
|
||||
AuthenticationUtil.runAs(() -> nodeService.hasAspect(oldRendition, RenditionModel.ASPECT_RENDITION2), ownerUserName));
|
||||
|
||||
updateContent(ownerUserName, sourceNodeRef, "quick.png");
|
||||
NodeRef newRendition = waitForRendition(ownerUserName, sourceNodeRef, DOC_LIB);
|
||||
NodeRef newRendition = waitForRendition(ownerUserName, sourceNodeRef, DOC_LIB, true);
|
||||
assertNotNull("The rendition should be reported via RenditionService2", newRendition);
|
||||
Thread.sleep(200);
|
||||
boolean hasRenditionedAspect = false;
|
||||
@@ -307,7 +314,7 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
|
||||
.doInTransaction(() ->
|
||||
AuthenticationUtil.runAs(() ->
|
||||
renditionService.render(sourceNodeRef, doclibRendDefQName), ADMIN));
|
||||
assertNotNull("The old renditions service did not render", waitForRendition(ADMIN, sourceNodeRef, DOC_LIB));
|
||||
assertNotNull("The old renditions service did not render", waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, true));
|
||||
List<String> lastThumbnailModification = transactionService.getRetryingTransactionHelper()
|
||||
.doInTransaction(() ->
|
||||
AuthenticationUtil.runAs(() ->
|
||||
@@ -349,14 +356,14 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
|
||||
{
|
||||
NodeRef sourceNodeRef = createSource(ADMIN, "quick.jpg");
|
||||
render(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
waitForRendition(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, true);
|
||||
|
||||
renditionService2.setEnabled(false);
|
||||
try
|
||||
{
|
||||
updateContent(ADMIN, sourceNodeRef, "quick.png");
|
||||
Thread.sleep(200);
|
||||
NodeRef renditionNodeRef = waitForRendition(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
NodeRef renditionNodeRef = waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, true);
|
||||
boolean hasRendition2Aspect = true;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
@@ -394,12 +401,12 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
|
||||
.doInTransaction(() ->
|
||||
AuthenticationUtil.runAs(() ->
|
||||
renditionService.render(sourceNodeRef, doclibRendDefQName), ADMIN));
|
||||
waitForRendition(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, true);
|
||||
|
||||
renditionService2.setEnabled(true);
|
||||
|
||||
updateContent(ADMIN, sourceNodeRef, "quick.png");
|
||||
NodeRef renditionNodeRef = waitForRendition(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
NodeRef renditionNodeRef = waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, true);
|
||||
boolean hasAspect = nodeService.hasAspect(renditionNodeRef, RenditionModel.ASPECT_RENDITION2);
|
||||
assertFalse("Should have switched to the old rendition service", hasAspect);
|
||||
}
|
||||
@@ -419,7 +426,7 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
|
||||
String ownerUserName = createRandomUser();
|
||||
NodeRef sourceNodeRef = createSource(ownerUserName, "quick.jpg");
|
||||
render(ownerUserName, sourceNodeRef, DOC_LIB);
|
||||
NodeRef newRendition = waitForRendition(ownerUserName, sourceNodeRef, DOC_LIB);
|
||||
NodeRef newRendition = waitForRendition(ownerUserName, sourceNodeRef, DOC_LIB, true);
|
||||
boolean hasRendition2Aspect = AuthenticationUtil.runAs(() -> nodeService.hasAspect(newRendition, RenditionModel.ASPECT_RENDITION2), ownerUserName);
|
||||
assertTrue("The source should have the old renditioned aspect",
|
||||
AuthenticationUtil.runAs(() -> nodeService.hasAspect(sourceNodeRef, RenditionModel.ASPECT_RENDITIONED), ownerUserName));
|
||||
@@ -428,7 +435,7 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
|
||||
{
|
||||
renditionService2.setEnabled(false);
|
||||
updateContent(ownerUserName, sourceNodeRef, "quick.png");
|
||||
NodeRef oldRendition = waitForRendition(ownerUserName, sourceNodeRef, DOC_LIB);
|
||||
NodeRef oldRendition = waitForRendition(ownerUserName, sourceNodeRef, DOC_LIB, true);
|
||||
Thread.sleep(200);
|
||||
hasRendition2Aspect = false;
|
||||
for (int i = 0; i < 5; i++)
|
||||
@@ -467,12 +474,12 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
|
||||
.doInTransaction(() ->
|
||||
AuthenticationUtil.runAs(() ->
|
||||
renditionService.render(sourceNodeRef, doclibRendDefQName), ADMIN));
|
||||
waitForRendition(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, true);
|
||||
|
||||
renditionService2.setEnabled(true);
|
||||
render(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
Thread.sleep(200);
|
||||
NodeRef renditionNodeRef = waitForRendition(ADMIN, sourceNodeRef, DOC_LIB);
|
||||
NodeRef renditionNodeRef = waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, true);
|
||||
boolean hasRendition2Aspect = false;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
|
@@ -26,17 +26,6 @@
|
||||
|
||||
package org.alfresco.repo.thumbnail;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.content.transform.magick.ImageResizeOptions;
|
||||
@@ -45,9 +34,9 @@ import org.alfresco.repo.rendition.MockedTestServiceRegistry;
|
||||
import org.alfresco.repo.rendition.RenditionServiceImpl;
|
||||
import org.alfresco.repo.rendition.executer.AbstractRenderingEngine;
|
||||
import org.alfresco.repo.rendition.executer.ImageRenderingEngine;
|
||||
import org.alfresco.repo.rendition2.RenditionService2Impl;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.TransactionServiceImpl;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.rendition.RenditionDefinition;
|
||||
@@ -67,6 +56,18 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Thumbnail service implementation unit test
|
||||
*
|
||||
@@ -79,6 +80,7 @@ public class ThumbnailServiceImplParameterTest
|
||||
{
|
||||
// Mocked services.
|
||||
private ActionService mockActionService = mock(ActionService.class);
|
||||
private RenditionService2Impl mockRenditionService2 = mock(RenditionService2Impl.class);
|
||||
|
||||
// Real services - backed by mocked services.
|
||||
private RenditionServiceImpl renditionService;
|
||||
@@ -103,6 +105,8 @@ public class ThumbnailServiceImplParameterTest
|
||||
|
||||
renditionService.setActionService(mockActionService);
|
||||
renditionService.setServiceRegistry(new MockedTestServiceRegistry());
|
||||
renditionService.setRenditionService2(mockRenditionService2);
|
||||
when(mockRenditionService2.isCreatedByRenditionService2(any(), any())).thenReturn(false);
|
||||
|
||||
ThumbnailServiceImpl thumbs = new ThumbnailServiceImpl()
|
||||
{
|
||||
|
Reference in New Issue
Block a user