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/21 15:36:32 UTC

[jackrabbit-filevault] branch master updated: JCRVLT-536 only emit "WARN" by default for violations against default (#149)

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 05abf8e  JCRVLT-536 only emit "WARN" by default for violations against default (#149)
05abf8e is described below

commit 05abf8edff459ab9526077bbb143363d6f8294ff
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Mon Jun 21 17:34:26 2021 +0200

    JCRVLT-536 only emit "WARN" by default for violations against default (#149)
---
 src/site/markdown/validation.md                    |   2 +-
 .../spi/impl/nodetype/JcrNodeTypeMetaData.java     |   7 +-
 .../spi/impl/nodetype/JcrNodeTypeMetaDataImpl.java |  66 +++++------
 .../spi/impl/nodetype/NodeTypeValidator.java       |  10 +-
 .../impl/nodetype/NodeTypeValidatorFactory.java    |  19 +++-
 .../impl/nodetype/JcrNodeTypeMetaDataImplTest.java | 121 ++++++++++-----------
 .../spi/impl/nodetype/NodeTypeValidatorTest.java   |  16 +--
 7 files changed, 122 insertions(+), 119 deletions(-)

diff --git a/src/site/markdown/validation.md b/src/site/markdown/validation.md
index 7a5d31d..83c0eb9 100644
--- a/src/site/markdown/validation.md
+++ b/src/site/markdown/validation.md
@@ -59,7 +59,7 @@ ID  |  Description | Options | Incremental Execution Limitations
 `jackrabbit-mergelimitations` | Checks for the limitation of import mode=merge outlined at [JCRVLT-255][jcrvlt-255]. | none | none
 `jackrabbit-oakindex` |  Checks if the package (potentially) modifies/creates an OakIndexDefinition. This is done by evaluating both the filter.xml for potential matches as well as the actual content for nodes with jcr:primaryType  `oak:indexDefinition`. | none | none
 `jackrabbit-packagetype` | Checks if the package type is correctly set for this package, i.e. is compliant with all rules outlined at [Package Types](packagetypes.html). | *jcrInstallerNodePathRegex*: the regex of the node paths which all OSGi bundles and configurations within packages must match ([JCR Installer](https://sling.apache.org/documentation/bundles/jcr-installer-provider.html)) (default=`/([^/]*/){0,4}?(install|config)(\\.[^/]*)*/(\\d{1,3}/)?.+?\\.`).<br/>*additionalJcrInstall [...]
-`jackrabbit-nodetypes` | Checks if all non empty elements within [DocView files](docview.html) have the mandatory property `jcr:primaryType` set and follow the [node type definition of their given type](https://jackrabbit.apache.org/jcr/node-types.html). | *cnds*: A URI pointing to one or multiple [CNDs](https://jackrabbit.apache.org/jcr/node-type-notation.html) (separated by `,`) which define the additional namespaces and nodetypes used apart from the [default ones defined in JCR 2.0](h [...]
+`jackrabbit-nodetypes` | Checks if all non empty elements within [DocView files](docview.html) have the mandatory property `jcr:primaryType` set and follow the [node type definition of their given type](https://jackrabbit.apache.org/jcr/node-types.html). | *cnds*: A URI pointing to one or multiple [CNDs](https://jackrabbit.apache.org/jcr/node-type-notation.html) (separated by `,`) which define the additional namespaces and nodetypes used apart from the [default ones defined in JCR 2.0](h [...]
 `jackrabbit-accesscontrol` | Checks that [access control list nodes (primary type `rep:ACL`, `rep:CugPolicy` and `rep:PrincipalPolicy`)](https://jackrabbit.apache.org/oak/docs/security/accesscontrol/default.html#Representation_in_the_Repository) are only used when the [package property's](./properties.html) `acHandling` is set to something but `ignore` or `clear` and also that there is at least one access control list node otherwise | none | Validation message in case no access control l [...]
 
 ### Custom Validators
diff --git a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaData.java b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaData.java
index d30e8e4..d0f2369 100644
--- a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaData.java
+++ b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/nodetype/JcrNodeTypeMetaData.java
@@ -44,14 +44,14 @@ public interface JcrNodeTypeMetaData {
 
     Collection<ValidationMessage> addProperty(@NotNull NodeContext nodeContext, @NotNull NamePathResolver namePathResolver, @NotNull EffectiveNodeTypeProvider effectiveNodeTypeProvider,
             @NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider, @NotNull ItemDefinitionProvider itemDefinitionProvider,
-            @NotNull ValidationMessageSeverity severity, String name, boolean isMultiValue, Value... values) throws RepositoryException;
+            @NotNull ValidationMessageSeverity severity, @NotNull ValidationMessageSeverity severityForDefaultNodeTypeViolations, String name, boolean isMultiValue, Value... values) throws RepositoryException;
     @NotNull JcrNodeTypeMetaData addImplicitChildNode(@NotNull NameResolver nameResolver,
             @NotNull EffectiveNodeTypeProvider effectiveNodeTypeProvider, @NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider,
             @NotNull ItemDefinitionProvider itemDefinitionProvider, @NotNull NodeContext nodeContext, @NotNull Name implicitNodeType)
             throws RepositoryException;
     @NotNull JcrNodeTypeMetaData addChildNode(@NotNull NameResolver nameResolver, @NotNull EffectiveNodeTypeProvider effectiveNodeTypeProvider,
             @NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider, @NotNull ItemDefinitionProvider itemDefinitionProvider,
-            @NotNull ValidationMessageSeverity severity, @NotNull NodeContext nodeContext, @NotNull String primaryType, String... mixinTypes)
+            @NotNull NodeContext nodeContext, @NotNull String primaryType, String... mixinTypes)
                     throws RepositoryException, NamespaceExceptionInNodeName;
     @NotNull JcrNodeTypeMetaData addUnknownChildNode(@NotNull NameResolver nameResolver, @NotNull NodeContext nodeContext, @NotNull String name) throws IllegalNameException, NamespaceException;
     
@@ -62,7 +62,8 @@ public interface JcrNodeTypeMetaData {
     @NotNull JcrNodeTypeMetaData getOrCreateNode(NamePathResolver nameResolver, @NotNull NodeContext nodeContext, String path) throws RepositoryException;
     
     @NotNull Collection<ValidationMessage> finalizeValidation(@NotNull NamePathResolver nameResolver,
-            @NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider, @NotNull ItemDefinitionProvider itemDefinitionProvider, @NotNull ValidationMessageSeverity severity, @NotNull WorkspaceFilter filter) throws NamespaceException;
+            @NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider, @NotNull ItemDefinitionProvider itemDefinitionProvider, @NotNull ValidationMessageSeverity severity, 
+            @NotNull ValidationMessageSeverity severityForDefaultNodeTypeViolations, @NotNull WorkspaceFilter filter) throws NamespaceException;
     @NotNull Name getPrimaryNodeType();
     String getQualifiedPath(NamePathResolver resolver) throws NamespaceException;
     void setNodeTypes(@NotNull NameResolver nameResolver, @NotNull EffectiveNodeTypeProvider effectiveNodeTypeProvider,
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 bd675f8..fbca7bd 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
@@ -78,14 +78,12 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
     static final String CONSTRAINT_ABSTRACT_TYPE_AS_PRIMARY_TYPE = "Given node type is abstract and cannot be used as primary node type.";
     static final String CONSTRAINT_CHILD_NODE_NOT_ALLOWED = "Node type does not allow arbitrary child nodes and does not allow this specific name and node type either!";
 
-    static final String MESSAGE_CHILD_NODE_OF_NOT_CONTAINED_PARENT_POTENTIALLY_NOT_ALLOWED = "Node '%s [%s]' is not allowed as child of not contained node with potential default types '[%s]': %s";
-    static final String MESSAGE_CHILD_NODE_NOT_ALLOWED = "Node '%s [%s]' is not allowed as child of node with types [%s]: %s";
-    static final String MESSAGE_PROPERTY_OF_NOT_CONTAINED_PARENT_POTENTIALLY_NOT_ALLOWED = "Property '%s' [%s] is not allowed in node with potential default types [%s]: %s";;
-    static final String MESSAGE_PROPERTY_NOT_ALLOWED = "Property '%s' [%s] is not allowed in node with types [%s]: %s";
-    static final String MESSAGE_MANDATORY_CHILD_NODE_MISSING = "Mandatory child node missing: %s inside node with types [%s]";
+    static final String MESSAGE_CHILD_NODE_NOT_ALLOWED = "Node '%s [%s]' is not allowed as child of node with %s: %s";
+    static final String MESSAGE_PROPERTY_NOT_ALLOWED = "Property '%s' [%s] is not allowed in node with %s: %s";
+    static final String MESSAGE_MANDATORY_CHILD_NODE_MISSING = "Mandatory child node missing: %s inside node with %s";
     static final String MESSAGE_MANDATORY_UNCONTAINED_CHILD_NODE_MISSING = "Mandatory child node missing: %s inside node with types [%s] (outside of filter rules)";
-    static final String MESSAGE_MANDATORY_PROPERTY_MISSING = "Mandatory property '%s' missing in node with types [%s]";
-    static final String MESSAGE_MANDATORY_PROPERTY_WITH_WRONG_TYPE = "Mandatory property '%s' has type '%s' while it should have '%s' in node with types [%s]";
+    static final String MESSAGE_MANDATORY_PROPERTY_MISSING = "Mandatory property '%s' missing in node with %s";
+    static final String MESSAGE_MANDATORY_PROPERTY_WITH_WRONG_TYPE = "Mandatory property '%s' has type '%s' while it should have '%s' in node with %s";
 
     // do not validate protected JCR system properties that are handled by FileVault specially in https://github.com/apache/jackrabbit-filevault/blob/f785fcb24d4cbd01c734e9273310a925c29ae15b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java#L123 and 
     // https://github.com/apache/jackrabbit-filevault/blob/f785fcb24d4cbd01c734e9273310a925c29ae15b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java#L140
@@ -213,12 +211,6 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
             @NotNull NodeContext nodeContext, @Nullable Name implicitNodeType) throws RepositoryException {
         JcrNodeTypeMetaDataImpl childNode = addChildNode(nameResolver, effectiveNodeTypeProvider, nodeTypeDefinitionProvider,
                 itemDefinitionProvider, true, nodeContext, Text.getName(nodeContext.getNodePath()), implicitNodeType);
-        // now validate for validity
-        Optional<String> constraintViolation = childNode.validateAgainstParentNodeType(effectiveNodeType, nodeTypeDefinitionProvider,
-                itemDefinitionProvider);
-        if (constraintViolation.isPresent()) {
-            throw new IllegalArgumentException("The implicit node type is invalid here: " + constraintViolation.get());
-        }
         return childNode;
     }
 
@@ -238,8 +230,7 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
     public @NotNull JcrNodeTypeMetaData addChildNode(@NotNull NameResolver nameResolver,
             @NotNull EffectiveNodeTypeProvider effectiveNodeTypeProvider,
             @NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider, @NotNull ItemDefinitionProvider itemDefinitionProvider,
-            @NotNull ValidationMessageSeverity severity, @NotNull NodeContext nodeContext, @NotNull String primaryType,
-            String... mixinTypes)
+            @NotNull NodeContext nodeContext, @NotNull String primaryType, String... mixinTypes)
             throws IllegalNameException, RepositoryException, NamespaceExceptionInNodeName {
 
         List<Name> types = getTypes(nameResolver, primaryType, mixinTypes);
@@ -299,7 +290,7 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
      * @param parentEffectiveNodeType
      * @return constraints violation message
      * @throws RepositoryException */
-    private Optional<String> validateAgainstParentNodeType(@Nullable EffectiveNodeType parentEffectiveNodeType,
+    private Optional<String> validateAgainstParentNodeType(@NotNull EffectiveNodeType parentEffectiveNodeType,
             @NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider,
             @NotNull ItemDefinitionProvider itemDefinitionProvider) throws RepositoryException {
         if (effectiveNodeType == null || primaryNodeType == null) {
@@ -311,9 +302,6 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
             return Optional.empty();
         }
 
-        if (parentEffectiveNodeType == null) {
-            return Optional.empty();
-        }
         QNodeTypeDefinition primaryNodeTypeDefinition = nodeTypeDefinitionProvider.getNodeTypeDefinition(primaryNodeType);
         if (primaryNodeTypeDefinition.isAbstract()) {
             return Optional.of(CONSTRAINT_ABSTRACT_TYPE_AS_PRIMARY_TYPE);
@@ -338,15 +326,15 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
 
     @Override
     public @NotNull Collection<ValidationMessage> finalizeValidation(@NotNull NamePathResolver namePathResolver,  @NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider, @NotNull ItemDefinitionProvider itemDefinitionProvider,
-            @NotNull ValidationMessageSeverity severity, @NotNull WorkspaceFilter filter) throws NamespaceException {
+            @NotNull ValidationMessageSeverity severity, @NotNull ValidationMessageSeverity severityForDefaultNodeTypeViolations, @NotNull WorkspaceFilter filter) throws NamespaceException {
         if (!isValidationDone) {
             Collection<ValidationMessage> messages = new LinkedList<>();
             // 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 children and mandatory properties of " + getQualifiedPath(namePathResolver)));
-                messages.addAll(validateChildNodes(namePathResolver, nodeTypeDefinitionProvider, itemDefinitionProvider, severity, filter));
-                messages.addAll(validateMandatoryProperties(namePathResolver, severity));
+                messages.addAll(validateChildNodes(namePathResolver, nodeTypeDefinitionProvider, itemDefinitionProvider, severity, severityForDefaultNodeTypeViolations, filter));
+                messages.addAll(validateMandatoryProperties(namePathResolver, severity, severityForDefaultNodeTypeViolations));
             }
             // only remove child nodes on 2nd level to be able to validate mandatory properties of parent
             childNodesByName.clear();
@@ -361,7 +349,7 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
     }
 
     private Collection<ValidationMessage> validateChildNodes(@NotNull NamePathResolver namePathResolver,  @NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider, @NotNull ItemDefinitionProvider itemDefinitionProvider,
-            @NotNull ValidationMessageSeverity severity, @NotNull WorkspaceFilter filter) {
+            @NotNull ValidationMessageSeverity severity, @NotNull ValidationMessageSeverity severityForDefaultNodeTypeViolations, @NotNull WorkspaceFilter filter) {
         if (effectiveNodeType == null) {
             return Collections.emptyList();
         }
@@ -374,10 +362,9 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
                 constraintViolation = childNode.validateAgainstParentNodeType(effectiveNodeType, nodeTypeDefinitionProvider,
                         itemDefinitionProvider);
                 if (constraintViolation.isPresent()) {
-                    messages.add(new ValidationMessage(severity,
+                    messages.add(new ValidationMessage(isImplicit ? severityForDefaultNodeTypeViolations : severity,
                             String.format(
-                                    isImplicit ? MESSAGE_CHILD_NODE_OF_NOT_CONTAINED_PARENT_POTENTIALLY_NOT_ALLOWED
-                                            : MESSAGE_CHILD_NODE_NOT_ALLOWED,
+                                    MESSAGE_CHILD_NODE_NOT_ALLOWED,
                                     namePathResolver.getJCRName(childNode.name), namePathResolver.getJCRName(childNode.primaryNodeType),
                                     getEffectiveNodeTypeLabel(namePathResolver, effectiveNodeType),
                                     constraintViolation.get()), childNode.context));
@@ -405,7 +392,8 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
                 pathBuilder.addLast(mandatoryNodeType.getName());
                 try {
                     if (filter.contains(namePathResolver.getJCRPath(pathBuilder.getPath()))) {
-                        messages.add(new ValidationMessage(severity, String.format(MESSAGE_MANDATORY_CHILD_NODE_MISSING,
+                        messages.add(new ValidationMessage(isImplicit ? severityForDefaultNodeTypeViolations : severity,
+                                String.format(MESSAGE_MANDATORY_CHILD_NODE_MISSING,
                                 getNodeDefinitionLabel(namePathResolver, mandatoryNodeType),
                                 getEffectiveNodeTypeLabel(namePathResolver, effectiveNodeType))));
                     } else {
@@ -423,8 +411,15 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
         return messages;
     }
 
-    private static String getEffectiveNodeTypeLabel(NameResolver nameResolver, EffectiveNodeType nodeType) throws NamespaceException {
-        return joinAsQualifiedJcrName(nameResolver, nodeType.getMergedNodeTypes());
+    private String getEffectiveNodeTypeLabel(NameResolver nameResolver, EffectiveNodeType nodeType) throws NamespaceException {
+        String label;
+        String types = joinAsQualifiedJcrName(nameResolver, nodeType.getMergedNodeTypes());
+        if (isImplicit) 
+            label = String.format("potential default types [%s]", types);
+        else {
+            label =  String.format("types [%s]", types);
+        }
+        return label;
     }
 
     private static String getNodeDefinitionLabel(NameResolver nameResolver, QNodeDefinition nodeDefinition) throws NamespaceException {
@@ -499,7 +494,7 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
     }
 
     private Collection<ValidationMessage> validateMandatoryProperties(@NotNull NamePathResolver nameResolver,
-            @NotNull ValidationMessageSeverity severity) {
+            @NotNull ValidationMessageSeverity severity, @NotNull ValidationMessageSeverity severityForDefaultNodeTypeViolations) {
 
         if (effectiveNodeType == null) {
             return Collections.emptyList();
@@ -517,7 +512,7 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
             }
             try {
                 if (!propertyTypesByName.containsKey(mandatoryPropertyDefinition.getName())) {
-                    messages.add(new ValidationMessage(severity,
+                    messages.add(new ValidationMessage(isImplicit ? severityForDefaultNodeTypeViolations : severity,
                             String.format(MESSAGE_MANDATORY_PROPERTY_MISSING,
                                     nameResolver.getJCRName(mandatoryPropertyDefinition.getName()),
                                     getEffectiveNodeTypeLabel(nameResolver, effectiveNodeType)), context));
@@ -526,7 +521,7 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
                     int actualPropertyType = propertyTypesByName.get(mandatoryPropertyDefinition.getName());
                     if (mandatoryPropertyDefinition.getRequiredType() != actualPropertyType) {
                         // check type
-                        messages.add(new ValidationMessage(severity,
+                        messages.add(new ValidationMessage(isImplicit ? severityForDefaultNodeTypeViolations : severity,
                                 String.format(MESSAGE_MANDATORY_PROPERTY_WITH_WRONG_TYPE,
                                         nameResolver.getJCRName(mandatoryPropertyDefinition.getName()),
                                         PropertyType.nameFromValue(actualPropertyType),
@@ -546,7 +541,7 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
     public Collection<ValidationMessage> addProperty(@NotNull NodeContext nodeContext, @NotNull NamePathResolver namePathResolver,
             @NotNull EffectiveNodeTypeProvider effectiveNodeTypeProvider,
             @NotNull NodeTypeDefinitionProvider nodeTypeDefinitionProvider, @NotNull ItemDefinitionProvider itemDefinitionProvider,
-            @NotNull ValidationMessageSeverity severity, String name, boolean isMultiValue, Value... values) throws RepositoryException {
+            @NotNull ValidationMessageSeverity severity, @NotNull ValidationMessageSeverity severityForDefaultNodeTypeViolations, String name, boolean isMultiValue, Value... values) throws RepositoryException {
         Collection<ValidationMessage> messages = new ArrayList<>();
         // some sanity checks on multivalue
         if (!isMultiValue && values.length > 1) {
@@ -572,10 +567,9 @@ public class JcrNodeTypeMetaDataImpl implements JcrNodeTypeMetaData {
                 nodeTypeDefinitionProvider, itemDefinitionProvider, qName, values, isAuthenticationOrAuthorizationContext,
                 isMultiValue);
         if (constraintViolation.isPresent()) {
-            messages.add(new ValidationMessage(severity,
+            messages.add(new ValidationMessage(isImplicit ? severityForDefaultNodeTypeViolations : severity,
                     String.format(
-                            isImplicit ? MESSAGE_PROPERTY_OF_NOT_CONTAINED_PARENT_POTENTIALLY_NOT_ALLOWED
-                                    : MESSAGE_PROPERTY_NOT_ALLOWED,
+                            MESSAGE_PROPERTY_NOT_ALLOWED,
                             namePathResolver.getJCRName(qName), PropertyType.nameFromValue(values[0].getType()),
                             getEffectiveNodeTypeLabel(namePathResolver, effectiveNodeType),
                             constraintViolation.get()),
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 4add3c5..8d3d02f 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
@@ -73,6 +73,7 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
     private final WorkspaceFilter filter;
     private final ValidationMessageSeverity defaultSeverity;
     private final ValidationMessageSeverity severityForUnknownNodeTypes;
+    private final ValidationMessageSeverity severityForDefaultNodeTypeViolations;
     private final DocViewPropertyValueFactory docViewPropertyValueFactory;
     private final NodeTypeManagerProvider ntManagerProvider;
     private final Set<String> loggedUnknownNodeTypeMessages;
@@ -82,13 +83,14 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
 
     public NodeTypeValidator(boolean isIncremental, @NotNull WorkspaceFilter filter, @NotNull NodeTypeManagerProvider ntManagerProvider,
             @NotNull Name defaultPrimaryNodeType, @NotNull ValidationMessageSeverity defaultSeverity,
-            @NotNull ValidationMessageSeverity severityForUnknownNodeTypes)
+            @NotNull ValidationMessageSeverity severityForUnknownNodeTypes, @NotNull ValidationMessageSeverity severityForDefaultNodeTypeViolations)
             throws IllegalNameException, ConstraintViolationException, NoSuchNodeTypeException {
         this.filter = filter;
         this.ntManagerProvider = ntManagerProvider;
         this.defaultType = defaultPrimaryNodeType;
         this.defaultSeverity = defaultSeverity;
         this.severityForUnknownNodeTypes = severityForUnknownNodeTypes;
+        this.severityForDefaultNodeTypeViolations = severityForDefaultNodeTypeViolations;
         this.docViewPropertyValueFactory = new DocViewPropertyValueFactory();
         this.loggedUnknownNodeTypeMessages = new HashSet<>();
 
@@ -145,7 +147,7 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
         try {
             messages.addAll(currentNodeTypeMetaData.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(),
                     ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                    ntManagerProvider.getItemDefinitionProvider(), defaultSeverity, propertyName, isMultiValue, values));
+                    ntManagerProvider.getItemDefinitionProvider(), defaultSeverity, severityForDefaultNodeTypeViolations, propertyName, isMultiValue, values));
         } catch (NoSuchNodeTypeException | NamespaceException e) {
             // log each unknown node type/namespace only once!
             if (!loggedUnknownNodeTypeMessages.contains(e.getMessage())) {
@@ -221,7 +223,7 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
                 } else {
                     currentNodeTypeMetaData = parentNode.addChildNode(ntManagerProvider.getNameResolver(),
                             ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                            ntManagerProvider.getItemDefinitionProvider(), defaultSeverity, nodeContext, primaryType, mixinTypes);
+                            ntManagerProvider.getItemDefinitionProvider(), nodeContext, primaryType, mixinTypes);
                     
                 }
             } catch (NoSuchNodeTypeException | NamespaceException e) {
@@ -288,7 +290,7 @@ public class NodeTypeValidator implements DocumentViewXmlValidator, JcrPathValid
         for (JcrNodeTypeMetaData child : node.getChildren()) {
             messages.addAll(finalizeValidationForSubtree(child, nodeContext));
             messages.addAll(child.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                    ntManagerProvider.getItemDefinitionProvider(), defaultSeverity, filter));
+                    ntManagerProvider.getItemDefinitionProvider(), defaultSeverity, severityForDefaultNodeTypeViolations, filter));
         }
         return messages;
     }
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 e5d3faf..4818fa9 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
@@ -52,13 +52,18 @@ public class NodeTypeValidatorFactory implements ValidatorFactory {
     public static final String OPTION_CNDS = "cnds";
     /** The default node type to assume if no other node type is given */
     public static final String OPTION_DEFAULT_NODE_TYPES = "defaultNodeType";
+    static final @NotNull String DEFAULT_DEFAULT_NODE_TYPE = JcrConstants.NT_FOLDER;
+
     public static final String OPTION_SEVERITY_FOR_UNKNOWN_NODETYPES = "severityForUnknownNodetypes";
+    static final @NotNull ValidationMessageSeverity DEFAULT_SEVERITY_FOR_UNKNOWN_NODETYPE = ValidationMessageSeverity.WARN;
+    
+    public static final String OPTION_SEVERITY_FOR_DEFAULT_NODE_TYPE_VIOLATIONS = "severityForDefaultNodeTypeViolations";
+    static final @NotNull ValidationMessageSeverity DEFAULT_SEVERITY_FOR_DEFAULT_NODE_TYPE_VIOLATIONS = ValidationMessageSeverity.WARN;
+    
     /** Comma-separated list of name spaces that are known as valid (even if not defined in the CND files). Use syntax "prefix1=ns-uri1,prefix2=nsuri2,...". */
     public static final String OPTION_VALID_NAMESPACES = "validNameSpaces";
 
-    static final @NotNull String DEFAULT_DEFAULT_NODE_TYPE = JcrConstants.NT_FOLDER;
 
-    static final @NotNull ValidationMessageSeverity DEFAULT_SEVERITY_FOR_UNKNOWN_NODETYPE = ValidationMessageSeverity.WARN;
 
     private static final Logger LOGGER = LoggerFactory.getLogger(NodeTypeValidatorFactory.class);
 
@@ -87,6 +92,14 @@ public class NodeTypeValidatorFactory implements ValidatorFactory {
             severityForUnknownNodetypes = DEFAULT_SEVERITY_FOR_UNKNOWN_NODETYPE;
         }
 
+        final @NotNull ValidationMessageSeverity severityForDefaultNodeTypeViolations;
+        if (settings.getOptions().containsKey(OPTION_SEVERITY_FOR_DEFAULT_NODE_TYPE_VIOLATIONS)) {
+            String optionValue = settings.getOptions().get(OPTION_SEVERITY_FOR_DEFAULT_NODE_TYPE_VIOLATIONS);
+            severityForDefaultNodeTypeViolations = ValidationMessageSeverity.valueOf(optionValue.toUpperCase());
+        } else {
+            severityForDefaultNodeTypeViolations = DEFAULT_SEVERITY_FOR_DEFAULT_NODE_TYPE_VIOLATIONS;
+        }
+
         Map<String,String> validNameSpaces; 
         if (settings.getOptions().containsKey(OPTION_VALID_NAMESPACES)) {
             validNameSpaces = parseNamespaces(settings.getOptions().get(OPTION_VALID_NAMESPACES));
@@ -110,7 +123,7 @@ public class NodeTypeValidatorFactory implements ValidatorFactory {
                 ntManagerProvider.registerNamespace(entry.getKey(), entry.getValue());
             }
             return new NodeTypeValidator(context.isIncremental(), context.getFilter(), ntManagerProvider, ntManagerProvider.getNameResolver().getQName(defaultNodeType), settings.getDefaultSeverity(),
-                    severityForUnknownNodetypes);
+                    severityForUnknownNodetypes, severityForDefaultNodeTypeViolations);
         } catch (IOException | RepositoryException | ParseException e) {
             throw new IllegalArgumentException("Error loading default node type " + defaultNodeType, e);
         }
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 0eef044..fb5879d 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
@@ -72,19 +72,18 @@ public class JcrNodeTypeMetaDataImplTest {
 
     @Test
     public void testGetNode() throws RepositoryException {
-        ValidationMessageSeverity severity = ValidationMessageSeverity.ERROR;
         JcrNodeTypeMetaData child = root.addChildNode(ntManagerProvider.getNameResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
-                ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(), severity,
+                ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
                 createSimpleNodeContext("my"),
                 NodeType.NT_FOLDER);
         JcrNodeTypeMetaData grandChild = child.addChildNode(ntManagerProvider.getNameResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(),
-                ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(), severity,
+                ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
                 createSimpleNodeContext("test"),
                 NodeType.NT_FOLDER);
         JcrNodeTypeMetaData child2 = root.addChildNode(ntManagerProvider.getNameResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(),
-                ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(), severity,
+                ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
                 createSimpleNodeContext("test2"),
                 NodeType.NT_FOLDER);
         Assert.assertEquals(child2,
@@ -94,14 +93,13 @@ public class JcrNodeTypeMetaDataImplTest {
     public void testGetNodeWithNonExistingPath() throws MalformedPathException, NamespaceException, IllegalArgumentException,
             PathNotFoundException, RepositoryException {
 
-        ValidationMessageSeverity severity = ValidationMessageSeverity.ERROR;
         JcrNodeTypeMetaData child = root.addChildNode(ntManagerProvider.getNameResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
-                ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(), severity,
+                ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
                 createSimpleNodeContext("my"),
                 NodeType.NT_FOLDER);
         JcrNodeTypeMetaData grandChild = child.addChildNode(ntManagerProvider.getNameResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), severity, createSimpleNodeContext("test"), NodeType.NT_FOLDER);
+                ntManagerProvider.getItemDefinitionProvider(), createSimpleNodeContext("test"), NodeType.NT_FOLDER);
         Assert.assertFalse(grandChild.getNode(ntManagerProvider.getNamePathResolver(), "/test2").isPresent());
     }
 
@@ -109,7 +107,6 @@ public class JcrNodeTypeMetaDataImplTest {
     public void testAddChildNodeWithUndeclaredNamespaceInName() throws RepositoryException {
         root.addChildNode(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
                 ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
-                ValidationMessageSeverity.ERROR,
                 createSimpleNodeContext("invalid:name"), NodeTypeConstants.NT_FOLDER);
     }
 
@@ -117,7 +114,6 @@ public class JcrNodeTypeMetaDataImplTest {
     public void testAddChildNodeWithUndeclaredNamespaceInType() throws RepositoryException {
         root.addChildNode(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
                 ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
-                ValidationMessageSeverity.ERROR,
                 createSimpleNodeContext("myname"), "my:nodeType1");
     }
 
@@ -125,7 +121,6 @@ public class JcrNodeTypeMetaDataImplTest {
     public void testAddChildNodeWithUndeclaredType() throws RepositoryException {
         root.addChildNode(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
                 ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
-                ValidationMessageSeverity.ERROR,
                 createSimpleNodeContext("myname"), "jcr:nodeType1");
     }
 
@@ -144,79 +139,76 @@ public class JcrNodeTypeMetaDataImplTest {
         
         JcrNodeTypeMetaData node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, nodeContext,
+                ntManagerProvider.getItemDefinitionProvider(), nodeContext,
                 "mix:mimeType");
         ValidationExecutorTest.assertViolation(root.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
                 ntManagerProvider.getItemDefinitionProvider(),
-                ValidationMessageSeverity.ERROR, filter),
+                ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, filter),
                 new ValidationMessage(ValidationMessageSeverity.ERROR,
-                String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_NOT_ALLOWED, "name", "mix:mimeType", ROOT_NODE_TYPES,
+                String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_NOT_ALLOWED, "name", "mix:mimeType", "types [" + ROOT_NODE_TYPES +"]",
                         JcrNodeTypeMetaDataImpl.CONSTRAINT_MIXIN_TYPE_AS_PRIMARY_TYPE), nodeContext));
 
         // add node with abstract type
         root = JcrNodeTypeMetaDataImpl.createRoot(false, ntManagerProvider.getEffectiveNodeTypeProvider());
         node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, nodeContext,
+                ntManagerProvider.getItemDefinitionProvider(), nodeContext,
                 "nt:hierarchyNode");
         ValidationExecutorTest.assertViolation(root.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
                 ntManagerProvider.getItemDefinitionProvider(),
-                ValidationMessageSeverity.ERROR, filter),
+                ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, filter),
                 new ValidationMessage(ValidationMessageSeverity.ERROR,
-                String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_NOT_ALLOWED, "name", "nt:hierarchyNode", ROOT_NODE_TYPES,
+                String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_NOT_ALLOWED, "name", "nt:hierarchyNode", "types [" + ROOT_NODE_TYPES +"]",
                         JcrNodeTypeMetaDataImpl.CONSTRAINT_ABSTRACT_TYPE_AS_PRIMARY_TYPE), nodeContext));
 
         // add node for version storage
         root = JcrNodeTypeMetaDataImpl.createRoot(false, ntManagerProvider.getEffectiveNodeTypeProvider());
         node = root.addChildNode(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
                 ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
-                ValidationMessageSeverity.ERROR,
                 createSimpleNodeContext("versionedNode"), "rep:versionStorage");
         // add child node with protected node which is ACL (i.e. accepted)
         node.addChildNode(ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(),
                 ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
-                ValidationMessageSeverity.ERROR,
                 createSimpleNodeContext("rep:policy"), "rep:Policy");
         // add child node with protected node which is not ACL (i.e. not accepted)
         root = JcrNodeTypeMetaDataImpl.createRoot(false, ntManagerProvider.getEffectiveNodeTypeProvider());
         node.addChildNode(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
                 ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
-                ValidationMessageSeverity.ERROR,
                 nodeContext, "nt:versionHistory");
         ValidationExecutorTest.assertViolation(node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
                 ntManagerProvider.getItemDefinitionProvider(),
-                ValidationMessageSeverity.ERROR, filter), new ValidationMessage(ValidationMessageSeverity.ERROR,
-                String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_NOT_ALLOWED, "name", "nt:versionHistory", "rep:versionStorage",
+                ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, filter), new ValidationMessage(ValidationMessageSeverity.ERROR,
+                String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_NOT_ALLOWED, "name", "nt:versionHistory", "types [rep:versionStorage]",
                         JcrNodeTypeMetaDataImpl.CONSTRAINT_CHILD_NODE_PROTECTED), nodeContext));
 
         // add valid child node
         root = JcrNodeTypeMetaDataImpl.createRoot(false, ntManagerProvider.getEffectiveNodeTypeProvider());
         node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, createSimpleNodeContext("name"),
+                ntManagerProvider.getItemDefinitionProvider(), createSimpleNodeContext("name"),
                 "my:nodeType1");
         // below that add auto-created child node
         nodeContext = createSimpleNodeContext("my:autoCreatedChild1");
         node.addChildNode(ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR,
+                ntManagerProvider.getItemDefinitionProvider(), 
                 nodeContext, "my:nodeType2");
         // and next to it a child node which is not allowed
         NodeContext nodeContext2 = createSimpleNodeContext("name2");
         node.addChildNode(ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, nodeContext2,
+                ntManagerProvider.getItemDefinitionProvider(), nodeContext2,
                 "my:nodeType1");
         ValidationExecutorTest.assertViolation(node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
                 ntManagerProvider.getItemDefinitionProvider(),
-                ValidationMessageSeverity.ERROR, filter), 
+                ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, filter), 
                 new ValidationMessage(ValidationMessageSeverity.ERROR,
                         String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_NOT_ALLOWED, "my:autoCreatedChild1", "my:nodeType2",
-                                "my:nodeType1",
+                                "types [my:nodeType1]",
                                 JcrNodeTypeMetaDataImpl.CONSTRAINT_CHILD_NODE_AUTO_CREATED), nodeContext),
                 new ValidationMessage(ValidationMessageSeverity.ERROR,
-                String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_NOT_ALLOWED, "name2", "my:nodeType1", "my:nodeType1",
+                String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_NOT_ALLOWED, "name2", "my:nodeType1", "types [my:nodeType1]",
                         JcrNodeTypeMetaDataImpl.CONSTRAINT_CHILD_NODE_NOT_ALLOWED), nodeContext2));
     }
 
@@ -231,7 +223,7 @@ public class JcrNodeTypeMetaDataImplTest {
         // add valid node
         JcrNodeTypeMetaData node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, createSimpleNodeContext("name"),
+                ntManagerProvider.getItemDefinitionProvider(), createSimpleNodeContext("name"),
                 "my:nodeType1");
 
         DefaultWorkspaceFilter filter = new DefaultWorkspaceFilter();
@@ -239,71 +231,72 @@ public class JcrNodeTypeMetaDataImplTest {
         // mandatory child node missing outside filter
         Collection<ValidationMessage> messages = root.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
                 ntManagerProvider.getItemDefinitionProvider(),
-                ValidationMessageSeverity.ERROR, filter);
+                ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, filter);
         MatcherAssert.assertThat(messages, AnyValidationMessageMatcher.noValidationInCollection());
 
         node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, createSimpleNodeContext("name2"),
+                ntManagerProvider.getItemDefinitionProvider(), createSimpleNodeContext("name2"),
                 "my:nodeType1");
         
         // mandatory child node missing inside filter
         filter.add(new PathFilterSet("/"));
         messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(),ValidationMessageSeverity.ERROR, filter);
+                ntManagerProvider.getItemDefinitionProvider(),ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, filter);
         ValidationExecutorTest.assertViolation(messages, new ValidationMessage(ValidationMessageSeverity.ERROR,
-                String.format(JcrNodeTypeMetaDataImpl.MESSAGE_MANDATORY_CHILD_NODE_MISSING, "my:namedChild1 [my:nodeType1]", "my:nodeType1",
+                String.format(JcrNodeTypeMetaDataImpl.MESSAGE_MANDATORY_CHILD_NODE_MISSING, "my:namedChild1 [my:nodeType1]", "types [my:nodeType1]",
                         "/name2")));
 
         // calling a second time will not lead to anything
         messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, filter);
+                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, filter);
         MatcherAssert.assertThat(messages, AnyValidationMessageMatcher.noValidationInCollection());
         
         // now add mandatory child node
         node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, createSimpleNodeContext("name3"),
+                ntManagerProvider.getItemDefinitionProvider(), createSimpleNodeContext("name3"),
                 "my:nodeType1");
         
         node.addChildNode(ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, createSimpleNodeContext("my:namedChild1"),
+                ntManagerProvider.getItemDefinitionProvider(), createSimpleNodeContext("my:namedChild1"),
                 "my:nodeType1");
         messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR,
+                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, 
                 new DefaultWorkspaceFilter());
         MatcherAssert.assertThat(messages, AnyValidationMessageMatcher.noValidationInCollection());
 
         // add arbitrary property to root
         MatcherAssert.assertThat(root.addProperty(createSimpleNodeContext("/"), ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, "property", false,
+                ntManagerProvider.getItemDefinitionProvider(),ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR,  "property", false,
                 ValueFactoryImpl.getInstance().createValue("foo")), AnyValidationMessageMatcher.noValidationInCollection());
         
         NodeContext nodeContext = createSimpleNodeContext("nodeForMandatoryProperties");
         node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, nodeContext, "my:nodeType2");
+                ntManagerProvider.getItemDefinitionProvider(), nodeContext, "my:nodeType2");
         messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(),ValidationMessageSeverity.ERROR, filter);
+                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, filter);
         ValidationExecutorTest.assertViolation(messages, new ValidationMessage(ValidationMessageSeverity.ERROR,
-                String.format(JcrNodeTypeMetaDataImpl.MESSAGE_MANDATORY_PROPERTY_MISSING, "my:mandatoryProperty", "my:nodeType2",
+                String.format(JcrNodeTypeMetaDataImpl.MESSAGE_MANDATORY_PROPERTY_MISSING, "my:mandatoryProperty", "types [my:nodeType2]",
                         "/nodeForMandatoryProperties"), nodeContext));
 
         nodeContext = createSimpleNodeContext("nodeForMandatoryProperties2");
         node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, nodeContext, "my:nodeType2");
+                ntManagerProvider.getItemDefinitionProvider(), nodeContext, "my:nodeType2");
+        // TODO: assert return value
         node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
                 ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
-                ValidationMessageSeverity.ERROR,
+                ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, 
                 "my:mandatoryProperty", false, ValueFactoryImpl.getInstance().createValue("foo"));
         messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, filter);
+                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, filter);
         ValidationExecutorTest.assertViolation(messages, new ValidationMessage(ValidationMessageSeverity.ERROR,
                 String.format(JcrNodeTypeMetaDataImpl.MESSAGE_MANDATORY_PROPERTY_WITH_WRONG_TYPE, "my:mandatoryProperty", "String", "Date",
-                        "my:nodeType2"), nodeContext));
+                        "types [my:nodeType2]"), nodeContext));
     }
 
     @Test
@@ -317,29 +310,29 @@ public class JcrNodeTypeMetaDataImplTest {
         // add valid node
         JcrNodeTypeMetaData node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, createSimpleNodeContext("name"),
+                ntManagerProvider.getItemDefinitionProvider(), createSimpleNodeContext("name"),
                 "my:nodeType1");
 
         DefaultWorkspaceFilter filter = new DefaultWorkspaceFilter();
 
         node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, createSimpleNodeContext("name2"),
+                ntManagerProvider.getItemDefinitionProvider(), 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(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(),  ValidationMessageSeverity.ERROR, filter);
+                ntManagerProvider.getItemDefinitionProvider(),  ValidationMessageSeverity.ERROR, 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");
+                ntManagerProvider.getItemDefinitionProvider(), nodeContext, "my:nodeType2");
         messages = node.finalizeValidation(ntManagerProvider.getNamePathResolver(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, filter);
+                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, filter);
         MatcherAssert.assertThat(messages, AnyValidationMessageMatcher.noValidationInCollection());
     }
     
