[MNT-24992] Add method to force renditions content hash code (#3288)

(cherry picked from commit 74380693d086fc99bd00f128f78e206725bc9780)
This commit is contained in:
Tiago Salvado 2025-03-28 23:17:58 +00:00 committed by Tiago Salvado
parent e059aa060a
commit fd6c651ece
5 changed files with 128 additions and 6 deletions

View File

@ -1539,7 +1539,7 @@
"filename": "repository/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionIntegrationTest.java", "filename": "repository/src/test/java/org/alfresco/repo/rendition2/AbstractRenditionIntegrationTest.java",
"hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8", "hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
"is_verified": false, "is_verified": false,
"line_number": 127, "line_number": 130,
"is_secret": false "is_secret": false
} }
], ],
@ -1888,5 +1888,5 @@
} }
] ]
}, },
"generated_at": "2024-10-09T09:32:52Z" "generated_at": "2025-03-27T23:45:41Z"
} }

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited * Copyright (C) 2005 - 2025 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
@ -124,4 +124,13 @@ public interface RenditionService2
* Indicates if renditions are enabled. Set using the {@code system.thumbnail.generate} value. * Indicates if renditions are enabled. Set using the {@code system.thumbnail.generate} value.
*/ */
boolean isEnabled(); boolean isEnabled();
/**
* This method forces the content hash code for every {@code sourceNodeRef} renditions.
*
* @param sourceNodeRef
* the source node to update renditions hash code
*/
@NotAuditable
void forceRenditionsContentHashCode(NodeRef sourceNodeRef);
} }

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited * Copyright (C) 2005 - 2025 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
@ -950,4 +950,35 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
} }
} }
@Override
public void forceRenditionsContentHashCode(NodeRef sourceNodeRef)
{
if (sourceNodeRef != null && nodeService.exists(sourceNodeRef))
{
List<ChildAssociationRef> renditions = getRenditionChildAssociations(sourceNodeRef);
if (renditions != null)
{
int sourceContentHashCode = getSourceContentHashCode(sourceNodeRef);
for (ChildAssociationRef rendition : renditions)
{
NodeRef renditionNode = rendition.getChildRef();
if (nodeService.hasAspect(renditionNode, RenditionModel.ASPECT_RENDITION2))
{
int renditionContentHashCode = getRenditionContentHashCode(renditionNode);
String renditionName = rendition.getQName().getLocalName();
if (sourceContentHashCode != renditionContentHashCode)
{
if (logger.isDebugEnabled())
{
logger.debug("Update content hash code for rendition " + renditionName + " of node "
+ sourceNodeRef);
}
nodeService.setProperty(renditionNode, PROP_RENDITION_CONTENT_HASH_CODE,
sourceContentHashCode);
}
}
}
}
}
}
} }

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited * Copyright (C) 2005 - 2025 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
@ -45,6 +45,7 @@ import org.alfresco.repo.thumbnail.ThumbnailRegistry;
import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.service.cmr.rendition.RenditionService; import org.alfresco.service.cmr.rendition.RenditionService;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.ContentWriter;
@ -52,6 +53,7 @@ import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.security.MutableAuthenticationService; import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.security.PersonService;
@ -128,6 +130,7 @@ public abstract class AbstractRenditionIntegrationTest extends BaseSpringTest
protected static final String ADMIN = "admin"; protected static final String ADMIN = "admin";
protected static final String DOC_LIB = "doclib"; protected static final String DOC_LIB = "doclib";
protected static final String PDF = "pdf";
private CronExpression origLocalTransCron; private CronExpression origLocalTransCron;
private CronExpression origRenditionCron; private CronExpression origRenditionCron;
@ -569,4 +572,28 @@ public abstract class AbstractRenditionIntegrationTest extends BaseSpringTest
return renditionContentHashCode; return renditionContentHashCode;
} }
/**
* Helper method which gets the content hash code from the supplied source node (the equivalent method from {@link RenditionService2Impl} is not public)
*
* @param sourceNodeRef
* the source node
*
* @return -1 in case of there is no content, otherwise, the actual content hash code otherwise
*/
protected int getSourceContentHashCode(NodeRef sourceNodeRef)
{
int hashCode = -1;
ContentData contentData = DefaultTypeConverter.INSTANCE.convert(ContentData.class, nodeService.getProperty(sourceNodeRef, PROP_CONTENT));
if (contentData != null)
{
// Originally we used the contentData URL, but that is not enough if the mimetype changes.
String contentString = contentData.getContentUrl() + contentData.getMimetype();
if (contentString != null)
{
hashCode = contentString.hashCode();
}
}
return hashCode;
}
} }

