You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bval.apache.org by mb...@apache.org on 2018/02/21 21:02:02 UTC

[12/17] bval git commit: BV2: new validation implementation

BV2: new validation implementation


Project: http://git-wip-us.apache.org/repos/asf/bval/repo
Commit: http://git-wip-us.apache.org/repos/asf/bval/commit/05df7ee2
Tree: http://git-wip-us.apache.org/repos/asf/bval/tree/05df7ee2
Diff: http://git-wip-us.apache.org/repos/asf/bval/diff/05df7ee2

Branch: refs/heads/bv2
Commit: 05df7ee264cbef9199897b170e89bb7fcac58f26
Parents: a921963
Author: Matt Benson <mb...@apache.org>
Authored: Wed Feb 21 14:54:03 2018 -0600
Committer: Matt Benson <mb...@apache.org>
Committed: Wed Feb 21 14:59:58 2018 -0600

----------------------------------------------------------------------
 .../apache/bval/jsr/ApacheFactoryContext.java   |  83 ++++++---
 .../bval/jsr/ApacheValidatorConfiguration.java  |   7 +-
 .../apache/bval/jsr/ApacheValidatorFactory.java | 171 ++++++++++++-------
 .../bval/jsr/BootstrapConfigurationImpl.java    |  29 +++-
 .../bval/jsr/CascadingPropertyValidator.java    |  96 ++++++++---
 .../org/apache/bval/jsr/ConfigurationImpl.java  | 128 ++++++++------
 .../java/org/apache/bval/jsr/ValidatorImpl.java | 141 +++++++++++++++
 7 files changed, 494 insertions(+), 161 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/bval/blob/05df7ee2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java
index 8f68b9e..1e4b263 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java
@@ -18,46 +18,56 @@
  */
 package org.apache.bval.jsr;
 
-import org.apache.bval.MetaBeanFinder;
-import org.apache.bval.util.reflection.Reflection;
-import org.apache.commons.weaver.privilizer.Privilizing;
-import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
-
+import javax.validation.ClockProvider;
 import javax.validation.ConstraintValidatorFactory;
 import javax.validation.MessageInterpolator;
 import javax.validation.ParameterNameProvider;
 import javax.validation.TraversableResolver;
 import javax.validation.Validator;
 import javax.validation.ValidatorContext;