@@ -348,7 +341,7 @@ public class JcrNodeTypeMetaDataImplTest {
         root.addProperty(createSimpleNodeContext("/"), ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(),
                 ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
-                ValidationMessageSeverity.ERROR,
+                ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, 
                 "invalid:property", false, ValueFactoryImpl.getInstance().createValue("foo"));
     }
 
@@ -364,65 +357,65 @@ public class JcrNodeTypeMetaDataImplTest {
         // add arbitrary property to root
         MatcherAssert.assertThat(root.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, "property", false,
+                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, "property", false,
                 ValueFactoryImpl.getInstance().createValue("foo")), AnyValidationMessageMatcher.noValidationInCollection());
 
         JcrNodeTypeMetaData node = root.addChildNode(ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, createSimpleNodeContext("child"),
+                ntManagerProvider.getItemDefinitionProvider(), createSimpleNodeContext("child"),
                 "my:nodeType3");
 
         // not allowed (wrong type)
         ValidationExecutorTest.assertViolation( node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, "property", false,
+                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR,  "property", false,
                 ValueFactoryImpl.getInstance().createValue("foo")),
                 new ValidationMessage(ValidationMessageSeverity.ERROR,
                         String.format(JcrNodeTypeMetaDataImpl.MESSAGE_PROPERTY_NOT_ALLOWED, "property",
-                                "String", "my:nodeType3", JcrNodeTypeMetaDataImpl.CONSTRAINT_PROPERTY_NOT_ALLOWED),
+                                "String", "types [my:nodeType3]", JcrNodeTypeMetaDataImpl.CONSTRAINT_PROPERTY_NOT_ALLOWED),
                         nodeContext));
 
         // protected but nevertheless allowed
         MatcherAssert.assertThat(node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, "jcr:primaryType", false,
+                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, "jcr:primaryType", false,
                 ValueFactoryImpl.getInstance().createValue("foo")), AnyValidationMessageMatcher.noValidationInCollection());
 
         // protected
         ValidationExecutorTest.assertViolation(node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
                 ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
-                ValidationMessageSeverity.ERROR,
+                ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, 
                 "my:protected", false, ValueFactoryImpl.getInstance().createValue("foo")),