View File

@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited * Copyright (C) 2005 - 2025 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
@ -455,6 +455,61 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
assertEquals(TOTAL_NODES, countModifier(nodes, user1)); assertEquals(TOTAL_NODES, countModifier(nodes, user1));
} }
@Test
public void testForceRenditionsContentHashCode()
{
// Create a node
NodeRef sourceNodeRef = createSource(ADMIN, "quick.docx");
assertNotNull("Node not generated", sourceNodeRef);
// Get content hash code for the source node
int sourceNodeContentHashCode = getSourceContentHashCode(sourceNodeRef);
// Trigger the pdf rendition
render(ADMIN, sourceNodeRef, PDF);
NodeRef pdfRenditionNodeRef = waitForRendition(ADMIN, sourceNodeRef, PDF, true);
assertNotNull("pdf rendition was not generated", pdfRenditionNodeRef);
assertNotNull("pdf rendition was not generated", nodeService.getProperty(pdfRenditionNodeRef, PROP_CONTENT));
// Check the pdf rendition content hash code is valid
int pdfRenditionContentHashCode = getRenditionContentHashCode(pdfRenditionNodeRef);
assertEquals("pdf rendition content hash code is different from source node content hash code", sourceNodeContentHashCode, pdfRenditionContentHashCode);
// Trigger the doc lib rendition
render(ADMIN, sourceNodeRef, DOC_LIB);
NodeRef docLibRenditionNodeRef = waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, true);
assertNotNull("doc lib rendition was not generated", docLibRenditionNodeRef);
assertNotNull("doc lib rendition was not generated", nodeService.getProperty(docLibRenditionNodeRef, PROP_CONTENT));
// Check the doc lib rendition content hash code is valid
int docLibenditionContentHashCode = getRenditionContentHashCode(docLibRenditionNodeRef);
assertEquals("doc lib rendition content hash code is different from source node content hash code", sourceNodeContentHashCode, docLibenditionContentHashCode);
// Update the source node content
updateContent(ADMIN, sourceNodeRef, "quick.docx");
// Get source node content hash code after update
int sourceNodeContentHashCode2 = getSourceContentHashCode(sourceNodeRef);
// Check content hash code are different after content update
assertNotEquals("Source node content hash code is the same after content update", sourceNodeContentHashCode, sourceNodeContentHashCode2);
assertNotEquals("pdf rendition content hash code is the same after content update", sourceNodeContentHashCode2, pdfRenditionContentHashCode);
assertNotEquals("doc lib rendition content hash code is the same after content update", sourceNodeContentHashCode2, docLibenditionContentHashCode);
// Forces the content hash code for every source node renditions
AuthenticationUtil.runAs(() -> {
renditionService2.forceRenditionsContentHashCode(sourceNodeRef);
return null;
}, ADMIN);
// Check the renditions content hash code are now the same as the latest source node content hash code
int pdfRenditionContentHashCode2 = getRenditionContentHashCode(pdfRenditionNodeRef);
int docLibenditionContentHashCode2 = getRenditionContentHashCode(docLibRenditionNodeRef);
assertEquals("pdf rendition content hash code is different from latest source node content hash code", sourceNodeContentHashCode2, pdfRenditionContentHashCode2);
assertEquals("doc lib rendition content hash code is different from latest source node content hash code", sourceNodeContentHashCode2, docLibenditionContentHashCode2);
}
private int countModifier(List<NodeRef> nodes, String user) private int countModifier(List<NodeRef> nodes, String user)
{ {
int count = 0; int count = 0;