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 20:24:58 UTC

[02/11] bval git commit: implement BV 2.0 against existing BVal unit tests

http://git-wip-us.apache.org/repos/asf/bval/blob/3f287a7a/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java b/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java
index b260a9e..3a86142 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java
@@ -18,730 +18,100 @@ package org.apache.bval.jsr.xml;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.Serializable;
 import java.lang.annotation.Annotation;
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashSet;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
-import javax.validation.Constraint;
-import javax.validation.ConstraintValidator;
-import javax.validation.Payload;
 import javax.validation.ValidationException;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBElement;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Unmarshaller;
-import javax.xml.transform.stream.StreamSource;
-import javax.xml.validation.Schema;
 
 import org.apache.bval.jsr.ApacheValidatorFactory;
-import org.apache.bval.jsr.ConstraintAnnotationAttributes;
-import org.apache.bval.jsr.util.IOs;
-import org.apache.bval.util.FieldAccess;
-import org.apache.bval.util.MethodAccess;
-import org.apache.bval.util.ObjectUtils;
-import org.apache.bval.util.StringUtils;
+import org.apache.bval.jsr.metadata.XmlBuilder;
+import org.apache.bval.jsr.metadata.XmlValidationMappingProvider;
+import org.apache.bval.util.Exceptions;
+import org.apache.bval.util.Validate;
 import org.apache.bval.util.reflection.Reflection;
-import org.apache.commons.weaver.privilizer.Privileged;
 import org.apache.commons.weaver.privilizer.Privilizing;
 import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