-                new ValidationMessage(ValidationMessageSeverity.ERROR, String.format(JcrNodeTypeMetaDataImpl.MESSAGE_PROPERTY_NOT_ALLOWED,
-                        "my:protected", "String", "my:nodeType3", JcrNodeTypeMetaDataImpl.CONSTRAINT_PROPERTY_PROTECTED), nodeContext));
+                new ValidationMessage(ValidationMessageSeverity.ERROR,  String.format(JcrNodeTypeMetaDataImpl.MESSAGE_PROPERTY_NOT_ALLOWED,
+                        "my:protected", "String", "types [my:nodeType3]", JcrNodeTypeMetaDataImpl.CONSTRAINT_PROPERTY_PROTECTED), nodeContext));
 
         // multi value where single value is required
         ValidationExecutorTest.assertViolation(node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(),
                 ntManagerProvider.getEffectiveNodeTypeProvider(), ntManagerProvider.getNodeTypeDefinitionProvider(),
-                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, "my:property1", true,
+                ntManagerProvider.getItemDefinitionProvider(), ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, "my:property1", true,
                 ValueFactoryImpl.getInstance().createValue("foo"), ValueFactoryImpl.getInstance().createValue("bar")),
                 new ValidationMessage(ValidationMessageSeverity.ERROR, String.format(JcrNodeTypeMetaDataImpl.MESSAGE_PROPERTY_NOT_ALLOWED,
-                        "my:property1", "String", "my:nodeType3", JcrNodeTypeMetaDataImpl.CONSTRAINT_PROPERTY_NOT_ALLOWED), nodeContext));
+                        "my:property1", "String", "types [my:nodeType3]", JcrNodeTypeMetaDataImpl.CONSTRAINT_PROPERTY_NOT_ALLOWED), nodeContext));
 
         // constrained property
         MatcherAssert.assertThat(node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
                 ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
-                ValidationMessageSeverity.ERROR,
+                ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, 
                 "my:constrainedStringProperty", false, ValueFactoryImpl.getInstance().createValue("prefix1foo")),
                 AnyValidationMessageMatcher.noValidationInCollection());
 
         MatcherAssert.assertThat(node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
                 ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
-                ValidationMessageSeverity.ERROR,
+                ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, 
                 "my:constrainedStringProperty", false, ValueFactoryImpl.getInstance().createValue("foosuffix1")),
                 AnyValidationMessageMatcher.noValidationInCollection());
 
         ValidationExecutorTest.assertViolation( node.addProperty(nodeContext, ntManagerProvider.getNamePathResolver(), ntManagerProvider.getEffectiveNodeTypeProvider(),
                 ntManagerProvider.getNodeTypeDefinitionProvider(), ntManagerProvider.getItemDefinitionProvider(),
-                ValidationMessageSeverity.ERROR,
+                ValidationMessageSeverity.ERROR, ValidationMessageSeverity.ERROR, 
                 "my:constrainedStringProperty", false, ValueFactoryImpl.getInstance().createValue("foo")),
                 new ValidationMessage(ValidationMessageSeverity.ERROR, String.format(JcrNodeTypeMetaDataImpl.MESSAGE_PROPERTY_NOT_ALLOWED,
-                        "my:constrainedStringProperty", "String", "my:nodeType3",
+                        "my:constrainedStringProperty", "String", "types [my:nodeType3]",
                         String.format(JcrNodeTypeMetaDataImpl.CONSTRAINT_PROPERTY_VALUE,
                                 "'foo' does not satisfy the constraint '.*suffix1'")),
                         nodeContext));
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 382649e..81afbb1 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
@@ -79,7 +79,7 @@ public class NodeTypeValidatorTest {
             }
         }
         return new NodeTypeValidator(false, filter, ntManagerProvider, defaultNodeType, ValidationMessageSeverity.ERROR,
-                ValidationMessageSeverity.WARN);
+                ValidationMessageSeverity.WARN, ValidationMessageSeverity.WARN);
     }
 
     @Test
