Author: kwin
Date: Fri Mar  3 08:26:32 2017
New Revision: 1785229

URL: http://svn.apache.org/viewvc?rev=1785229&view=rev
Log:
SLING-6569 fall back to default resource bundle in case 
ValidationFailure.getMessage() is called with a null value

Modified:
    
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/ValidationFailure.java
    
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/spi/DefaultValidationFailure.java
    
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/spi/DefaultValidationResult.java
    
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/spi/ValidationContext.java
    sling/trunk/bundles/extensions/validation/core/pom.xml
    
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/CompositeValidationResult.java
    
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationContextImpl.java
    
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationModelRetrieverImpl.java
    
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationServiceImpl.java
    
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/validators/RegexValidator.java
    
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationServiceImplTest.java

Modified: 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/ValidationFailure.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/ValidationFailure.java?rev=1785229&r1=1785228&r2=1785229&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/ValidationFailure.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/ValidationFailure.java
 Fri Mar  3 08:26:32 2017
@@ -28,10 +28,10 @@ import org.osgi.annotation.versioning.Pr
 public interface ValidationFailure {
 
     /**
-     * @param resourceBundle ResourceBundle in which to look up the according 
message (used for i18n)
+     * @param resourceBundle ResourceBundle in which to look up the according 
message (used for i18n), if {@code null} is given, the default resource bundle 
is used.
      * @return the failure message
      */
-    @Nonnull String getMessage(@Nonnull ResourceBundle resourceBundle);
+    @Nonnull String getMessage(ResourceBundle resourceBundle);
 
     /**
      * Returns the relative location of the property/resource/value which 
triggered this validation failure.

Modified: 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/spi/DefaultValidationFailure.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/spi/DefaultValidationFailure.java?rev=1785229&r1=1785228&r2=1785229&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/spi/DefaultValidationFailure.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/spi/DefaultValidationFailure.java
 Fri Mar  3 08:26:32 2017
@@ -35,6 +35,7 @@ public class DefaultValidationFailure im
     private final @Nonnull String location;
     private final @Nonnull String messageKey;
     private final Object[] messageArguments;
+    private final @Nonnull ResourceBundle defaultResourceBundle;
     private final int severity;
 
     public final static int DEFAULT_SEVERITY = 0;
@@ -44,10 +45,12 @@ public class DefaultValidationFailure im
      * and formatting it using the given messageArguments via {@link 
MessageFormat#format(String, Object...)}.
      * @param location the location
      * @param severity the severity of this failure (may be {@code null}), 
which leads to setting it to the {@link #DEFAULT_SEVERITY}
+     * @param defaultResourceBundle the default resourceBundle which is used 
to resolve the {@link messageKey} in {@link #getMessage(ResourceBundle)}
+     *  if {@code null} is provided as parameter.
      * @param messageKey the key to look up in the resource bundle
      * @param messageArguments the arguments to be used with the looked up 
value from the resource bundle (given in {@link #getMessage(ResourceBundle)}
      */
-    public DefaultValidationFailure(@Nonnull String location, Integer 
severity, @Nonnull String messageKey, Object... messageArguments) {
+    public DefaultValidationFailure(@Nonnull String location, Integer 
severity, @Nonnull ResourceBundle defaultResourceBundle, @Nonnull String 
messageKey, Object... messageArguments) {
         this.location = location;
         if (severity != null) {
             this.severity = severity;
@@ -56,13 +59,14 @@ public class DefaultValidationFailure im
         }
         this.messageKey = messageKey;
         this.messageArguments = messageArguments;
+        this.defaultResourceBundle = defaultResourceBundle;
     }
 
     @SuppressWarnings("null")
     @Override
-    public @Nonnull String getMessage(@Nonnull ResourceBundle resourceBundle) {
+    public @Nonnull String getMessage(ResourceBundle resourceBundle) {
         if (resourceBundle == null) {
-            throw new NullPointerException("ResourceBundle must not be null");
+            resourceBundle = defaultResourceBundle;
         }
         return MessageFormat.format(resourceBundle.getString(messageKey), 
messageArguments);
     }

Modified: 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/spi/DefaultValidationResult.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/spi/DefaultValidationResult.java?rev=1785229&r1=1785228&r2=1785229&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/spi/DefaultValidationResult.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/spi/DefaultValidationResult.java
 Fri Mar  3 08:26:32 2017
@@ -22,6 +22,7 @@ import java.text.MessageFormat;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.ResourceBundle;
 
 import javax.annotation.Nonnull;
 
@@ -47,12 +48,13 @@ public class DefaultValidationResult imp
      * and formatting it using the given messageArguments via {@link 
MessageFormat#format(String, Object...)}.
      * @param location the location.
      * @param severity the severity of the embedded failure (may be {@code 
null}), which leads to setting it to the {@link #DEFAULT_SEVERITY}.
+     * @param defaultResourceBundle the default resourceBundle which is used 
to resolve the {@link messageKey} if no other bundle is provided.
      * @param messageKey the message key used for looking up a value in the 
resource bundle given in {@link 
ValidationFailure#getMessage(java.util.ResourceBundle)}.
      * @param messageArguments optional number of arguments being used in 
{@link MessageFormat#format(String, Object...)}
      */
-    public DefaultValidationResult(@Nonnull String location, Integer severity, 
@Nonnull String messageKey, Object... messageArguments) {
+    public DefaultValidationResult(@Nonnull String location, Integer severity, 
@Nonnull ResourceBundle defaultResourceBundle, @Nonnull String messageKey, 
Object... messageArguments) {
         this.isValid = false;
-        this.failures = Collections.<ValidationFailure>singletonList(new 
DefaultValidationFailure(location, severity, messageKey, messageArguments));
+        this.failures = Collections.<ValidationFailure>singletonList(new 
DefaultValidationFailure(location, severity, defaultResourceBundle, messageKey, 
messageArguments));
     }
 
     public DefaultValidationResult(ValidationFailure... failures) {

Modified: 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/spi/ValidationContext.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/spi/ValidationContext.java?rev=1785229&r1=1785228&r2=1785229&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/spi/ValidationContext.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/spi/ValidationContext.java
 Fri Mar  3 08:26:32 2017
@@ -18,6 +18,8 @@
  */
 package org.apache.sling.validation.spi;
 
+import java.util.ResourceBundle;
+
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 
@@ -54,4 +56,10 @@ public interface ValidationContext {
      * @return the severity of the validation failure. May be {@code null} 
when no explicit severity has been set in the model.
      */
     @CheckForNull Integer getSeverity();
+    
+    /**
+     * The default resource bundle which should be able to give out the error 
message of the validator in English. 
+     * @return
+     */
+    @Nonnull ResourceBundle getDefaultResourceBundle();
 }

Modified: sling/trunk/bundles/extensions/validation/core/pom.xml
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/pom.xml?rev=1785229&r1=1785228&r2=1785229&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/validation/core/pom.xml (original)
+++ sling/trunk/bundles/extensions/validation/core/pom.xml Fri Mar  3 08:26:32 
2017
@@ -102,6 +102,12 @@
         </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.i18n</artifactId>
+            <version>2.2.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.validation.api</artifactId>
             <version>1.0.0-SNAPSHOT</version>
             <scope>provided</scope>

Modified: 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/CompositeValidationResult.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/CompositeValidationResult.java?rev=1785229&r1=1785228&r2=1785229&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/CompositeValidationResult.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/CompositeValidationResult.java
 Fri Mar  3 08:26:32 2017
@@ -21,6 +21,7 @@ package org.apache.sling.validation.impl
 import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.ResourceBundle;
 
 import javax.annotation.Nonnull;
 
@@ -43,8 +44,8 @@ public class CompositeValidationResult i
         results.add(result);
     }
 
-    public void addFailure(@Nonnull String location, Integer severity, 
@Nonnull String message, Object... messageArguments) {
-        results.add(new DefaultValidationResult(location, severity, message, 
messageArguments));
+    public void addFailure(@Nonnull String location, Integer severity, 
@Nonnull ResourceBundle defaultResourceBundle, @Nonnull String message, 
Object... messageArguments) {
+        results.add(new DefaultValidationResult(location, severity, 
defaultResourceBundle, message, messageArguments));
     }
 
     /**

Modified: 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationContextImpl.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationContextImpl.java?rev=1785229&r1=1785228&r2=1785229&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationContextImpl.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationContextImpl.java
 Fri Mar  3 08:26:32 2017
@@ -18,6 +18,8 @@
  */
 package org.apache.sling.validation.impl;
 
+import java.util.ResourceBundle;
+
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 
@@ -31,13 +33,15 @@ public class ValidationContextImpl imple
     private final Integer severity;
     private final @Nonnull ValueMap valueMap;
     private final Resource resource;
+    private final @Nonnull ResourceBundle defaultResourceBundle;
 
-    public ValidationContextImpl(@Nonnull String location, Integer severity,  
@Nonnull ValueMap valueMap, Resource resource) {
+    public ValidationContextImpl(@Nonnull String location, Integer severity,  
@Nonnull ValueMap valueMap, Resource resource, @Nonnull ResourceBundle 
defaultResourceBundle) {
         super();
         this.location = location;
         this.severity = severity;
         this.valueMap = valueMap;
         this.resource = resource;
+        this.defaultResourceBundle = defaultResourceBundle;
     }
 
     @Override
@@ -64,4 +68,9 @@ public class ValidationContextImpl imple
         return severity;
     }
 
+    @Override
+    public @Nonnull ResourceBundle getDefaultResourceBundle() {
+        return defaultResourceBundle;
+    }
+
 }

Modified: 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationModelRetrieverImpl.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationModelRetrieverImpl.java?rev=1785229&r1=1785228&r2=1785229&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationModelRetrieverImpl.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationModelRetrieverImpl.java
 Fri Mar  3 08:26:32 2017
@@ -52,7 +52,7 @@ import org.slf4j.LoggerFactory;
 public class ValidationModelRetrieverImpl implements ValidationModelRetriever {
 
     /** 
-     * Map of validation providers (key=service properties), Declarative 
Services 1.3 takes care that the list is ordered according to {@link 
ServiceReference#compareTo(Object)}.
+     * List of validation providers, Declarative Services 1.3 takes care that 
the list is ordered according to {@link ServiceReference#compareTo(Object)}.
      * Highest ranked service is the last one in the list.
      * 
      * @see OSGi R6 Comp, 112.3.8.1

Modified: 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationServiceImpl.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationServiceImpl.java?rev=1785229&r1=1785228&r2=1785229&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationServiceImpl.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationServiceImpl.java
 Fri Mar  3 08:26:32 2017
@@ -22,6 +22,8 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Locale;
+import java.util.ResourceBundle;
 import java.util.function.Predicate;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -36,6 +38,7 @@ import org.apache.sling.api.resource.Res
 import org.apache.sling.api.resource.ResourceResolverFactory;
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.api.wrappers.ValueMapDecorator;
+import org.apache.sling.i18n.ResourceBundleProvider;
 import org.apache.sling.serviceusermapping.ServiceUserMapped;
 import org.apache.sling.validation.SlingValidationException;
 import org.apache.sling.validation.ValidationResult;
@@ -46,9 +49,13 @@ import org.apache.sling.validation.model
 import org.apache.sling.validation.model.ValidationModel;
 import org.apache.sling.validation.spi.ValidationContext;
 import org.apache.sling.validation.spi.Validator;
+import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -62,7 +69,6 @@ public class ValidationServiceImpl imple
     protected static final String 
I18N_KEY_MISSING_REQUIRED_PROPERTY_MATCHING_PATTERN = 
"sling.validator.missing-required-property-matching-pattern";
     protected static final String 
I18N_KEY_MISSING_REQUIRED_CHILD_RESOURCE_WITH_NAME = 
"sling.validator.missing-required-child-resource-with-name";
     protected static final String 
I18N_KEY_MISSING_REQUIRED_CHILD_RESOURCE_MATCHING_PATTERN = 
"sling.validator.missing-required-child-resource-matching-pattern";
-    
 
     private static final Logger LOG = 
LoggerFactory.getLogger(ValidationServiceImpl.class);
     
@@ -75,10 +81,19 @@ public class ValidationServiceImpl imple
     
     @Reference
     private ResourceResolverFactory rrf = null;
+    
+    /** 
+     * List of resource bundle providers, Declarative Services 1.3 takes care 
that the list is ordered according to {@link 
ServiceReference#compareTo(Object)}.
+     * Highest ranked service is the last one in the list.
+     * 
+     * @see OSGi R6 Comp, 112.3.8.1
+     */
+    @Reference(policy=ReferencePolicy.DYNAMIC, 
cardinality=ReferenceCardinality.AT_LEAST_ONE, 
policyOption=ReferencePolicyOption.GREEDY)
+    volatile List<ResourceBundleProvider> resourceBundleProviders;
 
     @Reference
     private ServiceUserMapped serviceUserMapped;
-    
+
     @Activate
     public void activate(ValidationServiceConfiguration configuration) {
         this.configuration = configuration;
@@ -94,7 +109,6 @@ public class ValidationServiceImpl imple
             }
         }
     }
-    
 
     // ValidationService 
###################################################################################################################
     
@@ -145,11 +159,25 @@ public class ValidationServiceImpl imple
     public @Nonnull ValidationResult validate(@Nonnull Resource resource, 
@Nonnull ValidationModel model) {
         return validate(resource, model, "");
     }
-    
+
+    private @Nonnull ResourceBundle getDefaultResourceBundle() {
+        Locale locale = Locale.ENGLISH;
+        // go from highest ranked to lowest ranked providers
+        for (int i = resourceBundleProviders.size() - 1; i >= 0; i--) {
+            ResourceBundleProvider resourceBundleProvider = 
resourceBundleProviders.get(i);
+            ResourceBundle defaultResourceBundle = 
resourceBundleProvider.getResourceBundle(locale);
+            if (defaultResourceBundle != null) {
+                return defaultResourceBundle;
+            }
+        }
+        throw new IllegalStateException("There is no resource provider in the 
system, providing a resource bundle for locale");
+    }
+
     protected @Nonnull ValidationResult validate(@Nonnull Resource resource, 
@Nonnull ValidationModel model, @Nonnull String relativePath) {
         if (resource == null || model == null || relativePath == null) {
             throw new IllegalArgumentException("ValidationService.validate - 
cannot accept null parameters");
         }
+        ResourceBundle defaultResourceBundle = getDefaultResourceBundle();
         CompositeValidationResult result = new CompositeValidationResult();
         ValueMap valueMap = resource.adaptTo(ValueMap.class);
         if (valueMap == null) {
@@ -158,10 +186,10 @@ public class ValidationServiceImpl imple
         }
 
         // validate direct properties of the resource
-        validateValueMap(valueMap, resource, relativePath, 
model.getResourceProperties(), result );
+        validateValueMap(valueMap, resource, relativePath, 
model.getResourceProperties(), result, defaultResourceBundle);
 
         // validate child resources, if any
-        validateChildren(resource, relativePath, model.getChildren(), result);
+        validateChildren(resource, relativePath, model.getChildren(), result, 
defaultResourceBundle);
         
         // optionally put result to cache
         if (configuration.cacheValidationResultsOnResources()) {
@@ -179,7 +207,7 @@ public class ValidationServiceImpl imple
      * @param result
      * @param childResources
      */
-    private void validateChildren(Resource resource, String relativePath, 
Collection<ChildResource> childResources, CompositeValidationResult result) {
+    private void validateChildren(Resource resource, String relativePath, 
Collection<ChildResource> childResources, CompositeValidationResult result,  
ResourceBundle defaultResourceBundle) {
         // validate children resources, if any
         for (ChildResource childResource : childResources) {
             // if a pattern is set we validate all children matching that 
pattern
@@ -189,33 +217,33 @@ public class ValidationServiceImpl imple
                 for (Resource child : resource.getChildren()) {
                     Matcher matcher = pattern.matcher(child.getName());
                     if (matcher.matches()) {
-                       validateChildResource(child, relativePath, 
childResource, result);
+                       validateChildResource(child, relativePath, 
childResource, result, defaultResourceBundle);
                        foundMatch = true;
                     }
                 }
                 if (!foundMatch && childResource.isRequired()) {
-                    result.addFailure(relativePath, null, 
I18N_KEY_MISSING_REQUIRED_CHILD_RESOURCE_MATCHING_PATTERN, pattern.toString());
+                    result.addFailure(relativePath, null, 
defaultResourceBundle, 
I18N_KEY_MISSING_REQUIRED_CHILD_RESOURCE_MATCHING_PATTERN, pattern.toString());
                 }
             } else {
                 Resource expectedResource = 
resource.getChild(childResource.getName());
                 if (expectedResource != null) {
-                    validateChildResource(expectedResource, relativePath, 
childResource, result);
+                    validateChildResource(expectedResource, relativePath, 
childResource, result, defaultResourceBundle);
                 } else if (childResource.isRequired()) {
-                    result.addFailure(relativePath, null, 
I18N_KEY_MISSING_REQUIRED_CHILD_RESOURCE_WITH_NAME, childResource.getName());
+                    result.addFailure(relativePath, null, 
defaultResourceBundle, I18N_KEY_MISSING_REQUIRED_CHILD_RESOURCE_WITH_NAME, 
childResource.getName());
                 }
             } 
         }
     }
 
-    private void validateChildResource(Resource resource, String 
relativePathOfParent, ChildResource childResource, CompositeValidationResult 
result) {
+    private void validateChildResource(Resource resource, String 
relativePathOfParent, ChildResource childResource, CompositeValidationResult 
result,  ResourceBundle defaultResourceBundle) {
         final String relativePath;
         if (relativePathOfParent.isEmpty()) {
             relativePath = resource.getName();
         } else {
             relativePath = relativePathOfParent +  "/" + resource.getName();
         }
-        validateValueMap(resource.adaptTo(ValueMap.class), resource, 
relativePath, childResource.getProperties(), result);
-        validateChildren(resource, relativePath, childResource.getChildren(), 
result);
+        validateValueMap(resource.adaptTo(ValueMap.class), resource, 
relativePath, childResource.getProperties(), result, defaultResourceBundle);
+        validateChildren(resource, relativePath, childResource.getChildren(), 
result, defaultResourceBundle);
     }
 
     @Override
@@ -223,8 +251,9 @@ public class ValidationServiceImpl imple
         if (valueMap == null || model == null) {
             throw new IllegalArgumentException("ValidationResult.validate - 
cannot accept null parameters");
         }
+        ResourceBundle defaultResourceBundle = getDefaultResourceBundle();
         CompositeValidationResult result = new CompositeValidationResult();
-        validateValueMap(valueMap, null, "", model.getResourceProperties(), 
result);
+        validateValueMap(valueMap, null, "", model.getResourceProperties(), 
result, defaultResourceBundle);
         return result;
     }    
 
@@ -237,7 +266,7 @@ public class ValidationServiceImpl imple
     }
 
     private void validateValueMap(ValueMap valueMap, Resource resource, String 
relativePath, Collection<ResourceProperty> resourceProperties,
-            CompositeValidationResult result) {
+            CompositeValidationResult result, ResourceBundle 
defaultResourceBundle) {
         if (valueMap == null) {
             throw new IllegalArgumentException("ValueMap may not be null");
         }
@@ -248,30 +277,30 @@ public class ValidationServiceImpl imple
                 for (String key : valueMap.keySet()) {
                     if (pattern.matcher(key).matches()) {
                         foundMatch = true;
-                        validatePropertyValue(key, valueMap, resource, 
relativePath, resourceProperty, result);
+                        validatePropertyValue(key, valueMap, resource, 
relativePath, resourceProperty, result, defaultResourceBundle);
                     }
                 }
                 if (!foundMatch && resourceProperty.isRequired()) {
-                    result.addFailure(relativePath, null, 
I18N_KEY_MISSING_REQUIRED_PROPERTY_MATCHING_PATTERN, pattern.toString());
+                    result.addFailure(relativePath, null, 
defaultResourceBundle, I18N_KEY_MISSING_REQUIRED_PROPERTY_MATCHING_PATTERN, 
pattern.toString());
                 }
             } else {
-                validatePropertyValue(resourceProperty.getName(), valueMap, 
resource, relativePath, resourceProperty, result);
+                validatePropertyValue(resourceProperty.getName(), valueMap, 
resource, relativePath, resourceProperty, result, defaultResourceBundle);
             }
         }
     }
 
-    private void validatePropertyValue(String property, ValueMap valueMap, 
Resource resource, String relativePath, ResourceProperty resourceProperty, 
CompositeValidationResult result) {
+    private void validatePropertyValue(String property, ValueMap valueMap, 
Resource resource, String relativePath, ResourceProperty resourceProperty, 
CompositeValidationResult result, ResourceBundle defaultResourceBundle) {
         Object fieldValues = valueMap.get(property);
         if (fieldValues == null) {
             if (resourceProperty.isRequired()) {
-                result.addFailure(relativePath, null, 
I18N_KEY_MISSING_REQUIRED_PROPERTY_WITH_NAME, property);
+                result.addFailure(relativePath, null, defaultResourceBundle, 
I18N_KEY_MISSING_REQUIRED_PROPERTY_WITH_NAME, property);
             }
             return;
         }
         List<ParameterizedValidator> validators = 
resourceProperty.getValidators();
         if (resourceProperty.isMultiple()) {
             if (!fieldValues.getClass().isArray()) {
-                result.addFailure(relativePath + property, null, 
I18N_KEY_EXPECTED_MULTIVALUE_PROPERTY);
+                result.addFailure(relativePath + property, null, 
defaultResourceBundle, I18N_KEY_EXPECTED_MULTIVALUE_PROPERTY);
                 return;
             }
         }
@@ -292,23 +321,23 @@ public class ValidationServiceImpl imple
             // see https://issues.apache.org/jira/browse/SLING-4178 for why 
the second check is necessary
             if (typedValue == null || (typedValue.length > 0 && typedValue[0] 
== null)) {
                 // here the missing required property case was already treated 
in validateValueMap
-                result.addFailure(relativePath + property, 
validator.getSeverity(), I18N_KEY_WRONG_PROPERTY_TYPE, validator.getType());
+                result.addFailure(relativePath + property, 
validator.getSeverity(), defaultResourceBundle, I18N_KEY_WRONG_PROPERTY_TYPE, 
validator.getType());
                 return;
             }
             
             // see https://issues.apache.org/jira/browse/SLING-662 for a 
description on how multivalue properties are treated with ValueMap
             if (validator.getType().isArray()) {
                 // ValueMap already returns an array in both cases (property 
is single value or multivalue)
-                validateValue(result, typedValue, property, relativePath, 
valueMap, resource, validator);
+                validateValue(result, typedValue, property, relativePath, 
valueMap, resource, validator, defaultResourceBundle);
             } else {
                 // call validate for each entry in the array (supports both 
singlevalue and multivalue)
                 @Nonnull Object[] array = (Object[])typedValue;
                 if (array.length == 1) {
-                   validateValue(result, array[0], property, relativePath, 
valueMap, resource, validator);
+                   validateValue(result, array[0], property, relativePath, 
valueMap, resource, validator, defaultResourceBundle);
                 } else {
                     int n = 0;
                     for (Object item : array) {
-                        validateValue(result, item, property + "[" + n++ + 
"]", relativePath, valueMap, resource, validator);
+                        validateValue(result, item, property + "[" + n++ + 
"]", relativePath, valueMap, resource, validator, defaultResourceBundle);
                     }
                 }
             }
@@ -316,10 +345,10 @@ public class ValidationServiceImpl imple
     }
     
     @SuppressWarnings("rawtypes")
-    private void validateValue(CompositeValidationResult result, @Nonnull 
Object value, String property, String relativePath, @Nonnull ValueMap valueMap, 
Resource resource, ParameterizedValidator validator) {
+    private void validateValue(CompositeValidationResult result, @Nonnull 
Object value, String property, String relativePath, @Nonnull ValueMap valueMap, 
Resource resource, ParameterizedValidator validator, ResourceBundle 
defaultResourceBundle) {
         try {
             @SuppressWarnings("unchecked")
-            ValidationContext validationContext = new 
ValidationContextImpl(relativePath + property, validator.getSeverity(), 
valueMap, resource);
+            ValidationContext validationContext = new 
ValidationContextImpl(relativePath + property, validator.getSeverity(), 
valueMap, resource, defaultResourceBundle);
             ValidationResult validatorResult = 
((Validator)validator.getValidator()).validate(value, validationContext, 
validator.getParameters());
             result.addValidationResult(validatorResult);
         } catch (SlingValidationException e) {

Modified: 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/validators/RegexValidator.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/validators/RegexValidator.java?rev=1785229&r1=1785228&r2=1785229&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/validators/RegexValidator.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/validators/RegexValidator.java
 Fri Mar  3 08:26:32 2017
@@ -54,7 +54,7 @@ public class RegexValidator implements V
             if (pattern.matcher((String)data).matches()) {
                 return DefaultValidationResult.VALID;
             }
-            return new DefaultValidationResult(context.getLocation(), 
context.getSeverity(), I18N_KEY_PATTERN_DOES_NOT_MATCH, regex);
+            return new DefaultValidationResult(context.getLocation(), 
context.getSeverity(), context.getDefaultResourceBundle(), 
I18N_KEY_PATTERN_DOES_NOT_MATCH, regex);
         } catch (PatternSyntaxException e) {
             throw new SlingValidationException("Given pattern in argument '" + 
REGEX_PARAM + "' is invalid", e);
         }

Modified: 
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationServiceImplTest.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationServiceImplTest.java?rev=1785229&r1=1785228&r2=1785229&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationServiceImplTest.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationServiceImplTest.java
 Fri Mar  3 08:26:32 2017
@@ -23,6 +23,7 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.ResourceBundle;
 import java.util.function.Predicate;
 
 import javax.annotation.CheckForNull;
@@ -40,6 +41,7 @@ import org.apache.sling.api.resource.Res
 import org.apache.sling.api.resource.SyntheticResource;
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.api.wrappers.ValueMapDecorator;
+import org.apache.sling.i18n.ResourceBundleProvider;
 import org.apache.sling.jcr.resource.JcrResourceConstants;
 import org.apache.sling.testing.mock.sling.junit.SlingContext;
 import org.apache.sling.validation.ValidationFailure;
@@ -64,6 +66,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
 
 @RunWith(MockitoJUnitRunner.class)
@@ -83,12 +86,20 @@ public class ValidationServiceImplTest {
 
     @Rule
     public SlingContext context = new SlingContext();
+    
+    @Mock
+    private ResourceBundle defaultResourceBundle;
+    
+    @Mock
+    private ResourceBundleProvider resourceBundleProvider;
 
     @Before
     public void setUp() throws LoginException, PersistenceException, 
RepositoryException {
         validationService = new ValidationServiceImpl();
         validationService.searchPaths = 
Arrays.asList(context.resourceResolver().getSearchPath());
         validationService.configuration = configuration;
+        validationService.resourceBundleProviders = 
Collections.singletonList(resourceBundleProvider);
+        
Mockito.doReturn(defaultResourceBundle).when(resourceBundleProvider).getResourceBundle(Mockito.anyObject());
         modelBuilder = new ValidationModelBuilder();
         propertyBuilder = new ResourcePropertyBuilder();
     }
@@ -107,7 +118,7 @@ public class ValidationServiceImplTest {
         HashMap<String, Object> hashMap = new HashMap<String, Object>();
         hashMap.put("field1", "1");
         ValidationResult vr = validationService.validate(new 
ValueMapDecorator(hashMap), vm);
-        Assert.assertThat(vr.getFailures(), 
Matchers.<ValidationFailure>contains(new DefaultValidationFailure("field1", 
null, ValidationServiceImpl.I18N_KEY_WRONG_PROPERTY_TYPE, Date.class)));
+        Assert.assertThat(vr.getFailures(), 
Matchers.<ValidationFailure>contains(new DefaultValidationFailure("field1", 
null, defaultResourceBundle, 
ValidationServiceImpl.I18N_KEY_WRONG_PROPERTY_TYPE, Date.class)));
     }
 
     @Test
@@ -150,7 +161,7 @@ public class ValidationServiceImplTest {
         hashMap.put("field3", "");
 
         ValidationResult vr = validationService.validate(new 
ValueMapDecorator(hashMap), vm);
-        Assert.assertThat(vr.getFailures(), 
Matchers.<ValidationFailure>contains(new DefaultValidationFailure("", null, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_PROPERTY_WITH_NAME, "field4")));
+        Assert.assertThat(vr.getFailures(), 
Matchers.<ValidationFailure>contains(new DefaultValidationFailure("", null, 
defaultResourceBundle, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_PROPERTY_WITH_NAME, "field4")));
     }
 
     @Test()
@@ -177,7 +188,7 @@ public class ValidationServiceImplTest {
         ValidationResult vr = validationService.validate(new 
ValueMapDecorator(hashMap), vm);
 
         Assert.assertFalse(vr.isValid()); // check for correct error message 
Map<String, List<String>>
-        Assert.assertThat(vr.getFailures(), 
Matchers.<ValidationFailure>contains(new DefaultValidationFailure("field1", 2, 
RegexValidator.I18N_KEY_PATTERN_DOES_NOT_MATCH, "abc")));
+        Assert.assertThat(vr.getFailures(), 
Matchers.<ValidationFailure>contains(new DefaultValidationFailure("field1", 2, 
defaultResourceBundle, RegexValidator.I18N_KEY_PATTERN_DOES_NOT_MATCH, "abc")));
     }
 
     @Test
@@ -197,7 +208,7 @@ public class ValidationServiceImplTest {
         ValidationResult vr = validationService.validate(new 
ValueMapDecorator(hashMap), vm);
 
         Assert.assertFalse(vr.isValid());
-        Assert.assertThat(vr.getFailures(), Matchers.<ValidationFailure> 
hasItem(new DefaultValidationFailure("field2", 0, 
RegexValidator.I18N_KEY_PATTERN_DOES_NOT_MATCH, TEST_REGEX)));
+        Assert.assertThat(vr.getFailures(), Matchers.<ValidationFailure> 
hasItem(new DefaultValidationFailure("field2", 0, defaultResourceBundle, 
RegexValidator.I18N_KEY_PATTERN_DOES_NOT_MATCH, TEST_REGEX)));
     }
 
     // see https://issues.apache.org/jira/browse/SLING-5674
@@ -219,8 +230,8 @@ public class ValidationServiceImplTest {
         ValidationResult vr = validationService.validate(nonExistingResource, 
vm);
         Assert.assertFalse("resource should have been considered invalid", 
vr.isValid());
         Assert.assertThat(vr.getFailures(), 
Matchers.<ValidationFailure>containsInAnyOrder(
-                new DefaultValidationFailure("", 0, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_PROPERTY_WITH_NAME, "field1"),
-                new DefaultValidationFailure("", 0, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_CHILD_RESOURCE_WITH_NAME, 
"child")
+                new DefaultValidationFailure("", 0, defaultResourceBundle, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_PROPERTY_WITH_NAME, "field1"),
+                new DefaultValidationFailure("", 0, defaultResourceBundle, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_CHILD_RESOURCE_WITH_NAME, 
"child")
                 ));
     }
 
@@ -243,8 +254,8 @@ public class ValidationServiceImplTest {
         ValidationResult vr = validationService.validate(nonExistingResource, 
vm);
         Assert.assertFalse("resource should have been considered invalid", 
vr.isValid());
         Assert.assertThat(vr.getFailures(), 
Matchers.<ValidationFailure>containsInAnyOrder(
-                new DefaultValidationFailure("", 0, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_PROPERTY_WITH_NAME, "field1"),
-                new DefaultValidationFailure("", 0, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_CHILD_RESOURCE_WITH_NAME, 
"child")
+                new DefaultValidationFailure("", 0, defaultResourceBundle, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_PROPERTY_WITH_NAME, "field1"),
+                new DefaultValidationFailure("", 0, defaultResourceBundle, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_CHILD_RESOURCE_WITH_NAME, 
"child")
                 ));
     }
 
@@ -277,7 +288,7 @@ public class ValidationServiceImplTest {
 
         ValidationResult vr = validationService.validate(testResource, vm);
         Assert.assertFalse("resource should have been considered invalid", 
vr.isValid());
-        Assert.assertThat(vr.getFailures(), 
Matchers.<ValidationFailure>contains(new 
DefaultValidationFailure("child/grandchild", 0, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_PROPERTY_WITH_NAME, "field1")));
+        Assert.assertThat(vr.getFailures(), 
Matchers.<ValidationFailure>contains(new 
DefaultValidationFailure("child/grandchild", 0, defaultResourceBundle, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_PROPERTY_WITH_NAME, "field1")));
     }
 
     @Test
@@ -390,10 +401,10 @@ public class ValidationServiceImplTest {
         Assert.assertFalse("resource should have been considered invalid", 
vr.isValid());
         
         Assert.assertThat(vr.getFailures(), 
Matchers.<ValidationFailure>containsInAnyOrder(
-                new DefaultValidationFailure("child2", 0, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_CHILD_RESOURCE_MATCHING_PATTERN,
 "grandchild.*"),
-                new DefaultValidationFailure("child3", 0, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_CHILD_RESOURCE_MATCHING_PATTERN,
 "grandchild.*"),
-                new DefaultValidationFailure("child3", 0, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_PROPERTY_WITH_NAME, "field1"),
-                new DefaultValidationFailure("", 0, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_CHILD_RESOURCE_MATCHING_PATTERN,
 "siblingchild.*")));
+                new DefaultValidationFailure("child2", 0, 
defaultResourceBundle, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_CHILD_RESOURCE_MATCHING_PATTERN,
 "grandchild.*"),
+                new DefaultValidationFailure("child3", 0, 
defaultResourceBundle, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_CHILD_RESOURCE_MATCHING_PATTERN,
 "grandchild.*"),
+                new DefaultValidationFailure("child3", 0, 
defaultResourceBundle, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_PROPERTY_WITH_NAME, "field1"),
+                new DefaultValidationFailure("", 0, defaultResourceBundle, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_CHILD_RESOURCE_MATCHING_PATTERN,
 "siblingchild.*")));
     }
 
     @Test
@@ -421,8 +432,8 @@ public class ValidationServiceImplTest {
         Assert.assertFalse("resource should have been considered invalid", 
vr.isValid());
         
         Assert.assertThat(vr.getFailures(), 
Matchers.<ValidationFailure>contains(
-                new DefaultValidationFailure("field3", 0, 
RegexValidator.I18N_KEY_PATTERN_DOES_NOT_MATCH, "\\d"),
-                new DefaultValidationFailure("", 0, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_PROPERTY_MATCHING_PATTERN, 
"otherfield.*")));
+                new DefaultValidationFailure("field3", 0, 
defaultResourceBundle, RegexValidator.I18N_KEY_PATTERN_DOES_NOT_MATCH, "\\d"),
+                new DefaultValidationFailure("", 0, defaultResourceBundle, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_PROPERTY_MATCHING_PATTERN, 
"otherfield.*")));
     }
 
     @Test
@@ -440,7 +451,7 @@ public class ValidationServiceImplTest {
 
         ValidationResult vr = validationService.validate(testResource, vm);
         Assert.assertFalse("resource should have been considered invalid", 
vr.isValid());
-        Assert.assertThat(vr.getFailures(), 
Matchers.<ValidationFailure>contains(new DefaultValidationFailure("field[1]", 
0, RegexValidator.I18N_KEY_PATTERN_DOES_NOT_MATCH, "\\d")));
+        Assert.assertThat(vr.getFailures(), 
Matchers.<ValidationFailure>contains(new DefaultValidationFailure("field[1]", 
0, defaultResourceBundle, RegexValidator.I18N_KEY_PATTERN_DOES_NOT_MATCH, 
"\\d")));
     }
 
     @Test()
@@ -497,8 +508,8 @@ public class ValidationServiceImplTest {
         ValidationResult vr = 
validationService.validateResourceRecursively(testResource, true, 
ignoreResourceType3Filter, false);
         Assert.assertFalse("resource should have been considered invalid", 
vr.isValid());
         Assert.assertThat(vr.getFailures(), 
Matchers.<ValidationFailure>contains(
-                new DefaultValidationFailure("", null,  
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_PROPERTY_WITH_NAME, "field1"),
-                new DefaultValidationFailure("child2", null, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_PROPERTY_WITH_NAME, "field2")));
+                new DefaultValidationFailure("", null, defaultResourceBundle,  
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_PROPERTY_WITH_NAME, "field1"),
+                new DefaultValidationFailure("child2", null, 
defaultResourceBundle, 
ValidationServiceImpl.I18N_KEY_MISSING_REQUIRED_PROPERTY_WITH_NAME, "field2")));
     }
 
     // see https://issues.apache.org/jira/browse/SLING-5674


Reply via email to