You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by kw...@apache.org on 2021/06/10 09:57:50 UTC

[jackrabbit-filevault] branch master updated: JCRVLT-532 use relaxed node type validation during incremental runs (#146)

This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jackrabbit-filevault.git


The following commit(s) were added to refs/heads/master by this push:
     new 85cafc1  JCRVLT-532 use relaxed node type validation during incremental runs (#146)
85cafc1 is described below

commit 85cafc10d2b28d05c77af06801c7264ca146e51e
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Thu Jun 10 11:56:49 2021 +0200

    JCRVLT-532 use relaxed node type validation during incremental runs (#146)
---
 .../vault/validation/spi/ValidationContext.java    |  8 +++++
 .../spi/impl/nodetype/JcrNodeTypeMetaDataImpl.java | 23 +++++++-----
 .../spi/impl/nodetype/NodeTypeValidator.java       |  4 +--
 .../impl/nodetype/NodeTypeValidatorFactory.java    |  5 +--
 .../vault/validation/spi/package-info.java         |  2 +-
 .../impl/nodetype/JcrNodeTypeMetaDataImplTest.java | 41 ++++++++++++++++++++--
 .../spi/impl/nodetype/NodeTypeValidatorTest.java   |  2 +-
 7 files changed, 66 insertions(+), 19 deletions(-)

diff --git a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/ValidationContext.java b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/ValidationContext.java
index 607aa1e..0b09161 100644
--- a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/ValidationContext.java
+++ b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/ValidationContext.java
@@ -64,4 +64,12 @@ public interface ValidationContext {
      * @return the package info of all resolved package dependencies (i.e. the ones for which an artifact was found).
      */
     @NotNull Collection<PackageInfo> getDependenciesPackageInfo();
+    
+    /**
+     * 
+     * @return {@code true} in case the validation is incremental (i.e. does not cover all files in a package). This should relax some validations.
+     */
+    default boolean isIncremental() {
+        return false;
+    }
 }
diff --git a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImpl.java b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImpl.java
index 0745420..144bc43 100644
--- a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImpl.java
+++ b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImpl.java
@@ -110,8 +110,9 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
     private final boolean isImplicit; // if this is true, the node type is set implicitly (not explicitly set in package, used as is in the
                                       // repository)
     private boolean isValidationDone;
+    private final boolean isIncremental;
 
-    private JcrNodeTypeMetaDataImpl(@NotNull Name name, @Nullable Name primaryNodeType, @Nullable EffectiveNodeType effectiveNodeType,
+    private JcrNodeTypeMetaDataImpl(boolean isIncremental, @NotNull Name name, @Nullable Name primaryNodeType, @Nullable EffectiveNodeType effectiveNodeType,
             JcrNodeTypeMetaDataImpl parentNode, boolean isAuthenticationOrAuthorizationContext, boolean isImplicit) {
         super();
         this.name = name; // fully namespaced (taking into account local namespace declaration for Docview XML)
@@ -124,6 +125,7 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
         this.isAuthenticationOrAuthorizationContext = isAuthenticationOrAuthorizationContext;
         this.isImplicit = isImplicit;
         this.isValidationDone = false;
+        this.isIncremental = isIncremental;
     }
 
     @Override
@@ -228,7 +230,7 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
     }
 
     private @NotNull JcrNodeTypeMetaDataImpl addUnknownChildNode(@NotNull Name name) throws IllegalNameException {
-        JcrNodeTypeMetaDataImpl childNode = new JcrNodeTypeMetaDataImpl(name, null, null, this, false, false);
+        JcrNodeTypeMetaDataImpl childNode = new JcrNodeTypeMetaDataImpl(this.isIncremental, name, null, null, this, false, false);
         childNodesByName.put(name, childNode);
         return childNode;
     }
@@ -299,7 +301,7 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
         if (!isAuthenticationOrAuthorizationContext) {
             isAuthenticationOrAuthorizationContext = this.isAuthenticationOrAuthorizationContext;
         }
-        JcrNodeTypeMetaDataImpl newNode = new JcrNodeTypeMetaDataImpl(qName, newPrimaryNodeType, newEffectiveNodeType, this,
+        JcrNodeTypeMetaDataImpl newNode = new JcrNodeTypeMetaDataImpl(this.isIncremental, qName, newPrimaryNodeType, newEffectiveNodeType, this,
                 isAuthenticationOrAuthorizationContext, isImplicit);
         childNodesByName.put(qName, newNode);
         return newNode;
@@ -350,10 +352,13 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
             @NotNull ValidationMessageSeverity severity, @NotNull WorkspaceFilter filter) throws NamespaceException {
         if (!isValidationDone) {
             Collection<ValidationMessage> messages = new LinkedList<>();
-            messages.add(new ValidationMessage(ValidationMessageSeverity.DEBUG,
-                    "Validate mandatory children and properties of " + getQualifiedPath(namePathResolver)));
-            messages.addAll(validateMandatoryChildNodes(namePathResolver, severity, filter));
-            messages.addAll(validateMandatoryProperties(namePathResolver, severity));
+            // in incremental validations ignore missing mandatory properties and child nodes (as they might not be visible to the validator)
+            if (!isIncremental) {
+                messages.add(new ValidationMessage(ValidationMessageSeverity.DEBUG,
+                        "Validate mandatory children and properties of " + getQualifiedPath(namePathResolver)));
+                messages.addAll(validateMandatoryChildNodes(namePathResolver, severity, filter));
+                messages.addAll(validateMandatoryProperties(namePathResolver, severity));
+            }
             // only remove child nodes on 2nd level to be able to validate mandatory properties of parent
             childNodesByName.clear();
             isValidationDone = true;
@@ -624,9 +629,9 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
         return true;
     }
 
-    public static @NotNull JcrNodeTypeMetaDataImpl createRoot(@NotNull EffectiveNodeTypeProvider effectiveNodeTypeProvider)
+    public static @NotNull JcrNodeTypeMetaDataImpl createRoot(boolean isIncremental, @NotNull EffectiveNodeTypeProvider effectiveNodeTypeProvider)
             throws ConstraintViolationException, NoSuchNodeTypeException {
-        return new JcrNodeTypeMetaDataImpl(NameConstants.ROOT, NameConstants.REP_ROOT, effectiveNodeTypeProvider.getEffectiveNodeType(
+        return new JcrNodeTypeMetaDataImpl(isIncremental, NameConstants.ROOT, NameConstants.REP_ROOT, effectiveNodeTypeProvider.getEffectiveNodeType(
                 new Name[] {
                         NameConstants.REP_ROOT,
                         NameConstants.REP_ACCESS_CONTROLLABLE,
diff --git a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidator.java b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidator.java
index 1a013a4..2bacdcf 100644
--- a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidator.java
+++ b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidator.java
@@ -80,7 +80,7 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
     private final @NotNull Name defaultType;
     private JcrNodeTypeMetaData currentNodeTypeMetaData;
 
-    public NodeTypeValidator(@NotNull WorkspaceFilter filter, @NotNull NodeTypeManagerProvider ntManagerProvider,
+    public NodeTypeValidator(boolean isIncremental, @NotNull WorkspaceFilter filter, @NotNull NodeTypeManagerProvider ntManagerProvider,
             @NotNull Name defaultPrimaryNodeType, @NotNull ValidationMessageSeverity defaultSeverity,
             @NotNull ValidationMessageSeverity severityForUnknownNodeTypes)
             throws IllegalNameException, ConstraintViolationException, NoSuchNodeTypeException {
@@ -92,7 +92,7 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
         this.docViewPropertyValueFactory = new DocViewPropertyValueFactory();
         this.loggedUnknownNodeTypeMessages = new HashSet<>();
 
-        this.currentNodeTypeMetaData = JcrNodeTypeMetaDataImpl.createRoot(ntManagerProvider.getEffectiveNodeTypeProvider());
+        this.currentNodeTypeMetaData = JcrNodeTypeMetaDataImpl.createRoot(isIncremental, ntManagerProvider.getEffectiveNodeTypeProvider());
     }
 
     static String getDocViewNodeLabel(DocViewNode node) {
diff --git a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorFactory.java b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorFactory.java
index 71ed2ca..e5d3faf 100644
--- a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorFactory.java
+++ b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorFactory.java
@@ -22,14 +22,11 @@ import java.io.Reader;
 import java.net.JarURLConnection;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.jar.Manifest;
 
 import javax.jcr.RepositoryException;
@@ -112,7 +109,7 @@ public class NodeTypeValidatorFactory implements ValidatorFactory {
             for (Map.Entry<String, String> entry : validNameSpaces.entrySet()) {
                 ntManagerProvider.registerNamespace(entry.getKey(), entry.getValue());
             }
-            return new NodeTypeValidator(context.getFilter(), ntManagerProvider, ntManagerProvider.getNameResolver().getQName(defaultNodeType), settings.getDefaultSeverity(),
+            return new NodeTypeValidator(context.isIncremental(), context.getFilter(), ntManagerProvider, ntManagerProvider.getNameResolver().getQName(defaultNodeType), settings.getDefaultSeverity(),
                     severityForUnknownNodetypes);
         } catch (IOException | RepositoryException | ParseException e) {
             throw new IllegalArgumentException("Error loading default node type " + defaultNodeType, e);
diff --git a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/package-info.java b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/package-info.java
index 0dfdeae..e36d16b 100644
--- a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/package-info.java
+++ b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/package-info.java
@@ -18,7 +18,7 @@
 /**
  * The FileVault validation framework SPI. Provides classes/interfaces to implement validators on FileVault packages.
  */
-@Version("1.3.0")
+@Version("1.4.0")
 package org.apache.jackrabbit.vault.validation.spi;
 
 import org.osgi.annotation.versioning.Version;
diff --git a/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImplTest.java b/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImplTest.java
index b2d472b..f69d870 100644
--- a/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImplTest.java
+++ b/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaDataImplTest.java
@@ -65,7 +65,7 @@ public class JcrNodeTypeMetaDataImplTest {
     @Before
     public void setUp() throws IOException, RepositoryException, ParseException {
         ntManagerProvider = new NodeTypeManagerProvider();
-        root = JcrNodeTypeMetaDataImpl.createRoot(ntManagerProvider.getEffectiveNodeTypeProvider());
+        root = JcrNodeTypeMetaDataImpl.createRoot(false, ntManagerProvider.getEffectiveNodeTypeProvider());
     }
 
     static NodeContext createSimpleNodeContext(String nodePath) {
@@ -220,7 +220,7 @@ public class JcrNodeTypeMetaDataImplTest {
     }
 
     @Test
-    public void testValidateMandatoryChildNode() throws IllegalNameException, NoSuchNodeTypeException, RepositoryException,
+    public void testValidateMandatoryChildNodesAndProperties() throws IllegalNameException, NoSuchNodeTypeException, RepositoryException,
             IOException, ParseException {
         try (InputStream input = this.getClass().getResourceAsStream("/simple-restricted-nodetypes.cnd");
                 Reader reader = new InputStreamReader(input, StandardCharsets.US_ASCII)) {
@@ -305,6 +305,43 @@ public class JcrNodeTypeMetaDataImplTest {
                         "my:nodeType2", "/nodeForMandatoryProperties2")));
     }
 
+    @Test
+    public void testValidateMandatoryChildNodesAndPropertiesDuringIncrementalBuild() throws InvalidNodeTypeDefinitionException, NodeTypeExistsException, UnsupportedRepositoryOperationException, ParseException, RepositoryException, IOException {
+        try (InputStream input = this.getClass().getResourceAsStream("/simple-restricted-nodetypes.cnd");
+                Reader reader = new InputStreamReader(input, StandardCharsets.US_ASCII)) {
+            ntManagerProvider.registerNodeTypes(reader);
+        }
+        // enable incremental validation
+        root = JcrNodeTypeMetaDataImpl.createRoot(true, ntManagerProvider.getEffectiveNodeTypeProvider());
+        // add valid node
+        JcrNodeTypeMetaData node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
+                ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
+                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, createSimpleNodeContext("name"),
+                "my:nodeType1");
+        assertNoValidationErrors(node);
+
+        DefaultWorkspaceFilter filter = new DefaultWorkspaceFilter();
+
+        node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
+                ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
+                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, createSimpleNodeContext("name2"),
+                "my:nodeType1");
+        
+        // mandatory child node missing but not reported due to incremental validation
+        filter.add(new PathFilterSet("/"));
+        Collection<ValidationMessage> messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ValidationMessageSeverity.ERROR, filter);
+        MatcherAssert.assertThat(messages, AnyValidationMessageMatcher.noValidationInCollection());
+
+        // mandatory property missing but not reported due to incremental validation
+        NodeContext nodeContext = createSimpleNodeContext("nodeForMandatoryProperties");
+        node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
+                ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
+                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, nodeContext, "my:nodeType2");
+        assertNoValidationErrors(node);
+        messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ValidationMessageSeverity.ERROR, filter);
+        MatcherAssert.assertThat(messages, AnyValidationMessageMatcher.noValidationInCollection());
+    }
+    
     @Test(expected = IllegalNameException.class)
     public void testAddPropertyWithUndeclaredNamespace() throws RepositoryException {
         root.addProperty(createSimpleNodeContext("/"), ntManagerProvider.getNamePathResolver(),
diff --git a/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorTest.java b/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorTest.java
index 54c5913..3790f3c 100644
--- a/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorTest.java
+++ b/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/NodeTypeValidatorTest.java
@@ -80,7 +80,7 @@ public class NodeTypeValidatorTest {
                 throw new IllegalArgumentException("Error loading node types from CND at " + cndUrl, e);
             }
         }
-        return new NodeTypeValidator(filter, ntManagerProvider, defaultNodeType, ValidationMessageSeverity.ERROR,
+        return new NodeTypeValidator(false, filter, ntManagerProvider, defaultNodeType, ValidationMessageSeverity.ERROR,
                 ValidationMessageSeverity.WARN);
     }