+import org.xml.sax.InputSource;
 
 /**
- * Uses JAXB to parse constraints.xml based on validation-mapping-1.0.xsd.<br>
+ * Uses JAXB to parse constraints.xml based on the validation-mapping XML
+ * schema.
  */
 @Privilizing(@CallTo(Reflection.class))
 public class ValidationMappingParser {
-    private static final String VALIDATION_MAPPING_XSD = "META-INF/validation-mapping-1.1.xsd";
+    private static final SchemaManager SCHEMA_MANAGER = new SchemaManager.Builder()
+        .add(null, "http://jboss.org/xml/ns/javax/validation/mapping", "META-INF/validation-mapping-1.0.xsd")
+        .add(XmlBuilder.Version.v11.getId(), "http://jboss.org/xml/ns/javax/validation/mapping",
+            "META-INF/validation-mapping-1.1.xsd")
+        .add(XmlBuilder.Version.v20.getId(), "http://xmlns.jcp.org/xml/ns/javax/validation/mapping",
+            "META-INF/validation-mapping-2.0.xsd")
+        .build();
 
-    private static final Set<ConstraintAnnotationAttributes> RESERVED_PARAMS = Collections
-        .unmodifiableSet(EnumSet.of(ConstraintAnnotationAttributes.GROUPS, ConstraintAnnotationAttributes.MESSAGE,
-            ConstraintAnnotationAttributes.PAYLOAD, ConstraintAnnotationAttributes.VALIDATION_APPLIES_TO));
-
-    private final Set<Class<?>> processedClasses;
     private final ApacheValidatorFactory factory;
 
     public ValidationMappingParser(ApacheValidatorFactory factory) {
-        this.factory = factory;
-        this.processedClasses = new HashSet<Class<?>>();
+        this.factory = Validate.notNull(factory, "factory");
     }
 
     /**
-     * Parse files with constraint mappings and collect information in the factory.
-     *  
-     * @param xmlStreams - one or more contraints.xml file streams to parse
+     * Parse files with constraint mappings and collect information in the
+     * factory.
+     * 
+     * @param xmlStreams
+     *            - one or more contraints.xml file streams to parse
      */
     public void processMappingConfig(Set<InputStream> xmlStreams) throws ValidationException {
         for (final InputStream xmlStream : xmlStreams) {
-            ConstraintMappingsType mapping = parseXmlMappings(xmlStream);
-
-            final String defaultPackage = mapping.getDefaultPackage();
-            processConstraintDefinitions(mapping.getConstraintDefinition(), defaultPackage);
-            for (final BeanType bean : mapping.getBean()) {
-                Class<?> beanClass = loadClass(bean.getClazz(), defaultPackage);
-                if (!processedClasses.add(beanClass)) {
-                    // spec: A given class must not be described more than once amongst all
-                    //  the XML mapping descriptors.
-                    throw new ValidationException(beanClass.getName() + " has already be configured in xml.");
-                }
-
-                boolean ignoreAnnotations = bean.getIgnoreAnnotations() == null ? true : bean.getIgnoreAnnotations();
-                factory.getAnnotationIgnores().setDefaultIgnoreAnnotation(beanClass, ignoreAnnotations);
-                processClassLevel(bean.getClassType(), beanClass, defaultPackage);
-                processConstructorLevel(bean.getConstructor(), beanClass, defaultPackage, ignoreAnnotations);
-                processFieldLevel(bean.getField(), beanClass, defaultPackage, ignoreAnnotations);
-                final Collection<String> potentialMethodName =
-                    processPropertyLevel(bean.getGetter(), beanClass, defaultPackage, ignoreAnnotations);
-                processMethodLevel(bean.getMethod(), beanClass, defaultPackage, ignoreAnnotations, potentialMethodName);
-                processedClasses.add(beanClass);
-            }
+            final ConstraintMappingsType mapping = parseXmlMappings(xmlStream);
+            processConstraintDefinitions(mapping.getConstraintDefinition(), mapping.getDefaultPackage());
+            new XmlBuilder(mapping).forBeans().forEach(factory.getMetadataBuilders()::registerCustomBuilder);
         }
     }
 
-    /** @param in XML stream to parse using the validation-mapping-1.0.xsd */
+    /**
+     * @param in
+     *            XML stream to parse using the validation-mapping-1.0.xsd
+     */
     private ConstraintMappingsType parseXmlMappings(final InputStream in) {
-        ConstraintMappingsType mappings;
         try {
-            final JAXBContext jc = JAXBContext.newInstance(ConstraintMappingsType.class);
-            final Unmarshaller unmarshaller = jc.createUnmarshaller();
-            unmarshaller.setSchema(getSchema());
-            final StreamSource stream = new StreamSource(in);
-            final JAXBElement<ConstraintMappingsType> root =
-                unmarshaller.unmarshal(stream, ConstraintMappingsType.class);
-            mappings = root.getValue();
-        } catch (final JAXBException e) {
+            return SCHEMA_MANAGER.unmarshal(new InputSource(in), ConstraintMappingsType.class);
+        } catch (Exception e) {
             throw new ValidationException("Failed to parse XML deployment descriptor file.", e);
         } finally {
-            IOs.closeQuietly(in);
             try {
-                in.reset(); // can be read several times + we ensured it was re-readable in addMapping()
+                in.reset(); // can be read several times + we ensured it was
+                            // re-readable in addMapping()
             } catch (final IOException e) {
                 // no-op
             }
         }
-        return mappings;
-    }
-
-    /** @return validation-mapping-1.0.xsd based schema */
-    private Schema getSchema() {
-        return ValidationParser.getSchema(VALIDATION_MAPPING_XSD);
-    }
-
-    private void processClassLevel(ClassType classType, Class<?> beanClass, String defaultPackage) {
-        if (classType == null) {
-            return;
-        }
-
-        // ignore annotation
-        if (classType.getIgnoreAnnotations() != null) {
-            factory.getAnnotationIgnores().setIgnoreAnnotationsOnClass(beanClass, classType.getIgnoreAnnotations());
-        }
-
-        // group sequence
-        Class<?>[] groupSequence = createGroupSequence(classType.getGroupSequence(), defaultPackage);
-        if (groupSequence != null) {
-            factory.addDefaultSequence(beanClass, groupSequence);
-        }
-
-        // constraints
-        for (ConstraintType constraint : classType.getConstraint()) {
-            MetaConstraint<?, ?> metaConstraint = createConstraint(constraint, beanClass, null, defaultPackage);
-            factory.addMetaConstraint(beanClass, metaConstraint);
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private <A extends Annotation, T> MetaConstraint<?, ?> createConstraint(final ConstraintType constraint,
-        final Class<T> beanClass, final Member member, final String defaultPackage) {
-
-        final Class<A> annotationClass = (Class<A>) loadClass(constraint.getAnnotation(), defaultPackage);
-        final AnnotationProxyBuilder<A> annoBuilder = new AnnotationProxyBuilder<A>(annotationClass);
-
-        if (constraint.getMessage() != null) {
-            annoBuilder.setMessage(constraint.getMessage());
-        }
-        annoBuilder.setGroups(getGroups(constraint.getGroups(), defaultPackage));
-        annoBuilder.setPayload(getPayload(constraint.getPayload(), defaultPackage));
-
-        for (final ElementType elementType : constraint.getElement()) {
-            final String name = elementType.getName();
-            checkValidName(name);
-
-            final Class<?> returnType = getAnnotationParameterType(annotationClass, name);
-            final Object elementValue = getElementValue(elementType, returnType, defaultPackage);
-            annoBuilder.putValue(name, elementValue);
-        }
-        return new MetaConstraint<T, A>(beanClass, member, annoBuilder.createAnnotation());
-    }
-
-    private void checkValidName(String name) {
-        for (ConstraintAnnotationAttributes attr : RESERVED_PARAMS) {
-            if (attr.getAttributeName().equals(name)) {
-                throw new ValidationException(name + " is a reserved parameter name.");
-            }
-        }
-    }
-
-    private <A extends Annotation> Class<?> getAnnotationParameterType(final Class<A> annotationClass,
-        final String name) {
-        final Method m = Reflection.getPublicMethod(annotationClass, name);
-        if (m == null) {
-            throw new ValidationException(
-                "Annotation of type " + annotationClass.getName() + " does not contain a parameter " + name + ".");
-        }
-        return m.getReturnType();
-    }
-
-    private Object getElementValue(ElementType elementType, Class<?> returnType, String defaultPackage) {
-        removeEmptyContentElements(elementType);
-
-        boolean isArray = returnType.isArray();
-        if (!isArray) {
-            if (elementType.getContent().size() != 1) {
-                throw new ValidationException("Attempt to specify an array where single value is expected.");
-            }
-            return getSingleValue(elementType.getContent().get(0), returnType, defaultPackage);
-        }
-        List<Object> values = new ArrayList<Object>();
-        for (Serializable s : elementType.getContent()) {
-            values.add(getSingleValue(s, returnType.getComponentType(), defaultPackage));
-        }
-        return values.toArray((Object[]) Array.newInstance(returnType.getComponentType(), values.size()));
-    }
-
-    private void removeEmptyContentElements(ElementType elementType) {
-        List<Serializable> contentToDelete = new ArrayList<Serializable>();
-        for (Serializable content : elementType.getContent()) {
-            if (content instanceof String && ((String) content).matches("[\\n ].*")) {
-                contentToDelete.add(content);
-            }
-        }
-        elementType.getContent().removeAll(contentToDelete);
-    }
-
-    @SuppressWarnings("unchecked")
-    private Object getSingleValue(Serializable serializable, Class<?> returnType, String defaultPackage) {
-        if (serializable instanceof String) {
-            String value = (String) serializable;
-            return convertToResultType(returnType, value, defaultPackage);
-        }
-        if (serializable instanceof JAXBElement<?>) {
-            JAXBElement<?> elem = (JAXBElement<?>) serializable;
-            if (String.class.equals(elem.getDeclaredType())) {
-                String value = (String) elem.getValue();
-                return convertToResultType(returnType, value, defaultPackage);
-            }
-            if (AnnotationType.class.equals(elem.getDeclaredType())) {
-                AnnotationType annotationType = (AnnotationType) elem.getValue();
-                try {
-                    Class<? extends Annotation> annotationClass = (Class<? extends Annotation>) returnType;
-                    return createAnnotation(annotationType, annotationClass, defaultPackage);
-                } catch (ClassCastException e) {
-                    throw new ValidationException("Unexpected parameter value");
-                }
-            }
-        }
-        throw new ValidationException("Unexpected parameter value");
     }
 
-    private Object convertToResultType(Class<?> returnType, String value, String defaultPackage) {
-        /**
-         * Class is represented by the fully qualified class name of the class.
-         * spec: Note that if the raw string is unqualified,
-         * default package is taken into account.
-         */
-        if (returnType.equals(String.class)) {
-            return value;
-        }
-        if (returnType.equals(Class.class)) {
-            ClassLoader cl = Reflection.getClassLoader(ValidationMappingParser.class);
-            try {
-                return Reflection.toClass(toQualifiedClassName(value, defaultPackage), cl);
-            } catch (Exception e) {
-                throw new ValidationException(e);
-            }
-        }
-        if (returnType.isEnum()) {
-            try {
-                @SuppressWarnings({ "rawtypes", "unchecked" })
-                final Enum e = Enum.valueOf(returnType.asSubclass(Enum.class), value);
-                return e;
-            } catch (IllegalArgumentException e) {
-                throw new ValidationException(e);
-            }
-        }
-        if (Byte.class.equals(returnType) || byte.class.equals(returnType)) { // spec mandates it
-            return Byte.parseByte(value);
-        }
-        if (Short.class.equals(returnType) || short.class.equals(returnType)) {
-            return Short.parseShort(value);
-        }
-        if (Integer.class.equals(returnType) || int.class.equals(returnType)) {
-            return Integer.parseInt(value);
-        }
-        if (Long.class.equals(returnType) || long.class.equals(returnType)) {
-            return Long.parseLong(value);
-        }
-        if (Float.class.equals(returnType) || float.class.equals(returnType)) {
-            return Float.parseFloat(value);
-        }
-        if (Double.class.equals(returnType) || double.class.equals(returnType)) {
-            return Double.parseDouble(value);
-        }
-        if (Boolean.class.equals(returnType) || boolean.class.equals(returnType)) {
-            return Boolean.parseBoolean(value);
-        }
-        if (Character.class.equals(returnType) || char.class.equals(returnType)) {
-            if (value.length() > 1) {
-                throw new IllegalArgumentException("a char has a length of 1");
-            }
-            return value.charAt(0);
-        }
-        throw new ValidationException(String.format("Unknown annotation value type %s", returnType.getName()));
-    }
-
-    private <A extends Annotation> Annotation createAnnotation(AnnotationType annotationType, Class<A> returnType,
+    private void processConstraintDefinitions(List<ConstraintDefinitionType> constraintDefinitionList,
         String defaultPackage) {
-        AnnotationProxyBuilder<A> metaAnnotation = new AnnotationProxyBuilder<A>(returnType);
-        for (ElementType elementType : annotationType.getElement()) {
-            String name = elementType.getName();
-            Class<?> parameterType = getAnnotationParameterType(returnType, name);
-            Object elementValue = getElementValue(elementType, parameterType, defaultPackage);
-            metaAnnotation.putValue(name, elementValue);
-        }
-        return metaAnnotation.createAnnotation();
-    }
 
-    private Class<?>[] getGroups(GroupsType groupsType, String defaultPackage) {
-        if (groupsType == null) {
-            return ObjectUtils.EMPTY_CLASS_ARRAY;
-        }
+        final Map<Class<? extends Annotation>, ValidatedByType> validatorMappings = new HashMap<>();
 
-        List<Class<?>> groupList = new ArrayList<Class<?>>();
-        for (String groupClass : groupsType.getValue()) {
-            groupList.add(loadClass(groupClass, defaultPackage));
-        }
-        return groupList.toArray(new Class[groupList.size()]);
-    }
-
-    @SuppressWarnings("unchecked")
-    private Class<? extends Payload>[] getPayload(PayloadType payloadType, String defaultPackage) {
-        if (payloadType == null) {
-            return new Class[] {};
-        }
-
-        List<Class<? extends Payload>> payloadList = new ArrayList<Class<? extends Payload>>();
-        for (String groupClass : payloadType.getValue()) {
-            Class<?> payload = loadClass(groupClass, defaultPackage);
-            if (!Payload.class.isAssignableFrom(payload)) {
-                throw new ValidationException(
-                    "Specified payload class " + payload.getName() + " does not implement javax.validation.Payload");
-            }
-            payloadList.add((Class<? extends Payload>) payload);
-        }
-        return payloadList.toArray(new Class[payloadList.size()]);
-    }
-
-    private Class<?>[] createGroupSequence(GroupSequenceType groupSequenceType, String defaultPackage) {
-        if (groupSequenceType != null) {
-            Class<?>[] groupSequence = new Class<?>[groupSequenceType.getValue().size()];
-            int i = 0;
-            for (String groupName : groupSequenceType.getValue()) {
-                Class<?> group = loadClass(groupName, defaultPackage);
-                groupSequence[i++] = group;
-            }
-            return groupSequence;
-        }
-        return null;
-    }
-
-    private <A> void processMethodLevel(final List<MethodType> methods, final Class<A> beanClass,
-        final String defaultPackage, final boolean parentIgnoreAnn, final Collection<String> getters) {
-        final List<String> methodNames = new ArrayList<String>();
-        for (final MethodType methodType : methods) {
-            final String methodName = methodType.getName();
-            if (methodNames.contains(methodName) || getters.contains(methodName)) {
-                throw new ValidationException(
-                    methodName + " is defined more than once in mapping xml for bean " + beanClass.getName());
-            }
-            methodNames.add(methodName);
-
-            final Method method =
-                Reflection.getDeclaredMethod(beanClass, methodName, toTypes(methodType.getParameter(), defaultPackage));
-            if (method == null) {
-                throw new ValidationException(beanClass.getName() + " does not contain the method  " + methodName);
-            }
-
-            // ignore annotations
-            final boolean ignoreMethodAnnotation =
-                methodType.getIgnoreAnnotations() == null ? parentIgnoreAnn : methodType.getIgnoreAnnotations();
-            factory.getAnnotationIgnores().setIgnoreAnnotationsOnMember(method, ignoreMethodAnnotation);
-
-            final boolean ignoreAnn;
-            if (methodType.getIgnoreAnnotations() == null) {
-                ignoreAnn = parentIgnoreAnn;
-            } else {
-                ignoreAnn = methodType.getIgnoreAnnotations();
-            }
-
-            // constraints
-            int i = 0;
-            for (final ParameterType p : methodType.getParameter()) {
-                for (final ConstraintType constraintType : p.getConstraint()) {
-                    final MetaConstraint<?, ?> constraint =
-                        createConstraint(constraintType, beanClass, method, defaultPackage);
-                    constraint.setIndex(i);
-                    factory.addMetaConstraint(beanClass, constraint);
-                }
-                if (p.getValid() != null) {
-                    final MetaConstraint<?, ?> constraint = new MetaConstraint<A, Annotation>(beanClass, method,
-                        AnnotationProxyBuilder.ValidAnnotation.INSTANCE);
-                    constraint.setIndex(i);
-                    factory.addMetaConstraint(beanClass, constraint);
-                }
-
-                if (p.getConvertGroup() != null) {
-                    for (final GroupConversionType groupConversion : p.getConvertGroup()) {
-                        final Class<?> from = loadClass(groupConversion.getFrom(), defaultPackage);
-                        final Class<?> to = loadClass(groupConversion.getTo(), defaultPackage);
-                        final MetaConstraint<?, ?> constraint = new MetaConstraint<A, Annotation>(beanClass, method,
-                            new AnnotationProxyBuilder.ConvertGroupAnnotation(from, to));
-                        constraint.setIndex(i);
-                        factory.addMetaConstraint(beanClass, constraint);
-                    }
-                }
-
-                boolean ignoreParametersAnnotation =
-                    p.getIgnoreAnnotations() == null ? ignoreMethodAnnotation : p.getIgnoreAnnotations();
-                factory.getAnnotationIgnores().setIgnoreAnnotationsOnParameter(method, i, ignoreParametersAnnotation);
-
-                i++;
-            }
-
-            final ReturnValueType returnValue = methodType.getReturnValue();
-            if (returnValue != null) {
-                for (final ConstraintType constraintType : returnValue.getConstraint()) {
-                    final MetaConstraint<?, ?> constraint =
-                        createConstraint(constraintType, beanClass, method, defaultPackage);
-                    factory.addMetaConstraint(beanClass, constraint);
-                }
-                if (returnValue.getValid() != null) {
-                    final MetaConstraint<?, ?> constraint = new MetaConstraint<A, Annotation>(beanClass, method,
-                        AnnotationProxyBuilder.ValidAnnotation.INSTANCE);
-                    factory.addMetaConstraint(beanClass, constraint);
-                }
-
-                if (returnValue.getConvertGroup() != null) {
-                    for (final GroupConversionType groupConversion : returnValue.getConvertGroup()) {
-                        final Class<?> from = loadClass(groupConversion.getFrom(), defaultPackage);
-                        final Class<?> to = loadClass(groupConversion.getTo(), defaultPackage);
-                        final MetaConstraint<?, ?> constraint = new MetaConstraint<A, Annotation>(beanClass, method,
-                            new AnnotationProxyBuilder.ConvertGroupAnnotation(from, to));
-                        factory.addMetaConstraint(beanClass, constraint);
-                    }
-                }
-                factory.getAnnotationIgnores().setIgnoreAnnotationOnReturn(method,
-                    returnValue.getIgnoreAnnotations() == null ? ignoreAnn : returnValue.getIgnoreAnnotations());
-            }
-
-            final CrossParameterType crossParameter = methodType.getCrossParameter();
-            if (crossParameter != null) {
-                for (final ConstraintType constraintType : crossParameter.getConstraint()) {
-                    final MetaConstraint<?, ?> constraint =
-                        createConstraint(constraintType, beanClass, method, defaultPackage);
-                    factory.addMetaConstraint(beanClass, constraint);
-                }
-                factory.getAnnotationIgnores().setIgnoreAnnotationOnCrossParameter(method,
-                    crossParameter.getIgnoreAnnotations() != null ? crossParameter.getIgnoreAnnotations() : ignoreAnn);
-            }
-        }
-    }
-
-    private <A> void processConstructorLevel(final List<ConstructorType> constructors, final Class<A> beanClass,
-        final String defaultPackage, final boolean parentIgnore) {
-        for (final ConstructorType constructorType : constructors) {
-            final Constructor<?> constructor =
-                Reflection.getDeclaredConstructor(beanClass, toTypes(constructorType.getParameter(), defaultPackage));
-            if (constructor == null) {
-                throw new ValidationException(
-                    beanClass.getName() + " does not contain the constructor  " + constructorType);
-            }
-
-            // ignore annotations
-            final boolean ignoreMethodAnnotation =
-                constructorType.getIgnoreAnnotations() == null ? parentIgnore : constructorType.getIgnoreAnnotations();
-            factory.getAnnotationIgnores().setIgnoreAnnotationsOnMember(constructor, ignoreMethodAnnotation);
-
-            final boolean ignoreAnn;
-            if (constructorType.getIgnoreAnnotations() == null) {
-                ignoreAnn = parentIgnore;
-            } else {
-                ignoreAnn = constructorType.getIgnoreAnnotations();
-            }
-
-            // constraints
-            int i = 0;
-            for (final ParameterType p : constructorType.getParameter()) {
-                for (final ConstraintType constraintType : p.getConstraint()) {
-                    final MetaConstraint<?, ?> constraint =
-                        createConstraint(constraintType, beanClass, constructor, defaultPackage);
-                    constraint.setIndex(i);
-                    factory.addMetaConstraint(beanClass, constraint);
-                }
-                if (p.getValid() != null) {
-                    final MetaConstraint<?, ?> constraint = new MetaConstraint<A, Annotation>(beanClass, constructor,
-                        AnnotationProxyBuilder.ValidAnnotation.INSTANCE);
-                    constraint.setIndex(i);
-                    factory.addMetaConstraint(beanClass, constraint);
-                }
-
-                if (p.getConvertGroup() != null) {
-                    for (final GroupConversionType groupConversion : p.getConvertGroup()) {
-                        final Class<?> from = loadClass(groupConversion.getFrom(), defaultPackage);
-                        final Class<?> to = loadClass(groupConversion.getTo(), defaultPackage);
-                        final MetaConstraint<?, ?> constraint = new MetaConstraint<A, Annotation>(beanClass,
-                            constructor, new AnnotationProxyBuilder.ConvertGroupAnnotation(from, to));
-                        constraint.setIndex(i);
-                        factory.addMetaConstraint(beanClass, constraint);
-                    }
-                }
-
-                boolean ignoreParametersAnnotation =
-                    p.getIgnoreAnnotations() == null ? ignoreMethodAnnotation : p.getIgnoreAnnotations();
-                if (ignoreParametersAnnotation || (ignoreMethodAnnotation && p.getIgnoreAnnotations() == null)) {
-                    // TODO what ?
-                }
-                factory.getAnnotationIgnores().setIgnoreAnnotationsOnParameter(constructor, i,
-                    p.getIgnoreAnnotations() != null ? p.getIgnoreAnnotations() : ignoreAnn);
-
-                i++;
-            }
-
-            final ReturnValueType returnValue = constructorType.getReturnValue();
-            if (returnValue != null) {
-                for (final ConstraintType constraintType : returnValue.getConstraint()) {
-                    final MetaConstraint<?, ?> constraint =
-                        createConstraint(constraintType, beanClass, constructor, defaultPackage);
-                    constraint.setIndex(-1);
-                    factory.addMetaConstraint(beanClass, constraint);
-                }
-                if (returnValue.getValid() != null) {
-                    final MetaConstraint<?, ?> constraint = new MetaConstraint<A, Annotation>(beanClass, constructor,
-                        AnnotationProxyBuilder.ValidAnnotation.INSTANCE);
-                    constraint.setIndex(-1);
-                    factory.addMetaConstraint(beanClass, constraint);
-                }
-
-                if (returnValue.getConvertGroup() != null) {
-                    for (final GroupConversionType groupConversion : returnValue.getConvertGroup()) {
-                        final Class<?> from = loadClass(groupConversion.getFrom(), defaultPackage);
-                        final Class<?> to = loadClass(groupConversion.getTo(), defaultPackage);
-                        final MetaConstraint<?, ?> constraint = new MetaConstraint<A, Annotation>(beanClass,
-                            constructor, new AnnotationProxyBuilder.ConvertGroupAnnotation(from, to));
-                        constraint.setIndex(-1);
-                        factory.addMetaConstraint(beanClass, constraint);
-                    }
-                }
-                factory.getAnnotationIgnores().setIgnoreAnnotationOnReturn(constructor,
-                    returnValue.getIgnoreAnnotations() != null ? returnValue.getIgnoreAnnotations() : ignoreAnn);
-            }
-
-            final CrossParameterType crossParameter = constructorType.getCrossParameter();
-            if (crossParameter != null) {
-                for (final ConstraintType constraintType : crossParameter.getConstraint()) {
-                    final MetaConstraint<?, ?> constraint =
-                        createConstraint(constraintType, beanClass, constructor, defaultPackage);
-                    factory.addMetaConstraint(beanClass, constraint);
-                }
-                factory.getAnnotationIgnores().setIgnoreAnnotationOnCrossParameter(constructor,
-                    crossParameter.getIgnoreAnnotations() != null ? crossParameter.getIgnoreAnnotations() : ignoreAnn);
-            }
-        }
-    }
-
-    private Class<?>[] toTypes(final List<ParameterType> parameter, final String defaultPck) {
-        if (parameter == null) {
-            return null;
-        }
-        final Class<?>[] types = new Class<?>[parameter.size()];
-        int i = 0;
-        for (final ParameterType type : parameter) {
-            types[i++] = loadClass(type.getType(), defaultPck);
-        }
-        return types;
-    }
-
-    private <A> void processFieldLevel(List<FieldType> fields, Class<A> beanClass, String defaultPackage,
-        boolean ignoreAnnotations) {
-        final List<String> fieldNames = new ArrayList<String>();
-        for (FieldType fieldType : fields) {
-            String fieldName = fieldType.getName();
-            if (fieldNames.contains(fieldName)) {
-                throw new ValidationException(
-                    fieldName + " is defined more than once in mapping xml for bean " + beanClass.getName());
-            }
-            fieldNames.add(fieldName);
-
-            final Field field = Reflection.getDeclaredField(beanClass, fieldName);
-            if (field == null) {
-                throw new ValidationException(beanClass.getName() + " does not contain the fieldType  " + fieldName);
-            }
-
-            // ignore annotations
-            final boolean ignoreFieldAnnotation =
-                fieldType.getIgnoreAnnotations() == null ? ignoreAnnotations : fieldType.getIgnoreAnnotations();
-            factory.getAnnotationIgnores().setIgnoreAnnotationsOnMember(field, ignoreFieldAnnotation);
-
-            // valid
-            if (fieldType.getValid() != null) {
-                factory.addValid(beanClass, new FieldAccess(field));
-            }
-
-            for (final GroupConversionType conversion : fieldType.getConvertGroup()) {
-                final Class<?> from = loadClass(conversion.getFrom(), defaultPackage);
-                final Class<?> to = loadClass(conversion.getTo(), defaultPackage);
-                final MetaConstraint<?, ?> constraint = new MetaConstraint<A, Annotation>(beanClass, field,
-                    new AnnotationProxyBuilder.ConvertGroupAnnotation(from, to));
-                factory.addMetaConstraint(beanClass, constraint);
-            }
-
-            // constraints
-            for (ConstraintType constraintType : fieldType.getConstraint()) {
-                MetaConstraint<?, ?> constraint = createConstraint(constraintType, beanClass, field, defaultPackage);
-                factory.addMetaConstraint(beanClass, constraint);
-            }
-        }
-    }
-
-    private <A> Collection<String> processPropertyLevel(List<GetterType> getters, Class<A> beanClass,
-        String defaultPackage, boolean ignoreAnnotatino) {
-        List<String> getterNames = new ArrayList<String>();
-        for (GetterType getterType : getters) {
-            final String getterName = getterType.getName();
-            final String methodName = "get" + StringUtils.capitalize(getterType.getName());
-            if (getterNames.contains(methodName)) {
-                throw new ValidationException(
-                    getterName + " is defined more than once in mapping xml for bean " + beanClass.getName());
-            }
-            getterNames.add(methodName);
-
-            final Method method = getGetter(beanClass, getterName);
-            if (method == null) {
-                throw new ValidationException(beanClass.getName() + " does not contain the property  " + getterName);
-            }
-
-            // ignore annotations
-            final boolean ignoreGetterAnnotation =
-                getterType.getIgnoreAnnotations() == null ? ignoreAnnotatino : getterType.getIgnoreAnnotations();
-            factory.getAnnotationIgnores().setIgnoreAnnotationsOnMember(method, ignoreGetterAnnotation);
-
-            // valid
-            if (getterType.getValid() != null) {
-                factory.addValid(beanClass, new MethodAccess(getterName, method));
-            }
-
-            // ConvertGroup
-            for (final GroupConversionType conversion : getterType.getConvertGroup()) {
-                final Class<?> from = loadClass(conversion.getFrom(), defaultPackage);
-                final Class<?> to = loadClass(conversion.getTo(), defaultPackage);
-                final MetaConstraint<?, ?> constraint = new MetaConstraint<A, Annotation>(beanClass, method,
-                    new AnnotationProxyBuilder.ConvertGroupAnnotation(from, to));
-                factory.addMetaConstraint(beanClass, constraint);
-            }
-
-            // constraints
-            for (ConstraintType constraintType : getterType.getConstraint()) {
-                MetaConstraint<?, ?> metaConstraint =
-                    createConstraint(constraintType, beanClass, method, defaultPackage);
-                factory.addMetaConstraint(beanClass, metaConstraint);
-            }
-        }
-
-        return getterNames;
-    }
-
-    @SuppressWarnings("unchecked")
-    private void processConstraintDefinitions(List<ConstraintDefinitionType> constraintDefinitionList,
-        String defaultPackage) {
         for (ConstraintDefinitionType constraintDefinition : constraintDefinitionList) {
-            String annotationClassName = constraintDefinition.getAnnotation();
+            final String annotationClassName = constraintDefinition.getAnnotation();
 
-            Class<?> clazz = loadClass(annotationClassName, defaultPackage);
-            if (!clazz.isAnnotation()) {
-                throw new ValidationException(annotationClassName + " is not an annotation");
-            }
-            Class<? extends Annotation> annotationClass = (Class<? extends Annotation>) clazz;
+            final Class<?> clazz = loadClass(annotationClassName, defaultPackage);
 
-            ValidatedByType validatedByType = constraintDefinition.getValidatedBy();
-            List<Class<? extends ConstraintValidator<?, ?>>> classes =
-                new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
-            /*
-             If include-existing-validator is set to false,
-             ConstraintValidator defined on the constraint annotation are ignored.
-              */
-            if (validatedByType.getIncludeExistingValidators() != null
-                && validatedByType.getIncludeExistingValidators()) {
-                /*
-                 If set to true, the list of ConstraintValidators described in XML
-                 are concatenated to the list of ConstraintValidator described on the
-                 annotation to form a new array of ConstraintValidator evaluated.
-                 */
-                classes.addAll(findConstraintValidatorClasses(annotationClass));
-            }
-            for (String validatorClassName : validatedByType.getValue()) {
-                Class<? extends ConstraintValidator<?, ?>> validatorClass;
-                validatorClass = (Class<? extends ConstraintValidator<?, ?>>) loadClass(validatorClassName);
+            Exceptions.raiseUnless(clazz.isAnnotation(), ValidationException::new, "%s is not an annotation",
+                annotationClassName);
 
-                if (!ConstraintValidator.class.isAssignableFrom(validatorClass)) {
-                    throw new ValidationException(validatorClass + " is not a constraint validator class");
-                }
+            final Class<? extends Annotation> annotationClass = clazz.asSubclass(Annotation.class);
 
-                /*
-                Annotation based ConstraintValidator come before XML based
-                ConstraintValidator in the array. The new list is returned
-                by ConstraintDescriptor.getConstraintValidatorClasses().
-                 */
-                if (!classes.contains(validatorClass))
-                    classes.add(validatorClass);
-            }
-            if (factory.getConstraintsCache().containsConstraintValidator(annotationClass)) {
-                throw new ValidationException(
-                    "Constraint validator for " + annotationClass.getName() + " already configured.");
-            } else {
-                factory.getConstraintsCache().putConstraintValidator(annotationClass,
-                    classes.toArray(new Class[classes.size()]));
-            }
-        }
-    }
+            Exceptions.raiseIf(validatorMappings.containsKey(annotationClass), ValidationException::new,
+                "Constraint validator for %s already configured.", annotationClass);
 
-    private List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> findConstraintValidatorClasses(
-        Class<? extends Annotation> annotationType) {
-        List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> classes =
-            new ArrayList<Class<? extends ConstraintValidator<? extends Annotation, ?>>>();
-
-        Class<? extends ConstraintValidator<?, ?>>[] validator =
-            factory.getDefaultConstraints().getValidatorClasses(annotationType);
-        if (validator == null) {
-            /* Collections.addAll() would be more straightforward here, but there is an Oracle compiler bug of some sort
-             * that precludes this:
-             */
-            Class<? extends ConstraintValidator<?, ?>>[] validatedBy =
-                annotationType.getAnnotation(Constraint.class).validatedBy();
-            classes.addAll(Arrays.asList(validatedBy));
-        } else {
-            Collections.addAll(classes, validator);
+            validatorMappings.put(annotationClass, constraintDefinition.getValidatedBy());
         }
-        return classes;
+        factory.getConstraintsCache()
+            .add(new XmlValidationMappingProvider(validatorMappings, cn -> toQualifiedClassName(cn, defaultPackage)));
     }
 
     private Class<?> loadClass(String className, String defaultPackage) {
@@ -751,42 +121,27 @@ public class ValidationMappingParser {
     private String toQualifiedClassName(String className, String defaultPackage) {
         if (!isQualifiedClass(className)) {
             if (className.startsWith("[L") && className.endsWith(";")) {
-                className = "[L" + defaultPackage + "." + className.substring(2);
+                className = "[L" + defaultPackage + '.' + className.substring(2);
             } else {
-                className = defaultPackage + "." + className;
+                className = defaultPackage + '.' + className;
             }
         }
         return className;
     }
 
     private boolean isQualifiedClass(String clazz) {
-        return clazz.contains(".");
-    }
-
-    @Privileged
-    private static Method getGetter(Class<?> clazz, String propertyName) {
-        try {
-            final String p = StringUtils.capitalize(propertyName);
-            try {
-                return clazz.getMethod("get" + p);
-            } catch (NoSuchMethodException e) {
-                return clazz.getMethod("is" + p);
-            }
-        } catch (NoSuchMethodException e) {
-            return null;
-        }
+        return clazz.indexOf('.') >= 0;
     }
 
     private Class<?> loadClass(final String className) {
         ClassLoader loader = Reflection.getClassLoader(ValidationMappingParser.class);
-        if (loader == null)
+        if (loader == null) {
             loader = getClass().getClassLoader();
-
+        }
         try {
-            return Class.forName(className, true, loader);
+            return Reflection.toClass(className, loader);
         } catch (ClassNotFoundException ex) {
-            throw new ValidationException("Unable to load class: " + className, ex);
+            throw Exceptions.create(ValidationException::new, ex, "Unable to load class: %s", className);
         }
     }
-
 }

http://git-wip-us.apache.org/repos/asf/bval/blob/3f287a7a/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java b/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java
index 7b9b14f..bed2e10 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java
@@ -22,12 +22,14 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 import java.util.Collection;
-import java.util.Enumeration;
+import java.util.Collections;
+import java.util.EnumSet;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
+import java.util.Optional;
+import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CopyOnWriteArraySet;
 import java.util.logging.Level;
@@ -40,59 +42,34 @@ import javax.validation.TraversableResolver;
 import javax.validation.ValidationException;
 import javax.validation.executable.ExecutableType;
 import javax.validation.spi.ValidationProvider;
-import javax.xml.XMLConstants;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBElement;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Unmarshaller;
-import javax.xml.transform.stream.StreamSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.SchemaFactory;
 
 import org.apache.bval.jsr.BootstrapConfigurationImpl;
 import org.apache.bval.jsr.ConfigurationImpl;
-import org.apache.bval.jsr.util.IOs;
+import org.apache.bval.jsr.metadata.XmlBuilder;
+import org.apache.bval.util.Exceptions;
 import org.apache.bval.util.reflection.Reflection;
 import org.apache.commons.weaver.privilizer.Privileged;
 import org.apache.commons.weaver.privilizer.Privilizing;
 import org.apache.commons.weaver.privilizer.Privilizing.CallTo;
-import org.xml.sax.SAXException;
+import org.xml.sax.InputSource;
 
 /**
  * Description: uses jaxb to parse validation.xml<br/>
  */
 @Privilizing(@CallTo(Reflection.class))
 public class ValidationParser {
+
     private static final String DEFAULT_VALIDATION_XML_FILE = "META-INF/validation.xml";
-    private static final String VALIDATION_CONFIGURATION_XSD = "META-INF/validation-configuration-1.1.xsd";
     private static final Logger log = Logger.getLogger(ValidationParser.class.getName());
-    private static final ConcurrentMap<String, Schema> SCHEMA_CACHE = new ConcurrentHashMap<String, Schema>(1);
-
-    private ValidationConfigType xmlConfig;
-    private BootstrapConfigurationImpl bootstrap;
-    private Collection<ValidationException> exceptions = new CopyOnWriteArrayList<ValidationException>();
-
-    private ValidationParser() {
-        // no-op
-    }
 
-    public void applyConfigWithInstantiation(ConfigurationImpl targetConfig) {
-        if (xmlConfig == null) {
-            return;
-        }
-
-        applyProviderClass(xmlConfig, targetConfig);
-        applyMessageInterpolator(xmlConfig, targetConfig);
-        applyTraversableResolver(xmlConfig, targetConfig);
-        applyConstraintFactory(xmlConfig, targetConfig);
-        applyParameterNameProvider(xmlConfig, targetConfig);
-        applyMappingStreams(xmlConfig, targetConfig);
-        applyProperties(xmlConfig, targetConfig);
-    }
-
-    public BootstrapConfigurationImpl getBootstrap() {
-        return bootstrap;
-    }
+    private static final SchemaManager SCHEMA_MANAGER = new SchemaManager.Builder()
+        .add(null, "http://jboss.org/xml/ns/javax/validation/configuration",
+            "META-INF/validation-configuration-1.0.xsd")
+        .add(XmlBuilder.Version.v11.getId(), "http://jboss.org/xml/ns/javax/validation/configuration",
+            "META-INF/validation-configuration-1.1.xsd")
+        .add(XmlBuilder.Version.v20.getId(), "http://xmlns.jcp.org/xml/ns/javax/validation/configuration",
+            "META-INF/validation-configuration-2.0.xsd")
+        .build();
 
     public static String getValidationXmlFile(String file) {
         if (file == null) {
@@ -101,19 +78,30 @@ public class ValidationParser {
         return file;
     }
 
-    public static ValidationParser processValidationConfig(final String file, final ConfigurationImpl targetConfig, final boolean ignoreXml) {
+    public static ValidationParser processValidationConfig(final String file, final ConfigurationImpl targetConfig,
+        final boolean ignoreXml) {
         final ValidationParser parser = new ValidationParser();
 
         if (!ignoreXml) {
             parser.xmlConfig = parseXmlConfig(file);
         }
 
-        if (parser.xmlConfig != null) {
+        if (parser.xmlConfig == null) { // default config
+            final CopyOnWriteArraySet<ExecutableType> executableTypes = new CopyOnWriteArraySet<>();
+            executableTypes.add(ExecutableType.CONSTRUCTORS);
+            executableTypes.add(ExecutableType.NON_GETTER_METHODS);
+
+            parser.bootstrap = new BootstrapConfigurationImpl(null, null, null, null, null, Collections.emptySet(),
+                true, executableTypes, Collections.emptyMap(), null, Collections.emptySet());
+
+            targetConfig.setExecutableValidation(executableTypes);
+        } else {
             if (parser.xmlConfig.getExecutableValidation() == null) {
                 final ExecutableValidationType value = new ExecutableValidationType();
                 value.setEnabled(true);
 
-                final DefaultValidatedExecutableTypesType defaultValidatedExecutableTypes = new DefaultValidatedExecutableTypesType();
+                final DefaultValidatedExecutableTypesType defaultValidatedExecutableTypes =
+                    new DefaultValidatedExecutableTypesType();
                 value.setDefaultValidatedExecutableTypes(defaultValidatedExecutableTypes);
                 defaultValidatedExecutableTypes.getExecutableType().add(ExecutableType.CONSTRUCTORS);
                 defaultValidatedExecutableTypes.getExecutableType().add(ExecutableType.NON_GETTER_METHODS);
@@ -123,35 +111,19 @@ public class ValidationParser {
 
             applySimpleConfig(parser.xmlConfig, targetConfig);
 
-            parser.bootstrap = new BootstrapConfigurationImpl(
-                    parser.xmlConfig.getDefaultProvider(),
-                    parser.xmlConfig.getConstraintValidatorFactory(),
-                    parser.xmlConfig.getMessageInterpolator(),
-                    parser.xmlConfig.getTraversableResolver(),
-                    parser.xmlConfig.getParameterNameProvider(),
-                    new CopyOnWriteArraySet<String>(parser.xmlConfig.getConstraintMapping()),
-                    parser.xmlConfig.getExecutableValidation().getEnabled(),
-                    new CopyOnWriteArraySet<ExecutableType>(targetConfig.getExecutableValidation()),
-                    toMap(parser.xmlConfig.getProperty()));
-        } else { // default config
-            final CopyOnWriteArraySet<ExecutableType> executableTypes = new CopyOnWriteArraySet<ExecutableType>();
-            executableTypes.add(ExecutableType.CONSTRUCTORS);
-            executableTypes.add(ExecutableType.NON_GETTER_METHODS);
-
-            parser.bootstrap = new BootstrapConfigurationImpl(
-                    null, null, null, null, null,
-                    new CopyOnWriteArraySet<String>(),
-                    true,
-                    executableTypes,
-                    new HashMap<String, String>());
-
-            targetConfig.setExecutableValidation(executableTypes);
+            parser.bootstrap = new BootstrapConfigurationImpl(parser.xmlConfig.getDefaultProvider(),
+                parser.xmlConfig.getConstraintValidatorFactory(), parser.xmlConfig.getMessageInterpolator(),
+                parser.xmlConfig.getTraversableResolver(), parser.xmlConfig.getParameterNameProvider(),
+                new HashSet<>(parser.xmlConfig.getConstraintMapping()),
+                parser.xmlConfig.getExecutableValidation().getEnabled(),
+                new HashSet<>(targetConfig.getExecutableValidation()), toMap(parser.xmlConfig.getProperty()),
+                parser.xmlConfig.getClockProvider(), new HashSet<>(parser.xmlConfig.getValueExtractor()));
         }
         return parser;
     }
 
     private static Map<String, String> toMap(final List<PropertyType> property) {
-        final Map<String, String> map = new HashMap<String, String>();
+        final Map<String, String> map = new HashMap<>();
         if (property != null) {
             for (final PropertyType p : property) {
                 map.put(p.getName(), p.getValue());
@@ -162,78 +134,26 @@ public class ValidationParser {
 
     @Privileged
     private static ValidationConfigType parseXmlConfig(final String validationXmlFile) {
-        InputStream inputStream = null;
-        try {
-            inputStream = getInputStream(getValidationXmlFile(validationXmlFile));
+        try (InputStream inputStream = getInputStream(getValidationXmlFile(validationXmlFile))) {
             if (inputStream == null) {
-            	log.log(Level.FINEST, String.format("No %s found. Using annotation based configuration only.", validationXmlFile));
+                log.log(Level.FINEST,
+                    String.format("No %s found. Using annotation based configuration only.", validationXmlFile));
                 return null;
             }
-
             log.log(Level.FINEST, String.format("%s found.", validationXmlFile));
 
-            Schema schema = getSchema();
-            JAXBContext jc = JAXBContext.newInstance(ValidationConfigType.class);
-            Unmarshaller unmarshaller = jc.createUnmarshaller();
-            unmarshaller.setSchema(schema);
-            StreamSource stream = new StreamSource(inputStream);
-            JAXBElement<ValidationConfigType> root =
-                    unmarshaller.unmarshal(stream, ValidationConfigType.class);
-            return root.getValue();
-        } catch (JAXBException e) {
-            throw new ValidationException("Unable to parse " + validationXmlFile, e);
-        } catch (IOException e) {
+            return SCHEMA_MANAGER.unmarshal(new InputSource(inputStream), ValidationConfigType.class);
+        } catch (Exception e) {
             throw new ValidationException("Unable to parse " + validationXmlFile, e);
-        } finally {
-            IOs.closeQuietly(inputStream);
         }
     }
 
     protected static InputStream getInputStream(final String path) throws IOException {
         final ClassLoader loader = Reflection.getClassLoader(ValidationParser.class);
-        final InputStream inputStream = loader.getResourceAsStream(path);
-
-        if (inputStream != null) {
-            // spec says: If more than one META-INF/validation.xml file
-            // is found in the classpath, a ValidationException is raised.
-            final Enumeration<URL> urls = loader.getResources(path);
-            if (urls.hasMoreElements()) {
-                final String url = urls.nextElement().toString();
-                while (urls.hasMoreElements()) {
-                    if (!url.equals(urls.nextElement().toString())) { // complain when first duplicate found
-                        throw new ValidationException("More than one " + path + " is found in the classpath");
-                    }
-                }
-            }
-        }
-
-        return IOs.convertToMarkableInputStream(inputStream);
-    }
-
-    private static Schema getSchema() {
-        return getSchema(VALIDATION_CONFIGURATION_XSD);
-    }
-
-    static Schema getSchema(final String xsd) {
-        final Schema schema = SCHEMA_CACHE.get(xsd);
-        if (schema != null) {
-            return schema;
-        }
-
-        final ClassLoader loader = Reflection.getClassLoader(ValidationParser.class);
-        final SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
-        final URL schemaUrl = loader.getResource(xsd);
-        try {
-            Schema s = sf.newSchema(schemaUrl);
-            final Schema old = SCHEMA_CACHE.putIfAbsent(xsd, s);
-            if (old != null) {
-                s = old;
-            }
-            return s;
-        } catch (SAXException e) {
-            log.log(Level.WARNING, String.format("Unable to parse schema: %s", xsd), e);
-            return null;
-        }
+        final List<URL> urls = Collections.list(loader.getResources(path));
+        Exceptions.raiseIf(urls.stream().distinct().count() > 1, ValidationException::new,
+            "More than one %s is found in the classpath", path);
+        return urls.isEmpty() ? null : urls.get(0).openStream();
     }
 
     public static void applySimpleConfig(ValidationConfigType xmlConfig, ConfigurationImpl targetConfig) {
@@ -246,37 +166,84 @@ public class ValidationParser {
         }
     }
 
-    private static void applyExecutableValidation(final ValidationConfigType xmlConfig, final ConfigurationImpl targetConfig) {
-        final CopyOnWriteArrayList<ExecutableType> executableTypes = new CopyOnWriteArrayList<ExecutableType>();
-        if (xmlConfig.getExecutableValidation() != null && xmlConfig.getExecutableValidation().getEnabled()
-                && xmlConfig.getExecutableValidation().getDefaultValidatedExecutableTypes() != null) {
-            executableTypes.addAll(xmlConfig.getExecutableValidation().getDefaultValidatedExecutableTypes().getExecutableType());
-        }
+    private static void applyExecutableValidation(final ValidationConfigType xmlConfig,
+        final ConfigurationImpl targetConfig) {
+
+        final Set<ExecutableType> executableTypes = Optional.of(xmlConfig)
+            .map(ValidationConfigType::getExecutableValidation).filter(vc -> Boolean.TRUE.equals(vc.getEnabled()))
+            .map(ExecutableValidationType::getDefaultValidatedExecutableTypes)
+            .map(DefaultValidatedExecutableTypesType::getExecutableType).map(EnumSet::copyOf)
+            .orElseGet(() -> EnumSet.noneOf(ExecutableType.class));
 
         if (executableTypes.contains(ExecutableType.ALL)) {
             executableTypes.clear();
             executableTypes.add(ExecutableType.CONSTRUCTORS);
             executableTypes.add(ExecutableType.NON_GETTER_METHODS);
             executableTypes.add(ExecutableType.GETTER_METHODS);
-        } else if (executableTypes.contains(ExecutableType.NONE)) { // if both are present ALL gains
+        } else if (executableTypes.contains(ExecutableType.NONE)) { // if both are present ALL trumps NONE
             executableTypes.clear();
         }
+        targetConfig.setExecutableValidation(Collections.unmodifiableSet(executableTypes));
+    }
+
+    private static void applyMappingStreams(ValidationConfigType xmlConfig, ConfigurationImpl target) {
+        for (String rawMappingFileName : xmlConfig.getConstraintMapping()) {
+            String mappingFileName = rawMappingFileName;
+            if (mappingFileName.charAt(0) == '/') {
+                // Classloader needs a path without a starting /
+                mappingFileName = mappingFileName.substring(1);
+            }
+            log.log(Level.FINEST, String.format("Trying to open input stream for %s", mappingFileName));
+            try {
+                final InputStream in = getInputStream(mappingFileName);
+                Exceptions.raiseIf(in == null, ValidationException::new,
+                    "Unable to open input stream for mapping file %s", mappingFileName);
+                target.addMapping(in);
+            } catch (IOException e) {
+                Exceptions.raise(ValidationException::new, e, "Unable to open input stream for mapping file %s",
+                    mappingFileName);
+            }
+        }
+    }
+
+    private ValidationConfigType xmlConfig;
+    private BootstrapConfigurationImpl bootstrap;
+    private Collection<ValidationException> exceptions = new CopyOnWriteArrayList<ValidationException>();
+
+    private ValidationParser() {
+        // no-op
+    }
+
+    public void applyConfigWithInstantiation(ConfigurationImpl targetConfig) {
+        if (xmlConfig == null) {
+            return;
+        }
 
-        targetConfig.setExecutableValidation(executableTypes);
+        applyProviderClass(xmlConfig, targetConfig);
+        applyMessageInterpolator(xmlConfig, targetConfig);
+        applyTraversableResolver(xmlConfig, targetConfig);
+        applyConstraintFactory(xmlConfig, targetConfig);
+        applyParameterNameProvider(xmlConfig, targetConfig);
+        applyMappingStreams(xmlConfig, targetConfig);
+        applyProperties(xmlConfig, targetConfig);
+    }
+
+    public BootstrapConfigurationImpl getBootstrap() {
+        return bootstrap;
     }
 
-    private void applyParameterNameProvider(final ValidationConfigType xmlConfig, final ConfigurationImpl targetConfig) {
+    private void applyParameterNameProvider(final ValidationConfigType xmlConfig,
+        final ConfigurationImpl targetConfig) {
         final String parameterNameProvider = xmlConfig.getParameterNameProvider();
-        if (targetConfig.getParameterNameProvider() == targetConfig.getDefaultParameterNameProvider()) { // ref ==
-            if (parameterNameProvider != null) {
-                final Class<?> loaded = loadClass(parameterNameProvider);
-                if (loaded == null) {
-                    log.log(Level.SEVERE, "Can't load " + parameterNameProvider);
-                } else {
-                    final Class<? extends ParameterNameProvider> clazz = loaded.asSubclass(ParameterNameProvider.class);
-                    targetConfig.parameterNameProviderClass(clazz);
-                    log.log(Level.INFO, String.format("Using %s as validation provider.", parameterNameProvider));
-                }
+        if (targetConfig.getParameterNameProvider() == targetConfig.getDefaultParameterNameProvider()
+            && parameterNameProvider != null) {
+            final Class<?> loaded = loadClass(parameterNameProvider);
+            if (loaded == null) {
+                log.log(Level.SEVERE, "Can't load " + parameterNameProvider);
+            } else {
+                final Class<? extends ParameterNameProvider> clazz = loaded.asSubclass(ParameterNameProvider.class);
+                targetConfig.parameterNameProviderClass(clazz);
+                log.log(Level.INFO, String.format("Using %s as validation provider.", parameterNameProvider));
             }
         }
     }
@@ -293,65 +260,36 @@ public class ValidationParser {
     }
 
     @SuppressWarnings("unchecked")
-    private void applyMessageInterpolator(ValidationConfigType xmlConfig,
-                                          ConfigurationImpl target) {
+    private void applyMessageInterpolator(ValidationConfigType xmlConfig, ConfigurationImpl target) {
         String messageInterpolatorClass = xmlConfig.getMessageInterpolator();
-        if (target.getMessageInterpolator() == target.getDefaultMessageInterpolator()) { // ref ==
-            if (messageInterpolatorClass != null) {
-                Class<MessageInterpolator> clazz = (Class<MessageInterpolator>)
-                        loadClass(messageInterpolatorClass);
-                target.messageInterpolatorClass(clazz);
-                log.log(Level.INFO, String.format("Using %s as message interpolator.", messageInterpolatorClass));
-            }
+        if (target.getMessageInterpolator() == target.getDefaultMessageInterpolator()
+            && messageInterpolatorClass != null) {
+            Class<MessageInterpolator> clazz = (Class<MessageInterpolator>) loadClass(messageInterpolatorClass);
+            target.messageInterpolatorClass(clazz);
+            log.log(Level.INFO, String.format("Using %s as message interpolator.", messageInterpolatorClass));
         }
     }
 
     @SuppressWarnings("unchecked")
-    private void applyTraversableResolver(ValidationConfigType xmlConfig,
-                                          ConfigurationImpl target) {
+    private void applyTraversableResolver(ValidationConfigType xmlConfig, ConfigurationImpl target) {
         String traversableResolverClass = xmlConfig.getTraversableResolver();
-        if (target.getTraversableResolver() == target.getDefaultTraversableResolver() && traversableResolverClass != null) {
-		    Class<TraversableResolver> clazz = (Class<TraversableResolver>)
-		            loadClass(traversableResolverClass);
-		    target.traversableResolverClass(clazz);
-		    log.log(Level.INFO, String.format("Using %s as traversable resolver.", traversableResolverClass));
-		}
+        if (target.getTraversableResolver() == target.getDefaultTraversableResolver()
+            && traversableResolverClass != null) {
+            Class<TraversableResolver> clazz = (Class<TraversableResolver>) loadClass(traversableResolverClass);
+            target.traversableResolverClass(clazz);
+            log.log(Level.INFO, String.format("Using %s as traversable resolver.", traversableResolverClass));
+        }
     }
 
     @SuppressWarnings("unchecked")
-    private void applyConstraintFactory(ValidationConfigType xmlConfig,
-                                        ConfigurationImpl target) {
+    private void applyConstraintFactory(ValidationConfigType xmlConfig, ConfigurationImpl target) {
         String constraintFactoryClass = xmlConfig.getConstraintValidatorFactory();
-        if (target.getConstraintValidatorFactory() == target.getDefaultConstraintValidatorFactory() && constraintFactoryClass != null) {
-		    Class<ConstraintValidatorFactory> clazz = (Class<ConstraintValidatorFactory>)
-		            loadClass(constraintFactoryClass);
-		    target.constraintValidatorFactoryClass(clazz);
-		    log.log(Level.INFO, String.format("Using %s as constraint factory.", constraintFactoryClass));
-		}
-    }
-
-    private static void applyMappingStreams(ValidationConfigType xmlConfig,
-                                     ConfigurationImpl target) {
-        for (String rawMappingFileName : xmlConfig.getConstraintMapping()) {
-            String mappingFileName = rawMappingFileName;
-            if (mappingFileName.startsWith("/")) {
-                // Classloader needs a path without a starting /
-                mappingFileName = mappingFileName.substring(1);
-            }
-            log.log(Level.FINEST, String.format("Trying to open input stream for %s", mappingFileName));
-            InputStream in;
-            try {
-                in = getInputStream(mappingFileName);
-                if (in == null) {
-                    throw new ValidationException(
-                            "Unable to open input stream for mapping file " +
-                                    mappingFileName);
-                }
-            } catch (IOException e) {
-                throw new ValidationException("Unable to open input stream for mapping file " +
-                        mappingFileName, e);
-            }
-            target.addMapping(in);
+        if (target.getConstraintValidatorFactory() == target.getDefaultConstraintValidatorFactory()
+            && constraintFactoryClass != null) {
+            Class<ConstraintValidatorFactory> clazz =
+                (Class<ConstraintValidatorFactory>) loadClass(constraintFactoryClass);
+            target.constraintValidatorFactoryClass(clazz);
+            log.log(Level.INFO, String.format("Using %s as constraint factory.", constraintFactoryClass));
         }
     }
 

http://git-wip-us.apache.org/repos/asf/bval/blob/3f287a7a/bval-jsr/src/main/java/org/apache/bval/jsr/xml/XmlUtils.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/xml/XmlUtils.java b/bval-jsr/src/main/java/org/apache/bval/jsr/xml/XmlUtils.java
new file mode 100644
index 0000000..2826174
--- /dev/null
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/xml/XmlUtils.java
@@ -0,0 +1,67 @@
+/*
+ *  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.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.helpers.DefaultValidationEventHandler;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+
+import org.apache.bval.util.reflection.Reflection;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+class XmlUtils {
+    private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY = DocumentBuilderFactory.newInstance();
+    private static final Logger log = Logger.getLogger(XmlUtils.class.getName());
+    private static final SchemaFactory SCHEMA_FACTORY = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+
+    static Schema loadSchema(String resource) {
+        final URL schemaUrl = Reflection.getClassLoader(XmlUtils.class).getResource(resource);
+        try {
+            return SCHEMA_FACTORY.newSchema(schemaUrl);
+        } catch (SAXException e) {
+            log.log(Level.WARNING, String.format("Unable to parse schema: %s", resource), e);
+            return null;
+        }
+    }
+
+    static Document parse(InputStream in) throws SAXException, IOException, ParserConfigurationException {
+        return DOCUMENT_BUILDER_FACTORY.newDocumentBuilder().parse(in);
+    }
+
+    static <T> T unmarshal(Document document, Schema schema, Class<T> type) throws JAXBException {
+        final JAXBContext jc = JAXBContext.newInstance(type);
+        final Unmarshaller unmarshaller = jc.createUnmarshaller();
+        unmarshaller.setSchema(schema);
+        unmarshaller.setEventHandler(new DefaultValidationEventHandler());
+        final JAXBElement<T> root = unmarshaller.unmarshal(document, type);
+        return root.getValue();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/bval/blob/3f287a7a/bval-jsr/src/main/resources/org/apache/bval/jsr/DefaultConstraints.properties
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/resources/org/apache/bval/jsr/DefaultConstraints.properties b/bval-jsr/src/main/resources/org/apache/bval/jsr/DefaultConstraints.properties
index 7bc433b..cc5cd6c 100644
--- a/bval-jsr/src/main/resources/org/apache/bval/jsr/DefaultConstraints.properties
+++ b/bval-jsr/src/main/resources/org/apache/bval/jsr/DefaultConstraints.properties
@@ -22,22 +22,94 @@
 
 javax.validation.constraints.AssertFalse=org.apache.bval.constraints.AssertFalseValidator
 javax.validation.constraints.AssertTrue=org.apache.bval.constraints.AssertTrueValidator
+
 javax.validation.constraints.DecimalMax=org.apache.bval.constraints.DecimalMaxValidatorForNumber,\
   org.apache.bval.constraints.DecimalMaxValidatorForString
+
 javax.validation.constraints.DecimalMin=org.apache.bval.constraints.DecimalMinValidatorForNumber,\
   org.apache.bval.constraints.DecimalMinValidatorForString
+
 javax.validation.constraints.Digits=org.apache.bval.constraints.DigitsValidatorForNumber,\
   org.apache.bval.constraints.DigitsValidatorForString
-javax.validation.constraints.Future=org.apache.bval.constraints.FutureValidatorForDate,\
-  org.apache.bval.constraints.FutureValidatorForCalendar
+
+javax.validation.constraints.Email=org.apache.bval.constraints.EmailValidator
+
+javax.validation.constraints.Future=\
+  org.apache.bval.constraints.FutureValidator$ForCalendar,\
+  org.apache.bval.constraints.FutureValidator$ForDate,\
+  org.apache.bval.constraints.FutureValidator$ForChronoLocalDate,\
+  org.apache.bval.constraints.FutureValidator$ForChronoLocalDateTime,\
+  org.apache.bval.constraints.FutureValidator$ForChronoZonedDateTime,\
+  org.apache.bval.constraints.FutureValidator$ForInstant,\
+  org.apache.bval.constraints.FutureValidator$ForLocalTime,\
+  org.apache.bval.constraints.FutureValidator$ForMonthDay,\
+  org.apache.bval.constraints.FutureValidator$ForOffsetDateTime,\
+  org.apache.bval.constraints.FutureValidator$ForOffsetTime,\
+  org.apache.bval.constraints.FutureValidator$ForYear,\
+  org.apache.bval.constraints.FutureValidator$ForYearMonth
+
+javax.validation.constraints.FutureOrPresent=\
+  org.apache.bval.constraints.FutureOrPresentValidator$ForCalendar,\
+  org.apache.bval.constraints.FutureOrPresentValidator$ForDate,\
+  org.apache.bval.constraints.FutureOrPresentValidator$ForChronoLocalDate,\
+  org.apache.bval.constraints.FutureOrPresentValidator$ForChronoLocalDateTime,\
+  org.apache.bval.constraints.FutureOrPresentValidator$ForChronoZonedDateTime,\
+  org.apache.bval.constraints.FutureOrPresentValidator$ForInstant,\
+  org.apache.bval.constraints.FutureOrPresentValidator$ForLocalTime,\
+  org.apache.bval.constraints.FutureOrPresentValidator$ForMonthDay,\
+  org.apache.bval.constraints.FutureOrPresentValidator$ForOffsetDateTime,\
+  org.apache.bval.constraints.FutureOrPresentValidator$ForOffsetTime,\
+  org.apache.bval.constraints.FutureOrPresentValidator$ForYear,\
+  org.apache.bval.constraints.FutureOrPresentValidator$ForYearMonth
+
 javax.validation.constraints.Max=org.apache.bval.constraints.MaxValidatorForNumber,\
   org.apache.bval.constraints.MaxValidatorForString
+
 javax.validation.constraints.Min=org.apache.bval.constraints.MinValidatorForNumber,\
   org.apache.bval.constraints.MinValidatorForString
+
+javax.validation.constraints.Negative=org.apache.bval.constraints.NumberSignValidator$ForNegative
+javax.validation.constraints.NegativeOrZero=org.apache.bval.constraints.NumberSignValidator$ForNegative$OrZero
+
+javax.validation.constraints.NotEmpty=org.apache.bval.constraints.NotEmptyValidator,\
+ org.apache.bval.constraints.NotEmptyValidatorForCharSequence,\
+ org.apache.bval.constraints.NotEmptyValidatorForCollection,\
+ org.apache.bval.constraints.NotEmptyValidatorForMap
+
 javax.validation.constraints.NotNull=org.apache.bval.constraints.NotNullValidator
 javax.validation.constraints.Null=org.apache.bval.constraints.NullValidator
-javax.validation.constraints.Past=org.apache.bval.constraints.PastValidatorForDate,\
-  org.apache.bval.constraints.PastValidatorForCalendar
+
+javax.validation.constraints.Past=\
+  org.apache.bval.constraints.PastValidator$ForCalendar,\
+  org.apache.bval.constraints.PastValidator$ForDate,\
+  org.apache.bval.constraints.PastValidator$ForChronoLocalDate,\
+  org.apache.bval.constraints.PastValidator$ForChronoLocalDateTime,\
+  org.apache.bval.constraints.PastValidator$ForChronoZonedDateTime,\
+  org.apache.bval.constraints.PastValidator$ForInstant,\
+  org.apache.bval.constraints.PastValidator$ForLocalTime,\
+  org.apache.bval.constraints.PastValidator$ForMonthDay,\
+  org.apache.bval.constraints.PastValidator$ForOffsetDateTime,\
+  org.apache.bval.constraints.PastValidator$ForOffsetTime,\
+  org.apache.bval.constraints.PastValidator$ForYear,\
+  org.apache.bval.constraints.PastValidator$ForYearMonth
+
+javax.validation.constraints.PastOrPresent=\
+  org.apache.bval.constraints.PastOrPresentValidator$ForCalendar,\
+  org.apache.bval.constraints.PastOrPresentValidator$ForDate,\
+  org.apache.bval.constraints.PastOrPresentValidator$ForChronoLocalDate,\
+  org.apache.bval.constraints.PastOrPresentValidator$ForChronoLocalDateTime,\
+  org.apache.bval.constraints.PastOrPresentValidator$ForChronoZonedDateTime,\
+  org.apache.bval.constraints.PastOrPresentValidator$ForInstant,\
+  org.apache.bval.constraints.PastOrPresentValidator$ForLocalTime,\
+  org.apache.bval.constraints.PastOrPresentValidator$ForMonthDay,\
+  org.apache.bval.constraints.PastOrPresentValidator$ForOffsetDateTime,\
+  org.apache.bval.constraints.PastOrPresentValidator$ForOffsetTime,\
+  org.apache.bval.constraints.PastOrPresentValidator$ForYear,\
+  org.apache.bval.constraints.PastOrPresentValidator$ForYearMonth
+
+javax.validation.constraints.Positive=org.apache.bval.constraints.NumberSignValidator$ForPositive
+javax.validation.constraints.PositiveOrZero=org.apache.bval.constraints.NumberSignValidator$ForPositive$OrZero
+
 javax.validation.constraints.Size=org.apache.bval.constraints.SizeValidatorForCharSequence,\
   org.apache.bval.constraints.SizeValidatorForMap,\
   org.apache.bval.constraints.SizeValidatorForCollection,\
@@ -50,4 +122,5 @@ javax.validation.constraints.Size=org.apache.bval.constraints.SizeValidatorForCh
   org.apache.bval.constraints.SizeValidatorForArrayOfLong,\
   org.apache.bval.constraints.SizeValidatorForArrayOfObject,\
   org.apache.bval.constraints.SizeValidatorForArrayOfShort
+
 javax.validation.constraints.Pattern=org.apache.bval.constraints.PatternValidator

http://git-wip-us.apache.org/repos/asf/bval/blob/3f287a7a/bval-jsr/src/main/resources/org/apache/bval/jsr/valueextraction/DefaultExtractors.properties
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/resources/org/apache/bval/jsr/valueextraction/DefaultExtractors.properties b/bval-jsr/src/main/resources/org/apache/bval/jsr/valueextraction/DefaultExtractors.properties
new file mode 100644
index 0000000..9d9b768
--- /dev/null
+++ b/bval-jsr/src/main/resources/org/apache/bval/jsr/valueextraction/DefaultExtractors.properties
@@ -0,0 +1,25 @@
+# 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.
+
+javax.validation.valueextraction.ValueExtractor=\
+  org.apache.bval.jsr.valueextraction.IterableElementExtractor,\
+  org.apache.bval.jsr.valueextraction.ListElementExtractor
+
+javax.validation.valueextraction.ValueExtractor.container=\
+  org.apache.bval.jsr.valueextraction.MapExtractor,\
+  org.apache.bval.jsr.valueextraction.OptionalExtractor,\
+  org.apache.bval.jsr.valueextraction.FxExtractor

http://git-wip-us.apache.org/repos/asf/bval/blob/3f287a7a/bval-jsr/src/main/xjb/binding-customization.xjb
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/xjb/binding-customization.xjb b/bval-jsr/src/main/xjb/binding-customization.xjb
index 598bd3c..762a058 100644
--- a/bval-jsr/src/main/xjb/binding-customization.xjb
+++ b/bval-jsr/src/main/xjb/binding-customization.xjb
@@ -19,7 +19,7 @@
 -->
 <jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">
-  <jxb:bindings schemaLocation="../xsd/validation-mapping-1.1.xsd" node="/xs:schema">
+  <jxb:bindings schemaLocation="../xsd/validation-mapping-2.0.xsd" node="/xs:schema">
     <jxb:globalBindings>
       <xjc:javaType name="java.lang.String" xmlType="xs:string"
                     adapter="javax.xml.bind.annotation.adapters.CollapsedStringAdapter"/>
@@ -29,7 +29,7 @@
       <jxb:property name="classType"/>
     </jxb:bindings>
   </jxb:bindings>
-  <jxb:bindings schemaLocation="../xsd/validation-configuration-1.1.xsd" node="/xs:schema">
+  <jxb:bindings schemaLocation="../xsd/validation-configuration-2.0.xsd" node="/xs:schema">
     <jxb:bindings node="//xs:element[@name='executable-type']">
       <jxb:javaType name="javax.validation.executable.ExecutableType"
                     parseMethod="javax.validation.executable.ExecutableType.valueOf"/>

http://git-wip-us.apache.org/repos/asf/bval/blob/3f287a7a/bval-jsr/src/main/xsd/validation-configuration-2.0.xsd
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/xsd/validation-configuration-2.0.xsd b/bval-jsr/src/main/xsd/validation-configuration-2.0.xsd
new file mode 100644
index 0000000..6fd7874
--- /dev/null
+++ b/bval-jsr/src/main/xsd/validation-configuration-2.0.xsd
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<xs:schema attributeFormDefault="unqualified"
+           elementFormDefault="qualified"
+           targetNamespace="http://xmlns.jcp.org/xml/ns/javax/validation/configuration"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           xmlns:config="http://xmlns.jcp.org/xml/ns/javax/validation/configuration"
+           version="2.0">
+  <xs:element name="validation-config" type="config:validation-configType" />
+  <xs:complexType name="validation-configType">
+    <xs:sequence>
+      <xs:element type="xs:string" name="default-provider" minOccurs="0" />
+      <xs:element type="xs:string" name="message-interpolator" minOccurs="0" />
+      <xs:element type="xs:string" name="traversable-resolver" minOccurs="0" />
+      <xs:element type="xs:string" name="constraint-validator-factory" minOccurs="0" />
+      <xs:element type="xs:string" name="parameter-name-provider" minOccurs="0" />
+      <xs:element type="xs:string" name="clock-provider" minOccurs="0" />
+      <xs:element type="xs:string" name="value-extractor" maxOccurs="unbounded" minOccurs="0" />
+      <xs:element type="config:executable-validationType" name="executable-validation" minOccurs="0" />
+      <xs:element type="xs:string" name="constraint-mapping" maxOccurs="unbounded" minOccurs="0" />
+      <xs:element type="config:propertyType" name="property" maxOccurs="unbounded" minOccurs="0" />
+    </xs:sequence>
+    <xs:attribute name="version" type="config:versionType" fixed="2.0" /> <!-- use="required" -->
+  </xs:complexType>
+  <xs:complexType name="executable-validationType">
+    <xs:sequence>
+      <xs:element type="config:default-validated-executable-typesType" name="default-validated-executable-types" minOccurs="0" />
+    </xs:sequence>
+    <xs:attribute name="enabled" use="optional" type="xs:boolean" default="true" />
+  </xs:complexType>
+  <xs:complexType name="default-validated-executable-typesType">
+    <xs:sequence>
+      <xs:element name="executable-type" maxOccurs="unbounded" minOccurs="1">
+        <xs:simpleType>
+          <xs:restriction base="xs:string">
+            <xs:enumeration value="NONE" />
+            <xs:enumeration value="CONSTRUCTORS" />
+            <xs:enumeration value="NON_GETTER_METHODS" />
+            <xs:enumeration value="GETTER_METHODS" />
+            <xs:enumeration value="ALL" />
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:complexType name="propertyType">
+    <xs:simpleContent>
+      <xs:extension base="xs:string">
+        <xs:attribute name="name" use="required" type="xs:string" />
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+  <xs:simpleType name="versionType">
+    <xs:restriction base="xs:token">
+      <xs:pattern value="[0-9]+(\.[0-9]+)*" />
+    </xs:restriction>
+  </xs:simpleType>
+</xs:schema>