@@ -101,7 +101,7 @@ public class NodeTypeValidatorTest {
         node = new DocViewNode("test", "test", null, props, null, "nt:folder");
         ValidationExecutorTest.assertViolation(validator.validate(node, nodeContext, false),
                 new ValidationMessage(ValidationMessageSeverity.ERROR,
-                        String.format(JcrNodeTypeMetaDataImpl.MESSAGE_PROPERTY_NOT_ALLOWED, "prop1", "String", "nt:folder",
+                        String.format(JcrNodeTypeMetaDataImpl.MESSAGE_PROPERTY_NOT_ALLOWED, "prop1", "String", "types [nt:folder]",
                                 "No applicable property definition found for name and type!"), nodeContext));
     }
 
@@ -137,9 +137,9 @@ public class NodeTypeValidatorTest {
         DocViewNode node = new DocViewNode("jcr:root", "jcr:root", null, props, null, JcrConstants.NT_UNSTRUCTURED);
         MatcherAssert.assertThat(validator.validate(node, nodeContext, false), AnyValidationMessageMatcher.noValidationInCollection());
         ValidationExecutorTest.assertViolation(validator.done(),
-                new ValidationMessage(ValidationMessageSeverity.ERROR,
-                        String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_OF_NOT_CONTAINED_PARENT_POTENTIALLY_NOT_ALLOWED,
-                                "test", "nt:unstructured", JcrConstants.NT_FOLDER,
+                new ValidationMessage(ValidationMessageSeverity.WARN,
+                        String.format(JcrNodeTypeMetaDataImpl.MESSAGE_CHILD_NODE_NOT_ALLOWED,
+                                "test", "nt:unstructured", "potential default types ["+JcrConstants.NT_FOLDER + "]",
                                 "Node type does not allow arbitrary child nodes and does not allow this specific name and node type either!"), nodeContext));
     }
 
@@ -184,7 +184,7 @@ public class NodeTypeValidatorTest {
         ValidationExecutorTest.assertViolation(validator.done(),
                 new ValidationMessage(ValidationMessageSeverity.ERROR,
                         String.format(JcrNodeTypeMetaDataImpl.MESSAGE_MANDATORY_PROPERTY_MISSING,
-                                "rep:principalName", "rep:SystemUser", nodeContext.getNodePath()), nodeContext));
+                                "rep:principalName", "types [rep:SystemUser]", nodeContext.getNodePath()), nodeContext));
     }
 
     @Test