+import javax.validation.valueextraction.ValueExtractor;
+
+import org.apache.bval.MetaBeanFinder;
+import org.apache.bval.jsr.descriptor.DescriptorManager;
+import org.apache.bval.jsr.groups.GroupsComputer;
+import org.apache.bval.jsr.valueextraction.ValueExtractors;
+import org.apache.bval.util.Lazy;
+import org.apache.bval.util.reflection.Reflection;
+import org.apache.commons.weaver.privilizer.Privilizing;
+import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
 
 /**
- * Description: Represents the context that is used to create
- * {@link ClassValidator} instances.
+ * Description: Represents the context that is used to create {@link ClassValidator} instances.
  */
 @Privilizing(@CallTo(Reflection.class))
 public class ApacheFactoryContext implements ValidatorContext {
+    private final Lazy<GroupsComputer> groupsComputer = new Lazy<>(GroupsComputer::new);
     private final ApacheValidatorFactory factory;
+    private final ValueExtractors valueExtractors;
     private volatile MetaBeanFinder metaBeanFinder;
 
     private MessageInterpolator messageInterpolator;
     private TraversableResolver traversableResolver;
     private ParameterNameProvider parameterNameProvider;
     private ConstraintValidatorFactory constraintValidatorFactory;
+    private ClockProvider clockProvider;
 
     /**
      * Create a new ApacheFactoryContext instance.
      * 
-     * @param factory validator factory
-     * @param metaBeanFinder meta finder
+     * @param factory
+     *            validator factory
+     * @param metaBeanFinder
+     *            meta finder
      */
     public ApacheFactoryContext(ApacheValidatorFactory factory, MetaBeanFinder metaBeanFinder) {
         this.factory = factory;
         this.metaBeanFinder = metaBeanFinder;
+        valueExtractors = factory.getValueExtractors().createChild();
     }
 
     /**
-     * Get the {@link ApacheValidatorFactory} used by this
-     * {@link ApacheFactoryContext}.
+     * Get the {@link ApacheValidatorFactory} used by this {@link ApacheFactoryContext}.
      * 
      * @return {@link ApacheValidatorFactory}
      */
@@ -75,13 +85,13 @@ public class ApacheFactoryContext implements ValidatorContext {
     }
 
     /**
-     * Discard cached metadata. Calling this method unnecessarily has the effect of severly
-     * limiting performance, therefore only do so when changes have been made that affect
-     * validation metadata, i.e. particularly NOT in response to:
+     * Discard cached metadata. Calling this method unnecessarily has the effect of severly limiting performance,
+     * therefore only do so when changes have been made that affect validation metadata, i.e. particularly NOT in
+     * response to:
      * <ul>
-     *   <li>{@link #messageInterpolator(MessageInterpolator)}</li>
-     *   <li>{@link #traversableResolver(TraversableResolver)}</li>
-     *   <li>{@link #constraintValidatorFactory(ConstraintValidatorFactory)</li>
+     * <li>{@link #messageInterpolator(MessageInterpolator)}</li>
+     * <li>{@link #traversableResolver(TraversableResolver)}</li>
+     * <li>{@link #constraintValidatorFactory(ConstraintValidatorFactory)</li>
      * </ul>
      */
     private synchronized void resetMeta() {
@@ -92,7 +102,7 @@ public class ApacheFactoryContext implements ValidatorContext {
      * {@inheritDoc}
      */
     @Override
-    public ValidatorContext messageInterpolator(MessageInterpolator messageInterpolator) {
+    public ApacheFactoryContext messageInterpolator(MessageInterpolator messageInterpolator) {
         this.messageInterpolator = messageInterpolator;
         return this;
     }
@@ -101,7 +111,7 @@ public class ApacheFactoryContext implements ValidatorContext {
      * {@inheritDoc}
      */
     @Override
-    public ValidatorContext traversableResolver(TraversableResolver traversableResolver) {
+    public ApacheFactoryContext traversableResolver(TraversableResolver traversableResolver) {
         this.traversableResolver = traversableResolver;
         return this;
     }
@@ -110,18 +120,30 @@ public class ApacheFactoryContext implements ValidatorContext {
      * {@inheritDoc}
      */
     @Override
-    public ValidatorContext constraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) {
+    public ApacheFactoryContext constraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) {
         this.constraintValidatorFactory = constraintValidatorFactory;
         return this;
     }
 
     @Override
-    public ValidatorContext parameterNameProvider(ParameterNameProvider parameterNameProvider) {
+    public ApacheFactoryContext parameterNameProvider(ParameterNameProvider parameterNameProvider) {
         this.parameterNameProvider = parameterNameProvider;
         resetMeta(); // needed since parameter names are a component of validation metadata
         return this;
     }
 
+    @Override
+    public ApacheFactoryContext clockProvider(ClockProvider clockProvider) {
+        this.clockProvider = clockProvider;
+        return this;
+    }
+
+    @Override
+    public ApacheFactoryContext addValueExtractor(ValueExtractor<?> extractor) {
+        valueExtractors.add(extractor);
+        return this;
+    }
+
     /**
      * Get the {@link ConstraintValidatorFactory}.
      * 
@@ -137,7 +159,7 @@ public class ApacheFactoryContext implements ValidatorContext {
      */
     @Override
     public Validator getValidator() {
-        return new ClassValidator(this);
+        return new ValidatorImpl(this);
     }
 
     /**
@@ -162,6 +184,23 @@ public class ApacheFactoryContext implements ValidatorContext {
         return parameterNameProvider == null ? factory.getParameterNameProvider() : parameterNameProvider;
     }
 
+    public ClockProvider getClockProvider() {
+        return clockProvider == null ? factory.getClockProvider() : clockProvider;
+    }
+
+    public ValueExtractors getValueExtractors() {
+        return valueExtractors;
+    }
+
+    public DescriptorManager getDescriptorManager() {
+        // TODO handle context customizations
+        return factory.getDescriptorManager();
+    }
+
+    public GroupsComputer getGroupsComputer() {
+        return groupsComputer.get();
+    }
+
     boolean isTreatMapsLikeBeans() {
         return Boolean
             .parseBoolean(factory.getProperties().get(ApacheValidatorConfiguration.Properties.TREAT_MAPS_LIKE_BEANS));

http://git-wip-us.apache.org/repos/asf/bval/blob/05df7ee2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java
index fb64d4e..81187f3 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java
@@ -32,7 +32,7 @@ public interface ApacheValidatorConfiguration extends Configuration<ApacheValida
     /**
      * Proprietary property keys for {@link ConfigurationImpl}  
      */
-    public interface Properties {
+    interface Properties {
         /**
          * the location where to look for the validation.xml file.
          * default: "META-INF/validation.xml"
@@ -91,5 +91,10 @@ public interface ApacheValidatorConfiguration extends Configuration<ApacheValida
          * </ol>
          */
         String METABEAN_FACTORY_CLASSNAMES = "apache.bval.metabean-factory-classnames";
+
+        /**
+         * Size to use for caching of constraint-related information. Default is {@code 50}.
+         */
+        String CONSTRAINTS_CACHE_SIZE = "apache.bval.constraints-cache-size";
     }
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/05df7ee2/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java
index 5e6a611..b516a73 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java
@@ -18,11 +18,39 @@
  */
 package org.apache.bval.jsr;
 
+import java.io.Closeable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.validation.ClockProvider;
+import javax.validation.ConstraintValidatorFactory;
+import javax.validation.MessageInterpolator;
+import javax.validation.ParameterNameProvider;
+import javax.validation.TraversableResolver;
+import javax.validation.Validation;
+import javax.validation.ValidationException;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
+import javax.validation.spi.ConfigurationState;
+
 import org.apache.bval.IntrospectorMetaBeanFactory;
 import org.apache.bval.MetaBeanBuilder;
 import org.apache.bval.MetaBeanFactory;
 import org.apache.bval.MetaBeanFinder;
 import org.apache.bval.MetaBeanManager;
+import org.apache.bval.jsr.descriptor.DescriptorManager;
+import org.apache.bval.jsr.metadata.MetadataBuilders;
+import org.apache.bval.jsr.util.AnnotationsManager;
+import org.apache.bval.jsr.valueextraction.ValueExtractors;
 import org.apache.bval.jsr.xml.AnnotationIgnores;
 import org.apache.bval.jsr.xml.MetaConstraint;
 import org.apache.bval.jsr.xml.ValidationMappingParser;
@@ -37,28 +65,6 @@ import org.apache.commons.weaver.privilizer.Privileged;
 import org.apache.commons.weaver.privilizer.Privilizing;
 import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
 
-import javax.validation.ConstraintValidatorFactory;
-import javax.validation.MessageInterpolator;
-import javax.validation.ParameterNameProvider;
-import javax.validation.TraversableResolver;
-import javax.validation.Validation;
-import javax.validation.ValidationException;
-import javax.validation.Validator;
-import javax.validation.ValidatorFactory;
-import javax.validation.spi.ConfigurationState;
-import java.io.Closeable;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
 /**
  * Description: a factory is a complete configurated object that can create
  * validators.<br/>
@@ -68,13 +74,17 @@ import java.util.concurrent.ConcurrentMap;
 public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
 
     private static volatile ApacheValidatorFactory DEFAULT_FACTORY;
-    private static final ConstraintDefaults DEFAULT_CONSTRAINTS = new ConstraintDefaults();
 
     private MessageInterpolator messageResolver;
     private TraversableResolver traversableResolver;
     private ConstraintValidatorFactory constraintValidatorFactory;
     private ParameterNameProvider parameterNameProvider;
+    private ClockProvider clockProvider;
     private final Map<String, String> properties;
+    private final AnnotationsManager annotationsManager;
+    private final DescriptorManager descriptorManager = new DescriptorManager(this);
+    private final MetadataBuilders metadataBuilders = new MetadataBuilders();
+    private final ValueExtractors valueExtractors = new ValueExtractors();
 
     /**
      * information from xml parsing
@@ -89,7 +99,7 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     private final ConcurrentMap<Class<?>, List<AccessStrategy>> validAccesses;
     private final ConcurrentMap<Class<?>, List<MetaConstraint<?, ? extends Annotation>>> constraintMap;
 
-    private final Collection<Closeable> toClose = new ArrayList<Closeable>();
+    private final Collection<Closeable> toClose = new ArrayList<>();
     private final MetaBeanFinder defaultMetaBeanFinder;
 
     /**
@@ -112,7 +122,7 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
      * @return a new instance of MetaBeanManager with adequate MetaBeanFactories
      */
     protected MetaBeanFinder buildMetaBeanFinder() {
-        final List<MetaBeanFactory> builders = new ArrayList<MetaBeanFactory>();
+        final List<MetaBeanFactory> builders = new ArrayList<>();
         if (Boolean.parseBoolean(getProperties().get(ApacheValidatorConfiguration.Properties.ENABLE_INTROSPECTOR))) {
             builders.add(new IntrospectorMetaBeanFactory());
         }
@@ -121,9 +131,8 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
         if (factoryClassNames != null) {
             for (String clsName : factoryClassNames) {
                 // cast, relying on #createMetaBeanFactory to throw the exception if incompatible:
-                @SuppressWarnings("unchecked")
                 final Class<? extends MetaBeanFactory> factoryClass =
-                    (Class<? extends MetaBeanFactory>) loadClass(clsName);
+                    loadClass(clsName).asSubclass(MetaBeanFactory.class);
                 builders.add(createMetaBeanFactory(factoryClass));
             }
         }
@@ -173,24 +182,27 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
      * Create a new ApacheValidatorFactory instance.
      */
     public ApacheValidatorFactory(ConfigurationState configuration) {
-        properties = new HashMap<String, String>(configuration.getProperties());
-        defaultSequences = new HashMap<Class<?>, Class<?>[]>();
-        validAccesses = new ConcurrentHashMap<Class<?>, List<AccessStrategy>>();
-        constraintMap = new ConcurrentHashMap<Class<?>, List<MetaConstraint<?, ? extends Annotation>>>();
+        properties = new HashMap<>(configuration.getProperties());
+        defaultSequences = new HashMap<>();
+        validAccesses = new ConcurrentHashMap<>();
+        constraintMap = new ConcurrentHashMap<>();
 
         parameterNameProvider = configuration.getParameterNameProvider();
         messageResolver = configuration.getMessageInterpolator();
         traversableResolver = configuration.getTraversableResolver();
         constraintValidatorFactory = configuration.getConstraintValidatorFactory();
+        clockProvider = configuration.getClockProvider();
 
         if (ConfigurationImpl.class.isInstance(configuration)) {
-            final ConfigurationImpl impl = ConfigurationImpl.class.cast(configuration);
-            toClose.add(impl.getClosable());
+            toClose.add(ConfigurationImpl.class.cast(configuration).getClosable());
         }
 
         new ValidationMappingParser(this).processMappingConfig(configuration.getMappingStreams());
 
         defaultMetaBeanFinder = buildMetaBeanFinder();
+
+        configuration.getValueExtractors().forEach(valueExtractors::add);
+        annotationsManager = new AnnotationsManager(this);
     }
 
     /**
@@ -203,8 +215,7 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     }
 
     /**
-     * Shortcut method to create a new Validator instance with factory's
-     * settings
+     * Shortcut method to create a new Validator instance with factory's settings
      *
      * @return the new validator instance
      */
@@ -271,6 +282,12 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
         }
     }
 
+    public void setClockProvider(final ClockProvider clockProvider) {
+        if (clockProvider != null) {
+            this.clockProvider = clockProvider;
+        }
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -307,6 +324,11 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     }
 
     @Override
+    public ClockProvider getClockProvider() {
+        return clockProvider;
+    }
+
+    @Override
     public void close() {
         try {
             for (final Closeable c : toClose) {
@@ -319,13 +341,14 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     }
 
     /**
-     * Return an object of the specified type to allow access to the
-     * provider-specific API. If the Bean Validation provider implementation
-     * does not support the specified class, the ValidationException is thrown.
+     * Return an object of the specified type to allow access to the provider-specific API. If the Bean Validation
+     * provider implementation does not support the specified class, the ValidationException is thrown.
      *
-     * @param type the class of the object to be returned.
+     * @param type
+     *            the class of the object to be returned.
      * @return an instance of the specified class
-     * @throws ValidationException if the provider does not support the call.
+     * @throws ValidationException
+     *             if the provider does not support the call.
      */
     @Override
     public <T> T unwrap(final Class<T> type) {
@@ -365,15 +388,6 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     }
 
     /**
-     * Get the detected {@link ConstraintDefaults}.
-     *
-     * @return ConstraintDefaults
-     */
-    public ConstraintDefaults getDefaultConstraints() {
-        return DEFAULT_CONSTRAINTS;
-    }
-
-    /**
      * Get the detected {@link AnnotationIgnores}.
      *
      * @return AnnotationIgnores
@@ -392,8 +406,34 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     }
 
     /**
-     * Add a meta-constraint to this {@link ApacheValidatorFactory}'s runtime
-     * customizations.
+     * Get the {@link AnnotationsManager}.
+     * 
+     * @return {@link AnnotationsManager}
+     */
+    public AnnotationsManager getAnnotationsManager() {
+        return annotationsManager;
+    }
+
+    /**
+     * Get the {@link DescriptorManager}.
+     * 
+     * @return {@link DescriptorManager}
+     */
+    public DescriptorManager getDescriptorManager() {
+        return descriptorManager;
+    }
+
+    /**
+     * Get the {@link ValueExtractors}.
+     * 
+     * @return {@link ValueExtractors}
+     */
+    public ValueExtractors getValueExtractors() {
+        return valueExtractors;
+    }
+
+    /**
+     * Add a meta-constraint to this {@link ApacheValidatorFactory}'s runtime customizations.
      *
      * @param beanClass
      * @param metaConstraint
@@ -401,7 +441,7 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     public void addMetaConstraint(final Class<?> beanClass, final MetaConstraint<?, ?> metaConstraint) {
         List<MetaConstraint<?, ? extends Annotation>> slot = constraintMap.get(beanClass);
         if (slot == null) {
-            slot = new ArrayList<MetaConstraint<?, ? extends Annotation>>();
+            slot = new ArrayList<>();
             final List<MetaConstraint<?, ? extends Annotation>> old = constraintMap.putIfAbsent(beanClass, slot);
             if (old != null) {
                 slot = old;
@@ -420,7 +460,7 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     public void addValid(Class<?> beanClass, AccessStrategy accessStrategy) {
         List<AccessStrategy> slot = validAccesses.get(beanClass);
         if (slot == null) {
-            slot = new ArrayList<AccessStrategy>();
+            slot = new ArrayList<>();
             final List<AccessStrategy> old = validAccesses.putIfAbsent(beanClass, slot);
             if (old != null) {
                 slot = old;
@@ -444,8 +484,7 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
      *
      * @param <T>
      * @param beanClass
-     * @return List of {@link MetaConstraint}s applicable to
-     *         <code>beanClass</code>
+     * @return List of {@link MetaConstraint}s applicable to <code>beanClass</code>
      */
     public <T> List<MetaConstraint<T, ? extends Annotation>> getMetaConstraints(Class<T> beanClass) {
         final List<MetaConstraint<?, ? extends Annotation>> slot = constraintMap.get(beanClass);
@@ -459,16 +498,15 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     }
 
     /**
-     * Get the {@link AccessStrategy} {@link List} indicating nested bean
-     * validations that must be triggered in the course of validating a
-     * <code>beanClass</code> graph.
+     * Get the {@link AccessStrategy} {@link List} indicating nested bean validations that must be triggered in the
+     * course of validating a <code>beanClass</code> graph.
      *
      * @param beanClass
      * @return {@link List} of {@link AccessStrategy}
      */
     public List<AccessStrategy> getValidAccesses(Class<?> beanClass) {
         final List<AccessStrategy> slot = validAccesses.get(beanClass);
-        return slot == null ? Collections.<AccessStrategy> emptyList() : Collections.unmodifiableList(slot);
+        return slot == null ? Collections.emptyList() : Collections.unmodifiableList(slot);
     }
 
     /**
@@ -481,6 +519,10 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
         return safeArray(defaultSequences.get(beanClass));
     }
 
+    public MetadataBuilders getMetadataBuilders() {
+        return metadataBuilders;
+    }
+
     private static Class<?>[] safeArray(Class<?>... array) {
         return array == null || array.length == 0 ? ObjectUtils.EMPTY_CLASS_ARRAY : array.clone();
     }
@@ -519,9 +561,8 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
     }
 
     /**
-     * separate class to prevent the classloader to immediately load optional
-     * classes: XMLMetaBeanManager, XMLMetaBeanFactory, XMLMetaBeanBuilder that
-     * might not be available in the classpath
+     * separate class to prevent the classloader to immediately load optional classes: XMLMetaBeanManager,
+     * XMLMetaBeanFactory, XMLMetaBeanBuilder that might not be available in the classpath
      */
     private static class XMLMetaBeanManagerCreator {
 
@@ -530,10 +571,10 @@ public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
         }
 
         /**
-         * Create the {@link MetaBeanManager} to process JSR303 XML. Requires
-         * bval-xstream at RT.
+         * Create the {@link MetaBeanManager} to process JSR303 XML. Requires bval-xstream at RT.
          *
-         * @param builders meta bean builders
+         * @param builders
+         *            meta bean builders
          * @return {@link MetaBeanManager}
          */
         // NOTE - We return MetaBeanManager instead of XMLMetaBeanManager to

http://git-wip-us.apache.org/repos/asf/bval/blob/05df7ee2/bval-jsr/src/main/java/org/apache/bval/jsr/BootstrapConfigurationImpl.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/BootstrapConfigurationImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/BootstrapConfigurationImpl.java
index 3a3abf1..d85ab51 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/BootstrapConfigurationImpl.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/BootstrapConfigurationImpl.java
@@ -34,12 +34,15 @@ public class BootstrapConfigurationImpl implements BootstrapConfiguration {
     private String messageInterpolatorClassName;
     private String constraintValidatorFactoryClassName;
     private String defaultProviderClassName;
+    private String clockProviderClassName;
+    private Set<String> valueExtractorClassNames;
 
     public BootstrapConfigurationImpl(final String defaultProviderClassName,
         final String constraintValidatorFactoryClassName, final String messageInterpolatorClassName,
         final String traversableResolverClassName, final String parameterNameProviderClassName,
         final Set<String> constraintMappingResourcePaths, final boolean executableValidationEnabled,
-        final Set<ExecutableType> defaultValidatedExecutableTypes, final Map<String, String> properties) {
+        final Set<ExecutableType> defaultValidatedExecutableTypes, final Map<String, String> properties,
+        final String clockProviderClassName, final Set<String> valueExtractorClassNames) {
         this.properties = Collections.unmodifiableMap(properties);
         this.defaultValidatedExecutableTypes = Collections.unmodifiableSet(defaultValidatedExecutableTypes);
         this.executableValidationEnabled = executableValidationEnabled;
@@ -49,6 +52,8 @@ public class BootstrapConfigurationImpl implements BootstrapConfiguration {
         this.messageInterpolatorClassName = messageInterpolatorClassName;
         this.constraintValidatorFactoryClassName = constraintValidatorFactoryClassName;
         this.defaultProviderClassName = defaultProviderClassName;
+        this.clockProviderClassName = clockProviderClassName;
+        this.valueExtractorClassNames = valueExtractorClassNames;
     }
 
     @Override
@@ -78,7 +83,7 @@ public class BootstrapConfigurationImpl implements BootstrapConfiguration {
 
     @Override
     public Set<String> getConstraintMappingResourcePaths() {
-        return constraintMappingResourcePaths;
+        return Collections.unmodifiableSet(constraintMappingResourcePaths);
     }
 
     @Override
@@ -88,11 +93,27 @@ public class BootstrapConfigurationImpl implements BootstrapConfiguration {
 
     @Override
     public Set<ExecutableType> getDefaultValidatedExecutableTypes() {
-        return defaultValidatedExecutableTypes;
+        return Collections.unmodifiableSet(defaultValidatedExecutableTypes);
     }
 
     @Override
     public Map<String, String> getProperties() {
-        return properties;
+        return Collections.unmodifiableMap(properties);
+    }
+
+    /**
+     * @since 2.0
+     */
+    @Override
+    public String getClockProviderClassName() {
+        return clockProviderClassName;
+    }
+
+    /**
+     * @since 2.0
+     */
+    @Override
+    public Set<String> getValueExtractorClassNames() {
+        return Collections.unmodifiableSet(valueExtractorClassNames);
     }
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/05df7ee2/bval-jsr/src/main/java/org/apache/bval/jsr/CascadingPropertyValidator.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/CascadingPropertyValidator.java b/bval-jsr/src/main/java/org/apache/bval/jsr/CascadingPropertyValidator.java
index ff2e273..f183c12 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/CascadingPropertyValidator.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/CascadingPropertyValidator.java
@@ -18,7 +18,9 @@ package org.apache.bval.jsr;
 
 import javax.validation.ConstraintViolation;
 import javax.validation.Valid;
+import javax.validation.ValidationException;
 import javax.validation.Validator;
+
 import java.util.Set;
 
 /**
@@ -30,38 +32,90 @@ import java.util.Set;
  * It should be noted that {@link Validator#validateProperty(Object, String, Class...)}
  * and {@link Validator#validateValue(Class, String, Object, Class...)} are assumed
  * semantically equivalent to calling the {@link CascadingPropertyValidator}-defined
- * methods with <code>cascade == false</code>.
+ * methods with {@code cascade == false}.
  * 
  * @version $Rev: 993539 $ $Date: 2010-09-07 16:27:50 -0500 (Tue, 07 Sep 2010) $
  */
 public interface CascadingPropertyValidator extends Validator {
 
     /**
-     * Validates all constraints placed on <code>object</code>'s
-     * <code>propertyName</code> property, with optional validation cascading.
-     * 
-     * @param <T>
-     * @param object
-     * @param propertyName
-     * @param cascade
-     * @param groups
-     * @return the resulting {@link Set} of {@link ConstraintViolation}s.
+     * {@inheritDoc} Validates all constraints placed on the property of {@code object} named {@code propertyName}.
+     *
+     * @param object       object to validate
+     * @param propertyName property to validate (i.e. field and getter constraints). Nested
+     *                     properties may be referenced (e.g. prop[2].subpropA.subpropB)
+     * @param groups       group or list of groups targeted for validation (default to
+     *                     {@link javax.validation.groups.Default})
+     * @return constraint violations or an empty {@link Set} if none
+     * @throws IllegalArgumentException if {@code object} is {@code null}, if {@code propertyName null},
+     *                                  empty or not a valid object property or if {@code null} is
+     *                                  passed to the varargs {@code groups}
+     * @throws ValidationException      if a non recoverable error happens during the validation process
+     */
+    @Override
+    default <T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, Class<?>... groups) {
+        return validateProperty(object, propertyName, false, groups);
+    }
+
+    /**
+     * Validates all constraints placed on the property of {@code object} named {@code propertyName}.
+     *
+     * @param object       object to validate
+     * @param propertyName property to validate (i.e. field and getter constraints). Nested
+     *                     properties may be referenced (e.g. prop[2].subpropA.subpropB)
+     * @param cascade      whether to cascade along {@link Valid} properties
+     * @param groups       group or list of groups targeted for validation (default to
+     *                     {@link javax.validation.groups.Default})
+     * @return constraint violations or an empty {@link Set} if none
+     * @throws IllegalArgumentException if {@code object} is {@code null}, if {@code propertyName null},
+     *                                  empty or not a valid object property or if {@code null} is
+     *                                  passed to the varargs {@code groups}
+     * @throws ValidationException      if a non recoverable error happens during the validation process
      */
     <T> Set<javax.validation.ConstraintViolation<T>> validateProperty(T object, String propertyName, boolean cascade,
         Class<?>... groups);
 
     /**
-     * Validates all constraints placed on <code>object</code>'s
-     * <code>propertyName</code> property, with optional validation cascading,
-     * given a hypothetical property <code>value</code>.
-     * 
-     * @param <T>
-     * @param beanType
-     * @param propertyName
-     * @param value
-     * @param cascade
-     * @param groups
-     * @return the resulting {@link Set} of {@link ConstraintViolation}s.
+     * {@inheritDoc} Validates all constraints placed on the property named {@code propertyName} of the class
+     * {@code beanType} would the property value be {@code value}.
+     * <p/>
+     * {@link ConstraintViolation} objects return {@code null} for {@link ConstraintViolation#getRootBean()} and
+     * {@link ConstraintViolation#getLeafBean()}.
+     *
+     * @param beanType     the bean type
+     * @param propertyName property to validate
+     * @param value        property value to validate
+     * @param groups       group or list of groups targeted for validation (default to
+     *                     {@link javax.validation.groups.Default})
+     * @return constraint violations or an empty {@link Set} if none
+     * @throws IllegalArgumentException if {@code beanType} is {@code null}, if
+     *                                  {@code propertyName null}, empty or not a valid object
+     *                                  property or if {@code null} is passed to the varargs {@code groups}
+     * @throws ValidationException      if a non recoverable error happens during the validation process
+     */
+    @Override
+    default <T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value,
+        Class<?>... groups) {
+        return validateValue(beanType, propertyName, value, false, groups);
+    }
+
+    /**
+     * {@inheritDoc} Validates all constraints placed on the property named {@code propertyName} of the class
+     * {@code beanType} would the property value be {@code value}.
+     * <p/>
+     * {@link ConstraintViolation} objects return {@code null} for {@link ConstraintViolation#getRootBean()} and
+     * {@link ConstraintViolation#getLeafBean()}.
+     *
+     * @param beanType     the bean type
+     * @param propertyName property to validate
+     * @param value        property value to validate
+     * @param groups       group or list of groups targeted for validation (default to
+     *                     {@link javax.validation.groups.Default})
+     * @return constraint violations or an empty {@link Set} if none
+     * @throws IllegalArgumentException if {@code beanType} is {@code null}, if
+     *                                  {@code propertyName null}, empty or not a valid object
+     *                                  property or if {@code null} is passed to the varargs {@code groups}
+     * @throws ValidationException      if a non recoverable error happens during the validation process
      */
     <T> Set<javax.validation.ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value,
         boolean cascade, Class<?>... groups);

http://git-wip-us.apache.org/repos/asf/bval/blob/05df7ee2/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java
index 7c4780f..046d6d2 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java
@@ -19,9 +19,10 @@
 package org.apache.bval.jsr;
 
 import java.io.Closeable;
-import java.io.IOException;
 import java.io.InputStream;
+import java.time.Clock;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -29,6 +30,7 @@ import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 import javax.validation.BootstrapConfiguration;
+import javax.validation.ClockProvider;
 import javax.validation.ConstraintValidatorFactory;
 import javax.validation.MessageInterpolator;
 import javax.validation.ParameterNameProvider;
@@ -40,6 +42,7 @@ import javax.validation.executable.ExecutableType;
 import javax.validation.spi.BootstrapState;
 import javax.validation.spi.ConfigurationState;
 import javax.validation.spi.ValidationProvider;
+import javax.validation.valueextraction.ValueExtractor;
 
 import org.apache.bval.cdi.BValExtension;
 import org.apache.bval.jsr.parameter.DefaultParameterNameProvider;
@@ -76,29 +79,33 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
      */
     protected MessageInterpolator defaultMessageInterpolator = new DefaultMessageInterpolator();
     protected volatile MessageInterpolator messageInterpolator = defaultMessageInterpolator;
-    protected Class<? extends MessageInterpolator> messageInterpolatorClass = null;
+    protected Class<? extends MessageInterpolator> messageInterpolatorClass;
 
     /**
      * Configured {@link ConstraintValidatorFactory}
      */
     protected ConstraintValidatorFactory defaultConstraintValidatorFactory = new DefaultConstraintValidatorFactory();
     protected volatile ConstraintValidatorFactory constraintValidatorFactory = defaultConstraintValidatorFactory;
-    protected Class<? extends ConstraintValidatorFactory> constraintValidatorFactoryClass = null;
+    protected Class<? extends ConstraintValidatorFactory> constraintValidatorFactoryClass;
 
     protected TraversableResolver defaultTraversableResolver = new DefaultTraversableResolver();
     protected volatile TraversableResolver traversableResolver = defaultTraversableResolver;
-    protected Class<? extends TraversableResolver> traversableResolverClass = null;
+    protected Class<? extends TraversableResolver> traversableResolverClass;
 
     protected ParameterNameProvider defaultParameterNameProvider = new DefaultParameterNameProvider();
     protected volatile ParameterNameProvider parameterNameProvider = defaultParameterNameProvider;
-    protected Class<? extends ParameterNameProvider> parameterNameProviderClass = null;
+    protected Class<? extends ParameterNameProvider> parameterNameProviderClass;
 
     protected BootstrapConfiguration bootstrapConfiguration;
 
     protected Collection<ExecutableType> executableValidation;
 
-    private Collection<BValExtension.Releasable<?>> releasables =
-        new CopyOnWriteArrayList<BValExtension.Releasable<?>>();
+    private Collection<BValExtension.Releasable<?>> releasables = new CopyOnWriteArrayList<>();
+    protected ClockProvider defaultClockProvider = Clock::systemDefaultZone;
+    protected volatile ClockProvider clockProvider = defaultClockProvider;
+    protected Class<? extends ClockProvider> clockProviderClass;
+
+    protected Set<ValueExtractor<?>> valueExtractors = new HashSet<>();
 
     private boolean beforeCdi = false;
 
@@ -109,8 +116,8 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
     private boolean prepared = false;
     // END DEFAULTS
 
-    private Set<InputStream> mappingStreams = new HashSet<InputStream>();
-    private Map<String, String> properties = new HashMap<String, String>();
+    private Set<InputStream> mappingStreams = new HashSet<>();
+    private Map<String, String> properties = new HashMap<>();
     private boolean ignoreXmlConfiguration = false;
 
     private volatile ValidationParser parser;
@@ -134,6 +141,7 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
         } else {
             throw new ValidationException("either provider or state are required");
         }
+        initializePropertyDefaults();
     }
 
     /**
@@ -141,13 +149,11 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
      */
     @Override
     public ApacheValidatorConfiguration traversableResolver(TraversableResolver resolver) {
-        if (resolver == null) {
-            return this;
+        if (resolver != null) {
+            this.traversableResolverClass = null;
+            this.traversableResolver = resolver;
+            this.prepared = false;
         }
-
-        this.traversableResolverClass = null;
-        this.traversableResolver = resolver;
-        this.prepared = false;
         return this;
     }
 
@@ -169,13 +175,11 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
      */
     @Override
     public ConfigurationImpl messageInterpolator(MessageInterpolator resolver) {
-        if (resolver == null) {
-            return this;
+        if (resolver != null) {
+            this.messageInterpolatorClass = null;
+            this.messageInterpolator = resolver;
+            this.prepared = false;
         }
-
-        this.messageInterpolatorClass = null;
-        this.messageInterpolator = resolver;
-        this.prepared = false;
         return this;
     }
 
@@ -184,23 +188,20 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
      */
     @Override
     public ConfigurationImpl constraintValidatorFactory(ConstraintValidatorFactory constraintFactory) {
-        if (constraintFactory == null) {
-            return this;
+        if (constraintFactory != null) {
+            this.constraintValidatorFactoryClass = null;
+            this.constraintValidatorFactory = constraintFactory;
+            this.prepared = false;
         }
-
-        this.constraintValidatorFactoryClass = null;
-        this.constraintValidatorFactory = constraintFactory;
-        this.prepared = false;
         return this;
     }
 
     @Override
     public ApacheValidatorConfiguration parameterNameProvider(ParameterNameProvider parameterNameProvider) {
-        if (parameterNameProvider == null) {
-            return this;
+        if (parameterNameProvider != null) {
+            this.parameterNameProviderClass = null;
+            this.parameterNameProvider = parameterNameProvider;
         }
-        this.parameterNameProviderClass = null;
-        this.parameterNameProvider = parameterNameProvider;
         return this;
     }
 
@@ -213,10 +214,9 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
      */
     @Override
     public ApacheValidatorConfiguration addMapping(InputStream stream) {
-        if (stream == null) {
-            return this;
+        if (stream != null) {
+            mappingStreams.add(IOs.convertToMarkableInputStream(stream));
         }
-        mappingStreams.add(IOs.convertToMarkableInputStream(stream));
         return this;
     }
 
@@ -297,7 +297,6 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
         if (beforeCdi) {
             return defaultMessageInterpolator;
         }
-
         if (messageInterpolator == defaultMessageInterpolator && messageInterpolatorClass != null) {
             synchronized (this) {
                 if (messageInterpolator == defaultMessageInterpolator && messageInterpolatorClass != null) {
@@ -336,7 +335,6 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
         if (prepared) {
             return this;
         }
-
         createBootstrapConfiguration();
         parser.applyConfigWithInstantiation(this); // instantiate the config if needed
 
@@ -367,7 +365,6 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
         if (beforeCdi) {
             return constraintValidatorFactory;
         }
-
         if (constraintValidatorFactory == defaultConstraintValidatorFactory
             && constraintValidatorFactoryClass != null) {
             synchronized (this) {
@@ -388,7 +385,6 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
         if (beforeCdi) {
             return defaultTraversableResolver;
         }
-
         if (traversableResolver == defaultTraversableResolver && traversableResolverClass != null) {
             synchronized (this) {
                 if (traversableResolver == defaultTraversableResolver && traversableResolverClass != null) {
@@ -404,7 +400,6 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
         if (beforeCdi) {
             return defaultParameterNameProvider;
         }
-
         if (parameterNameProvider == defaultParameterNameProvider && parameterNameProviderClass != null) {
             synchronized (this) {
                 if (parameterNameProvider == defaultParameterNameProvider && parameterNameProviderClass != null) {
@@ -452,14 +447,11 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
     }
 
     public Closeable getClosable() {
-        return new Closeable() {
-            @Override
-            public void close() throws IOException {
-                for (final BValExtension.Releasable<?> releasable : releasables) {
-                    releasable.release();
-                }
-                releasables.clear();
+        return () -> {
+            for (final BValExtension.Releasable<?> releasable : releasables) {
+                releasable.release();
             }
+            releasables.clear();
         };
     }
 
@@ -469,8 +461,7 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
             final BValExtension.Releasable<T> releasable = BValExtension.inject(cls);
             releasables.add(releasable);
             return releasable.getInstance();
-        } catch (final Exception e) {
-        } catch (final NoClassDefFoundError error) {
+        } catch (Exception | NoClassDefFoundError e) {
         }
         try {
             return cls.newInstance();
@@ -494,4 +485,45 @@ public class ConfigurationImpl implements ApacheValidatorConfiguration, Configur
     public void parameterNameProviderClass(final Class<? extends ParameterNameProvider> clazz) {
         parameterNameProviderClass = clazz;
     }
+
+    @Override
+    public ApacheValidatorConfiguration clockProvider(ClockProvider clockProvider) {
+        this.clockProvider = clockProvider;
+        return this;
+    }
+
+    @Override
+    public ApacheValidatorConfiguration addValueExtractor(ValueExtractor<?> extractor) {
+        valueExtractors.add(extractor);
+        return this;
+    }
+
+    @Override
+    public ClockProvider getDefaultClockProvider() {
+        return defaultClockProvider;
+    }
+
+    @Override
+    public Set<ValueExtractor<?>> getValueExtractors() {
+        return Collections.unmodifiableSet(valueExtractors);
+    }
+
+    @Override
+    public ClockProvider getClockProvider() {
+        if (beforeCdi) {
+            return defaultClockProvider;
+        }
+        if (clockProvider == defaultClockProvider && clockProviderClass != null) {
+            synchronized (this) {
+                if (clockProvider == defaultClockProvider && clockProviderClass != null) {
+                    clockProvider = newInstance(clockProviderClass);
+                }
+            }
+        }
+        return clockProvider;
+    }
+
+    protected void initializePropertyDefaults() {
+        properties.put(Properties.CONSTRAINTS_CACHE_SIZE, Integer.toString(50));
+    }
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/05df7ee2/bval-jsr/src/main/java/org/apache/bval/jsr/ValidatorImpl.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ValidatorImpl.java b/bval-jsr/src/main/java/org/apache/bval/jsr/ValidatorImpl.java
new file mode 100644
index 0000000..606e191
--- /dev/null
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ValidatorImpl.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.bval.jsr;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Set;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.ValidationException;
+import javax.validation.executable.ExecutableValidator;
+import javax.validation.metadata.BeanDescriptor;
+
+import org.apache.bval.jsr.job.ValidationJobFactory;
+import org.apache.bval.util.Validate;
+import org.apache.bval.util.reflection.Reflection;
+
+public class ValidatorImpl implements CascadingPropertyValidator, ExecutableValidator {
+
+    private final ApacheFactoryContext validatorContext;
+    private final ValidationJobFactory validationJobFactory;
+
+    ValidatorImpl(ApacheFactoryContext validatorContext) {
+        super();
+        this.validatorContext = Validate.notNull(validatorContext, "validatorContext");
+        this.validationJobFactory = new ValidationJobFactory(validatorContext);
+    }
+
+    @Override
+    public BeanDescriptor getConstraintsForClass(Class<?> clazz) {
+        return validatorContext.getDescriptorManager().getBeanDescriptor(clazz);
+    }
+
+    @Override
+    public <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) {
+        return validationJobFactory.validateBean(object, groups).getResults();
+    }
+
+    @Override
+    public <T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, boolean cascade,
+        Class<?>... groups) {
+        return validationJobFactory.validateProperty(object, propertyName, groups).cascade(cascade).getResults();
+    }
+
+    @Override
+    public <T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value,
+        boolean cascade, Class<?>... groups) {
+        return validationJobFactory.validateValue(beanType, propertyName, value, groups).cascade(cascade).getResults();
+    }
+
+    @Override
+    public ExecutableValidator forExecutables() {
+        return this;
+    }
+
+    @Override
+    public <T> Set<ConstraintViolation<T>> validateParameters(T object, Method method, Object[] parameterValues,
+        Class<?>... groups) {
+        return validationJobFactory.validateParameters(object, method, parameterValues, groups).getResults();
+    }
+
+    @Override
+    public <T> Set<ConstraintViolation<T>> validateReturnValue(T object, Method method, Object returnValue,
+        Class<?>... groups) {
+        return validationJobFactory.validateReturnValue(object, method, returnValue, groups).getResults();
+    }
+
+    @Override
+    public <T> Set<ConstraintViolation<T>> validateConstructorParameters(Constructor<? extends T> constructor,
+        Object[] parameterValues, Class<?>... groups) {
+        return validationJobFactory.<T> validateConstructorParameters(constructor, parameterValues, groups)
+            .getResults();
+    }
+
+    @Override
+    public <T> Set<ConstraintViolation<T>> validateConstructorReturnValue(Constructor<? extends T> constructor,
+        T createdObject, Class<?>... groups) {
+        return validationJobFactory.<T> validateConstructorReturnValue(constructor, createdObject, groups).getResults();
+    }
+
+    @Override
+    public <T> T unwrap(Class<T> type) {
+        // FIXME 2011-03-27 jw:
+        // This code is unsecure.
+        // It should allow only a fixed set of classes.
+        // Can't fix this because don't know which classes this method should support.
+
+        if (type.isAssignableFrom(getClass())) {
+            @SuppressWarnings("unchecked")
+            final T result = (T) this;
+            return result;
+        }
+        if (!(type.isInterface() || Modifier.isAbstract(type.getModifiers()))) {
+            return newInstance(type);
+        }
+        try {
+            final Class<?> cls = Reflection.toClass(type.getName() + "Impl");
+            if (type.isAssignableFrom(cls)) {
+                @SuppressWarnings("unchecked")
+                final Class<? extends T> implClass = (Class<? extends T>) cls;
+                return newInstance(implClass);
+            }
+        } catch (ClassNotFoundException e) {
+        }
+        throw new ValidationException("Type " + type + " not supported");
+    }
+
+    private <T> T newInstance(final Class<T> cls) {
+        final Constructor<T> cons = Reflection.getDeclaredConstructor(cls, ApacheFactoryContext.class);
+        if (cons == null) {
+            throw new ValidationException("Cannot instantiate " + cls);
+        }
+        final boolean mustUnset = Reflection.setAccessible(cons, true);
+        try {
+            return cons.newInstance(validatorContext);
+        } catch (final Exception ex) {
+            throw new ValidationException("Cannot instantiate " + cls, ex);
+        } finally {
+            if (mustUnset) {
+                Reflection.setAccessible(cons, false);
+            }
+        }
+    }
+}