diff --git a/src/main/java/biz/netcentric/filevault/validator/AemReplicationMetadataValidator.java b/src/main/java/biz/netcentric/filevault/validator/AemReplicationMetadataValidator.java index b9831d0..9cd8152 100644 --- a/src/main/java/biz/netcentric/filevault/validator/AemReplicationMetadataValidator.java +++ b/src/main/java/biz/netcentric/filevault/validator/AemReplicationMetadataValidator.java @@ -22,7 +22,6 @@ import javax.jcr.RepositoryException; -import org.apache.jackrabbit.spi.Name; import org.apache.jackrabbit.util.Text; import org.apache.jackrabbit.vault.util.DocViewNode2; import org.apache.jackrabbit.vault.validation.spi.DocumentViewXmlValidator; @@ -34,11 +33,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.day.cq.wcm.api.NameConstants; - public class AemReplicationMetadataValidator implements DocumentViewXmlValidator { - private static final Name NAME_JCR_CONTENT = org.apache.jackrabbit.spi.commons.name.NameConstants.JCR_CONTENT; private static final Logger LOGGER = LoggerFactory.getLogger(AemReplicationMetadataValidator.class); private final @NotNull ValidationMessageSeverity validationMessageSeverity; @@ -72,7 +68,7 @@ private Optional getNodeMetadata(@NotNull String nodePath, @NotNul NodeMetadata currentMetadata = relevantNodeMetadata.peek(); if (currentMetadata != null && ( nodePath.equals(currentMetadata.getPath()) || - nodePath.equals(currentMetadata.getPath() + "/" + NameConstants.NN_CONTENT))) { + nodePath.equals(currentMetadata.getPath() + "/" + NameConstants.QUALIFIED_NAME_JCR_CONTENT))) { return Optional.of(currentMetadata); } // first check includes, then excludes, first match returning relevant metadata wins @@ -103,9 +99,9 @@ private Optional getNodeMetadata(boolean isExclude, @NotNull Strin } else { String actualPrimaryType = node.getPrimaryType().orElse(""); NodeMetadata currentMetadata; - if (NameConstants.NT_PAGE.equals(actualPrimaryType) || NameConstants.NT_TEMPLATE.equals(actualPrimaryType)) { + if (NameConstants.NT_CQ_PAGE.equals(actualPrimaryType) || NameConstants.NT_CQ_TEMPLATE.equals(actualPrimaryType)) { LOGGER.debug("Waiting for jcr:content below {}", nodePath); - currentMetadata = new NodeMetadata(isExclude, nodePath + "/" + NameConstants.NN_CONTENT, true, typeSettings.getComparisonDate()); + currentMetadata = new NodeMetadata(isExclude, nodePath + "/" + NameConstants.QUALIFIED_NAME_JCR_CONTENT, true, typeSettings.getComparisonDate()); relevantNodeMetadata.add(currentMetadata); return Optional.empty(); } else { @@ -136,7 +132,7 @@ public Collection validate(@NotNull DocViewNode2 node, @NotNu return Collections.singletonList(new ValidationMessage(validationMessageSeverity, "Invalid last modification date found", e)); } currentMetadata.captureReplicationMetadata(node, agentNames); - } else if (node.getName().equals(NAME_JCR_CONTENT)) { + } else if (node.getName().equals(NameConstants.JCR_CONTENT)) { // capture replication metadata in jcr:content child node String parentNodePath = Text.getRelativeParent(nodeContext.getNodePath(), 1); if (currentMetadata.getPath().equals(parentNodePath)) { diff --git a/src/main/java/biz/netcentric/filevault/validator/NameConstants.java b/src/main/java/biz/netcentric/filevault/validator/NameConstants.java index 93658c3..df549d7 100644 --- a/src/main/java/biz/netcentric/filevault/validator/NameConstants.java +++ b/src/main/java/biz/netcentric/filevault/validator/NameConstants.java @@ -34,11 +34,16 @@ private NameConstants() { public static final String CQ_NAMESPACE_URI = "http://www.day.com/jcr/cq/1.0"; // no constant defined in https://developer.adobe.com/experience-manager/reference-materials/6-5/javadoc/constant-values.html public static final @NotNull Name SLING_RESOURCETYPE = NAME_FACTORY.create(JcrResourceConstants.SLING_NAMESPACE_URI, SlingConstants.PROPERTY_RESOURCE_TYPE); - public static final @NotNull String NT_CQ_PAGE_CONTENT = "cq:PageContent"; - public static final @NotNull Name CQ_LAST_MODIFIED = NAME_FACTORY.create(CQ_NAMESPACE_URI, "lastModified"); public static final @NotNull Name CQ_CREATED = NAME_FACTORY.create(CQ_NAMESPACE_URI, "created"); public static final @NotNull Name JCR_LASTMODIFIED = org.apache.jackrabbit.spi.commons.name.NameConstants.JCR_LASTMODIFIED; public static final @NotNull Name JCR_CREATED = org.apache.jackrabbit.spi.commons.name.NameConstants.JCR_CREATED; + public static final @NotNull Name JCR_CONTENT = org.apache.jackrabbit.spi.commons.name.NameConstants.JCR_CONTENT; + + /* the following are not names but their lexical form (qualified names) */ + public static final @NotNull String NT_CQ_PAGE_CONTENT = "cq:PageContent"; + public static final @NotNull String NT_CQ_PAGE = com.day.cq.wcm.api.NameConstants.NT_PAGE; + public static final @NotNull String NT_CQ_TEMPLATE = com.day.cq.wcm.api.NameConstants.NT_TEMPLATE; + public static final @NotNull String QUALIFIED_NAME_JCR_CONTENT = com.day.cq.wcm.api.NameConstants.NN_CONTENT; } diff --git a/src/main/java/biz/netcentric/filevault/validator/NodeMetadata.java b/src/main/java/biz/netcentric/filevault/validator/NodeMetadata.java index f054101..20767ad 100644 --- a/src/main/java/biz/netcentric/filevault/validator/NodeMetadata.java +++ b/src/main/java/biz/netcentric/filevault/validator/NodeMetadata.java @@ -82,9 +82,9 @@ public void captureComparisonDate(@NotNull DocViewNode2 node) throws IllegalStat } /** - * This never fails until actually dereferencing data - * @param node - * @param agentNames + * This method never fails until actually dereferencing data in another method. + * @param node the node to capture replication metadata from + * @param agentNames the agent names to capture replication metadata for */ public void captureReplicationMetadata(@NotNull DocViewNode2 node, @NotNull Collection<@NotNull String> agentNames) { for (String agentName : agentNames) { @@ -121,7 +121,13 @@ private void validateNoReplicationMetadata(@NotNull ValidationMessageSeverity va private void validateIsPublished(ValidationMessageSeverity validationMessageSeverity, Collection validationMessages, String agentName, boolean strictLastModificationCheck) { ReplicationMetadata replicationStatus = replicationStatusPerAgent.get(agentName); if (replicationStatus == null) { - throw new IllegalStateException("Replication status not yet populated via captureReplicationMetadata() for node " + this.path); + if (path.endsWith("/" + NameConstants.QUALIFIED_NAME_JCR_CONTENT)) { + validationMessages.add(new ValidationMessage(validationMessageSeverity, "No jcr:content node found at all where replication data would have been captured for agent " + agentName, path, null, null, 0, 0, null)); + } else { + // this is a programming error most probably + validationMessages.add(new ValidationMessage(validationMessageSeverity, "Replication status not yet populated via captureReplicationMetadata() for agent " + agentName, path, null, null, 0, 0, null)); + } + replicationStatus = ReplicationMetadata.EMPTY; } try { ReplicationActionType lastReplicationAction = replicationStatus.getLastReplicationAction(false); diff --git a/src/main/java/biz/netcentric/filevault/validator/ReplicationMetadata.java b/src/main/java/biz/netcentric/filevault/validator/ReplicationMetadata.java index 13220d7..2efb151 100644 --- a/src/main/java/biz/netcentric/filevault/validator/ReplicationMetadata.java +++ b/src/main/java/biz/netcentric/filevault/validator/ReplicationMetadata.java @@ -15,6 +15,7 @@ import java.text.ChoiceFormat; import java.util.Arrays; import java.util.Calendar; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -35,13 +36,18 @@ public class ReplicationMetadata { static final String DEFAULT_AGENT_NAME = "publish"; - private static final String CQ_LAST_REPLICATED = "lastReplicated"; - private static final String CQ_LAST_PUBLISHED = "lastPublished"; - private static final String CQ_LAST_REPLICATION_ACTION = "lastReplicationAction"; + // the following are just the local names of properties (without their namespace prefix) + private static final String LAST_REPLICATED = "lastReplicated"; + private static final String LAST_PUBLISHED = "lastPublished"; + private static final String LAST_REPLICATION_ACTION = "lastReplicationAction"; private final @NotNull DocViewNode2 node; private final @NotNull String agentName; + private static final DocViewNode2 EMPTY_NODE = new DocViewNode2(NameConstants.JCR_CONTENT, Collections.emptyList()); + // the node name does not matter + static final ReplicationMetadata EMPTY = new ReplicationMetadata(EMPTY_NODE, DEFAULT_AGENT_NAME); + public ReplicationMetadata(@NotNull DocViewNode2 node, @NotNull String agentName) { super(); this.node = node; @@ -69,7 +75,7 @@ static DocViewProperty2 getProperty(@NotNull DocViewNode2 node, @NotNull String public Calendar getLastReplicationDate(boolean allowNullReturnValue) { // this logic is derived from com.day.cq.replication.impl.ReplicationStatusImpl.readAgentStatus(...) // and com.day.cq.wcm.core.impl.reference.ReferenceReplicationStatusProvider.initReplicationStatusMap(...) - DocViewProperty2 property = getProperty(node, agentName, allowNullReturnValue, NameConstants.CQ_NAMESPACE_URI, CQ_LAST_REPLICATED, CQ_LAST_PUBLISHED); + DocViewProperty2 property = getProperty(node, agentName, allowNullReturnValue, NameConstants.CQ_NAMESPACE_URI, LAST_REPLICATED, LAST_PUBLISHED); Optional lastReplicationDate = Optional.ofNullable(property) .flatMap(DocViewProperty2::getStringValue) .map(NameConstants.VALUE_FACTORY::createValue) @@ -89,7 +95,7 @@ public Calendar getLastReplicationDate(boolean allowNullReturnValue) { public ReplicationActionType getLastReplicationAction(boolean allowNullReturnValue) { // this logic is derived from com.day.cq.replication.impl.ReplicationStatusImpl.readAgentStatus(...) // and com.day.cq.wcm.core.impl.reference.ReferenceReplicationStatusProvider.initReplicationStatusMap(...) - DocViewProperty2 property = getProperty(node, agentName, allowNullReturnValue, NameConstants.CQ_NAMESPACE_URI, CQ_LAST_REPLICATION_ACTION); + DocViewProperty2 property = getProperty(node, agentName, allowNullReturnValue, NameConstants.CQ_NAMESPACE_URI, LAST_REPLICATION_ACTION); Optional replicationActionType = Optional.ofNullable(property) .flatMap(DocViewProperty2::getStringValue) .map(ReplicationActionType::fromName);