@@ -200,7 +200,7 @@ public class NodeTypeValidatorTest {
         ValidationExecutorTest.assertViolation(validator.done(),
                 new ValidationMessage(ValidationMessageSeverity.ERROR,
                         String.format(JcrNodeTypeMetaDataImpl.MESSAGE_MANDATORY_CHILD_NODE_MISSING,
-                                "jcr:content [nt:base]", "nt:file", "/apps/test/node4")));
+                                "jcr:content [nt:base]", "types [nt:file]", "/apps/test/node4")));
         MatcherAssert.assertThat(validator.done(), AnyValidationMessageMatcher.noValidationInCollection());
     }
 
@@ -217,7 +217,7 @@ public class NodeTypeValidatorTest {
         DocViewNode node = new DocViewNode("jcr:root", "jcr:root", null, props, null, JcrConstants.NT_FILE);
         ValidationExecutorTest.assertViolation(validator.validate(node, nodeContext, false),
                 new ValidationMessage(ValidationMessageSeverity.ERROR,
-                        String.format(JcrNodeTypeMetaDataImpl.MESSAGE_PROPERTY_NOT_ALLOWED, "invalid-prop", "String", JcrConstants.NT_FILE,
+                        String.format(JcrNodeTypeMetaDataImpl.MESSAGE_PROPERTY_NOT_ALLOWED, "invalid-prop", "String", "types [" + JcrConstants.NT_FILE + "]",
                                 "No applicable property definition found for name and type!"), nodeContext));
     }