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:
alandavis
2018-12-13 16:34:31 +00:00
committed by GitHub
parent d3a00e3f91
commit 544e40ec54
10 changed files with 186 additions and 112 deletions

View File

@@ -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>

View File

@@ -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");
}
/*

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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++)
{

View File

@@ -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()
{