bval-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rmannibu...@apache.org
Subject svn commit: r1517540 [3/15] - in /bval/branches/bval-11/bval-jsr: ./ src/ src/main/ src/main/appended-resources/ src/main/appended-resources/META-INF/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/bval/ src/main/j...
Date Mon, 26 Aug 2013 13:59:20 GMT
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/constraints/SizeValidatorForCollection.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/constraints/SizeValidatorForCollection.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/constraints/SizeValidatorForCollection.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/constraints/SizeValidatorForCollection.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,47 @@
+/*
+ * 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.constraints;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import javax.validation.constraints.Size;
+import java.util.Collection;
+
+/** Check that a Collection's size is between min and max. */
+public class SizeValidatorForCollection extends SizeValidator
+      implements ConstraintValidator<Size, Collection<?>> {
+
+    /**
+     * Checks the number of entries in a map.
+     *
+     * @param collection The collection to validate.
+     * @param context    context in which the constraint is evaluated.
+     * @return Returns <code>true</code> if the collection is <code>null</code> or the number of entries in
+     *         <code>collection</code> is between the specified <code>min</code> and <code>max</code> values (inclusive),
+     *         <code>false</code> otherwise.
+     */
+    public boolean isValid(Collection<?> collection, ConstraintValidatorContext context) {
+        if (collection == null) {
+            return true;
+        }
+        int length = collection.size();
+        return length >= min && length <= max;
+    }
+
+}

Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/constraints/SizeValidatorForMap.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/constraints/SizeValidatorForMap.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/constraints/SizeValidatorForMap.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/constraints/SizeValidatorForMap.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,46 @@
+/*
+ * 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.constraints;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import javax.validation.constraints.Size;
+import java.util.Map;
+
+/** Check that a Map's size is between min and max. */
+public class SizeValidatorForMap extends SizeValidator
+      implements ConstraintValidator<Size, Map<?, ?>> {
+    /**
+     * Checks the number of entries in a map.
+     *
+     * @param map     The map to validate.
+     * @param context context in which the constraint is evaluated.
+     * @return Returns <code>true</code> if the map is <code>null</code> or the number of entries in <code>map</code>
+     *         is between the specified <code>min</code> and <code>max</code> values (inclusive),
+     *         <code>false</code> otherwise.
+     */
+    public boolean isValid(Map<?, ?> map, ConstraintValidatorContext context) {
+        if (map == null) {
+            return true;
+        }
+        int size = map.size();
+        return size >= min && size <= max;
+	}
+
+}

Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/el/ELFacade.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,138 @@
+/*
+ * 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.el;
+
+import javax.el.ArrayELResolver;
+import javax.el.BeanELResolver;
+import javax.el.CompositeELResolver;
+import javax.el.ELContext;
+import javax.el.ELResolver;
+import javax.el.ExpressionFactory;
+import javax.el.FunctionMapper;
+import javax.el.ListELResolver;
+import javax.el.MapELResolver;
+import javax.el.ResourceBundleELResolver;
+import javax.el.ValueExpression;
+import javax.el.VariableMapper;
+import java.lang.reflect.Method;
+import java.util.Formatter;
+import java.util.HashMap;
+import java.util.Map;
+
+// ELProcessor or JavaEE 7 would be perfect too but this impl can be used in javaee 6
+public final class ELFacade implements MessageEvaluator {
+    private static final ExpressionFactory EXPRESSION_FACTORY;
+    static {
+        ExpressionFactory ef;
+        try {
+            ef = ExpressionFactory.newInstance();
+        } catch (final Exception e) {
+            ef = null;
+        }
+        EXPRESSION_FACTORY = ef;
+    }
+    private static final ELResolver RESOLVER = initResolver();
+
+    public String interpolate(final String message, final Map<String, Object> annotationParameters, final Object validatedValue) {
+        try {
+            if (EXPRESSION_FACTORY != null) {
+                final BValELContext context = new BValELContext();
+                final VariableMapper variables = context.getVariableMapper();
+                for (final Map.Entry<String, Object> var : annotationParameters.entrySet()) {
+                    variables.setVariable(var.getKey(), EXPRESSION_FACTORY.createValueExpression(var.getValue(), Object.class));
+                }
+                variables.setVariable("validatedValue", EXPRESSION_FACTORY.createValueExpression(validatedValue, Object.class));
+
+                // #{xxx} shouldn't be evaluated
+                return EXPRESSION_FACTORY.createValueExpression(context, message.replace("#{", "\\#{"), String.class).getValue(context).toString();
+            }
+        } catch (final Exception e) {
+            // no-op
+        }
+
+        return message;
+    }
+
+    private static ELResolver initResolver() {
+        final CompositeELResolver resolver = new CompositeELResolver();
+        resolver.add(new MapELResolver());
+        resolver.add(new ListELResolver());
+        resolver.add(new ArrayELResolver());
+        resolver.add(new ResourceBundleELResolver());
+        resolver.add(new BeanELResolver());
+        return resolver;
+    }
+
+    private static class BValELContext extends ELContext {
+        private final FunctionMapper functions;
+        private final VariableMapper variables;
+
+        public BValELContext() {
+            this.variables = new BValVariableMapper();
+            this.functions = new BValFunctionMapper();
+        }
+
+        @Override
+        public ELResolver getELResolver() {
+            return RESOLVER;
+        }
+
+        @Override
+        public FunctionMapper getFunctionMapper() {
+            return functions;
+        }
+
+        @Override
+        public VariableMapper getVariableMapper() {
+            return variables;
+        }
+    }
+
+    private static class BValFunctionMapper extends FunctionMapper {
+        @Override
+        public Method resolveFunction(final String prefix, final String localName) {
+            return null;
+        }
+    }
+
+    private static class BValVariableMapper extends VariableMapper {
+        private final Map<String, ValueExpression> variables = new HashMap<String, ValueExpression>();
+
+        @Override
+        public ValueExpression resolveVariable(final String variable) {
+            if ("formatter".equals(variable)) {
+                return EXPRESSION_FACTORY.createValueExpression(new BValFormatter(), Object.class);
+            }
+            return variables.get(variable);
+        }
+
+        @Override
+        public ValueExpression setVariable(final String variable, final ValueExpression expression) {
+            variables.put(variable, expression);
+            return expression;
+        }
+    }
+
+    // used to not expose all method and avoid ambiguity with format(Local, String, Object...) in EL
+    public static class BValFormatter {
+        private final Formatter formatter = new Formatter();
+
+        public Formatter format(final String format, final Object ... args) {
+            return formatter.format(format, args);
+        }
+    }
+}

Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/el/MessageEvaluator.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/el/MessageEvaluator.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/el/MessageEvaluator.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/el/MessageEvaluator.java Mon Aug 26 13:59:15 2013
@@ -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.
+ */
+package org.apache.bval.el;
+
+import java.util.Map;
+
+// just here to ensure we can use Expression Language if at classpath
+// but not fail if not here (as before)
+public interface MessageEvaluator {
+    String interpolate(String message, Map<String, Object> annotationParameters, Object validatedValue);
+}

Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationConstraintBuilder.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,409 @@
+/*
+ * 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 org.apache.bval.jsr.groups.GroupsComputer;
+import org.apache.bval.jsr.xml.AnnotationProxyBuilder;
+import org.apache.bval.util.AccessStrategy;
+import org.apache.commons.lang3.reflect.TypeUtils;
+
+import javax.validation.Constraint;
+import javax.validation.ConstraintDeclarationException;
+import javax.validation.ConstraintDefinitionException;
+import javax.validation.ConstraintTarget;
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorFactory;
+import javax.validation.OverridesAttribute;
+import javax.validation.Payload;
+import javax.validation.ReportAsSingleViolation;
+import javax.validation.constraintvalidation.SupportedValidationTarget;
+import javax.validation.constraintvalidation.ValidationTarget;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Description: helper class that builds a {@link ConstraintValidation} or its
+ * composite constraint validations by parsing the jsr-annotations and
+ * providing information (e.g. for @OverridesAttributes) <br/>
+ */
+final class AnnotationConstraintBuilder<A extends Annotation> {
+    private static final Logger log = Logger.getLogger(AnnotationConstraintBuilder.class.getName());
+
+    private final ConstraintValidation<?> constraintValidation;
+    private List<ConstraintOverrides> overrides;
+
+    /**
+     * Create a new AnnotationConstraintBuilder instance.
+     * 
+     * @param validatorClasses
+     * @param annotation
+     * @param owner
+     * @param access
+     */
+    public AnnotationConstraintBuilder(ConstraintValidatorFactory factory, Class<? extends ConstraintValidator<A, ?>>[] validatorClasses,
+                                        A annotation, Class<?> owner, AccessStrategy access, ConstraintTarget target) {
+        boolean reportFromComposite =
+            annotation != null && annotation.annotationType().isAnnotationPresent(ReportAsSingleViolation.class);
+        constraintValidation = new ConstraintValidation<A>(factory, validatorClasses, annotation, owner, access, reportFromComposite, target);
+        buildFromAnnotation();
+    }
+
+    /** build attributes, payload, groups from 'annotation' */
+    private void buildFromAnnotation() {
+        if (constraintValidation.getAnnotation() != null) {
+            if (System.getSecurityManager() == null) {
+                doBuildFromAnnotations();
+            } else {
+                AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                    public Object run() {
+                        doBuildFromAnnotations();
+                        return null;
+                    }
+                });
+            }
+        }
+    }
+
+    private void doBuildFromAnnotations() {
+        final Class<? extends Annotation> annotationType = constraintValidation.getAnnotation().annotationType();
+
+        boolean foundPayload = false;
+        boolean foundGroups = false;
+        Method validationAppliesTo = null;
+        boolean foundMessage = false;
+
+        for (final Method method : AnnotationProxyBuilder.findMethods(annotationType)) {
+            // groups + payload must also appear in attributes (also
+            // checked by TCK-Tests)
+            if (method.getParameterTypes().length == 0) {
+                try {
+                    final String name = method.getName();
+                    if (ConstraintAnnotationAttributes.PAYLOAD.getAttributeName().equals(name)) {
+                        buildPayload(method);
+                        foundPayload = true;
+                    } else if (ConstraintAnnotationAttributes.GROUPS.getAttributeName().equals(name)) {
+                        buildGroups(method);
+                        foundGroups = true;
+                    } else if (ConstraintAnnotationAttributes.VALIDATION_APPLIES_TO.getAttributeName().equals(name)) {
+                        buildValidationAppliesTo(method);
+                        validationAppliesTo = method;
+                    } else if (name.startsWith("valid")) {
+                        throw new ConstraintDefinitionException("constraints parameters can't start with valid: " + name);
+                    } else {
+                        if (ConstraintAnnotationAttributes.MESSAGE.getAttributeName().equals(name)) {
+                            foundMessage = true;
+                            if (!TypeUtils.isAssignable(method.getReturnType(), ConstraintAnnotationAttributes.MESSAGE.getType())) {
+                                throw new ConstraintDefinitionException("Return type for message() must be of type " + ConstraintAnnotationAttributes.MESSAGE.getType());
+                            }
+                        }
+                        constraintValidation.getAttributes().put(name, method.invoke(constraintValidation.getAnnotation()));
+                    }
+                } catch (final ConstraintDefinitionException cde) {
+                    throw cde;
+                } catch (final Exception e) { // do nothing
+                    log.log(Level.WARNING, String.format("Error processing annotation: %s ", constraintValidation.getAnnotation()), e);
+                }
+            }
+        }
+
+        if (!foundMessage) {
+            throw new ConstraintDefinitionException("Annotation " + annotationType.getName() + " has no message method");
+        }
+        if (!foundPayload) {
+            throw new ConstraintDefinitionException("Annotation " + annotationType.getName() + " has no payload method");
+        }
+        if (!foundGroups) {
+            throw new ConstraintDefinitionException("Annotation " + annotationType.getName() + " has no groups method");
+        }
+        if (validationAppliesTo != null && !ConstraintTarget.IMPLICIT.equals(validationAppliesTo.getDefaultValue())) {
+            throw new ConstraintDefinitionException("validationAppliesTo default value should be IMPLICIT");
+        }
+
+        // valid validationAppliesTo
+        final Constraint annotation = annotationType.getAnnotation(Constraint.class);
+        if (annotation == null) {
+            return;
+        }
+
+        final Pair validationTarget = computeValidationTarget(annotation.validatedBy());
+        for (final Annotation a : annotationType.getAnnotations()) {
+            final Class<? extends Annotation> aClass = a.annotationType();
+            if (aClass.getName().startsWith("java.lang.annotation.")) {
+                continue;
+            }
+
+            final Constraint inheritedConstraint = aClass.getAnnotation(Constraint.class);
+            if (inheritedConstraint != null && !aClass.getName().startsWith("javax.validation.constraints.")) {
+                final Pair validationTargetInherited = computeValidationTarget(inheritedConstraint.validatedBy());
+                if ((validationTarget.a > 0 && validationTargetInherited.b > 0 && validationTarget.b == 0)
+                        || (validationTarget.b > 0 && validationTargetInherited.a > 0 && validationTarget.a == 0)) {
+                    throw new ConstraintDefinitionException("Parent and child constraint have different targets");
+                }
+            }
+        }
+    }
+
+    private Pair computeValidationTarget(final Class<?>[] validators) {
+        int param = 0;
+        int annotatedElt = 0;
+
+        for (final Class<?> validator : validators) {
+            final SupportedValidationTarget supportedAnnotationTypes = validator.getAnnotation(SupportedValidationTarget.class);
+            if (supportedAnnotationTypes != null) {
+                final List<ValidationTarget> values = Arrays.asList(supportedAnnotationTypes.value());
+                if (values.contains(ValidationTarget.PARAMETERS)) {
+                    param++;
+                }
+                if (values.contains(ValidationTarget.ANNOTATED_ELEMENT)) {
+                    annotatedElt++;
+                }
+            } else {
+                annotatedElt++;
+            }
+        }
+
+        if (annotatedElt == 0 && param >= 1 && constraintValidation.getValidationAppliesTo() != null) { // pure cross param
+            throw new ConstraintDefinitionException("pure cross parameter constraints shouldn't get validationAppliesTo attribute");
+        } else {
+            if (param >= 1 && annotatedElt >= 1 && constraintValidation.getValidationAppliesTo() == null) { // generic and cross param
+                throw new ConstraintDefinitionException("cross parameter AND generic constraints should get validationAppliesTo attribute");
+            } else if (param == 0 && constraintValidation.getValidationAppliesTo() != null) { // pure generic
+                throw new ConstraintDefinitionException("pure generic constraints shouldn't get validationAppliesTo attribute");
+            }
+        }
+
+        return new Pair(annotatedElt, param);
+    }
+
+    private void buildValidationAppliesTo(final Method method) throws InvocationTargetException, IllegalAccessException {
+        if (!TypeUtils.isAssignable(method.getReturnType(), ConstraintAnnotationAttributes.VALIDATION_APPLIES_TO.getType())) {
+            throw new ConstraintDefinitionException("Return type for validationAppliesTo() must be of type " + ConstraintAnnotationAttributes.VALIDATION_APPLIES_TO.getType());
+        }
+        final Object validationAppliesTo = method.invoke(constraintValidation.getAnnotation());
+        if (ConstraintTarget.class.isInstance(validationAppliesTo)) {
+            constraintValidation.setValidationAppliesTo(ConstraintTarget.class.cast(validationAppliesTo));
+        } else {
+            throw new ConstraintDefinitionException("validationAppliesTo type is " + ConstraintTarget.class.getName());
+        }
+    }
+
+    private void buildGroups(final Method method) throws IllegalAccessException, InvocationTargetException {
+        if (!TypeUtils.isAssignable(method.getReturnType(), ConstraintAnnotationAttributes.GROUPS.getType())) {
+            throw new ConstraintDefinitionException("Return type for groups() must be of type " + ConstraintAnnotationAttributes.GROUPS.getType());
+        }
+
+        final Object raw = method.invoke(constraintValidation.getAnnotation());
+        Class<?>[] garr;
+        if (raw instanceof Class<?>) {
+            garr = new Class[] { (Class<?>) raw };
+        } else if (raw instanceof Class<?>[]) {
+            garr = (Class<?>[]) raw;
+            if (Object[].class.cast(method.getDefaultValue()).length > 0) {
+                throw new ConstraintDefinitionException("Default value for groups() must be an empty array");
+            }
+        } else {
+            garr = null;
+        }
+
+        if (garr == null || garr.length == 0) {
+            garr = GroupsComputer.DEFAULT_GROUP;
+        }
+        constraintValidation.setGroups(garr);
+    }
+
+    @SuppressWarnings("unchecked")
+    private void buildPayload(final Method method) throws IllegalAccessException, InvocationTargetException {
+        if (!TypeUtils.isAssignable(method.getReturnType(), ConstraintAnnotationAttributes.PAYLOAD.getType())) {
+            throw new ConstraintDefinitionException("Return type for payload() must be of type " + ConstraintAnnotationAttributes.PAYLOAD.getType());
+        }
+        if (Object[].class.cast(method.getDefaultValue()).length > 0) {
+            throw new ConstraintDefinitionException("Default value for payload() must be an empty array");
+        }
+
+        Class<? extends Payload>[] payload_raw =
+            (Class<? extends Payload>[]) method.invoke(constraintValidation.getAnnotation());
+        Set<Class<? extends Payload>> payloadSet;
+        if (payload_raw == null) {
+            payloadSet = Collections.<Class<? extends Payload>> emptySet();
+        } else {
+            payloadSet = new HashSet<Class<? extends Payload>>(payload_raw.length);
+            Collections.addAll(payloadSet, payload_raw);
+        }
+        constraintValidation.setPayload(payloadSet);
+    }
+
+    /**
+     * Get the configured {@link ConstraintValidation}.
+     * 
+     * @return {@link ConstraintValidation}
+     */
+    public ConstraintValidation<?> getConstraintValidation() {
+        return constraintValidation;
+    }
+
+    /**
+     * initialize a child composite 'validation' with @OverridesAttribute from
+     * 'constraintValidation' and add to composites.
+     */
+    public void addComposed(ConstraintValidation<?> composite) {
+        applyOverridesAttributes(composite);
+
+        if (constraintValidation.getValidationAppliesTo() != null) {
+            composite.setValidationAppliesTo(constraintValidation.getValidationAppliesTo());
+        }
+
+        constraintValidation.addComposed(composite); // add AFTER apply()
+    }
+
+    private void applyOverridesAttributes(ConstraintValidation<?> composite) {
+        if (null == overrides) {
+            buildOverridesAttributes();
+        }
+        if (!overrides.isEmpty()) {
+            int index = computeIndex(composite);
+
+            // Search for the overrides to apply
+            ConstraintOverrides generalOverride = findOverride(composite.getAnnotation().annotationType(), -1);
+            if (generalOverride != null) {
+                if (index > 0) {
+                    throw new ConstraintDeclarationException("Wrong OverridesAttribute declaration for "
+                        + generalOverride.constraintType
+                        + ", it needs a defined index when there is a list of constraints");
+                }
+                generalOverride.applyOn(composite);
+            }
+
+            ConstraintOverrides override = findOverride(composite.getAnnotation().annotationType(), index);
+            if (override != null) {
+                override.applyOn(composite);
+            }
+
+        }
+    }
+
+    /**
+     * Calculates the index of the composite constraint. The index represents
+     * the order in which it is added in reference to other constraints of the
+     * same type.
+     * 
+     * @param composite
+     *            The composite constraint (not yet added).
+     * @return An integer index always >= 0
+     */
+    private int computeIndex(ConstraintValidation<?> composite) {
+        int idx = 0;
+        for (ConstraintValidation<?> each : constraintValidation.getComposingValidations()) {
+            if (each.getAnnotation().annotationType() == composite.getAnnotation().annotationType()) {
+                idx++;
+            }
+        }
+        return idx;
+    }
+
+    /** read overridesAttributes from constraintValidation.annotation */
+    private void buildOverridesAttributes() {
+        overrides = new LinkedList<ConstraintOverrides>();
+        for (Method method : constraintValidation.getAnnotation().annotationType().getDeclaredMethods()) {
+            OverridesAttribute.List annoOAL = method.getAnnotation(OverridesAttribute.List.class);
+            if (annoOAL != null) {
+                for (OverridesAttribute annoOA : annoOAL.value()) {
+                    parseConstraintOverride(method.getName(), annoOA);
+                }
+            }
+            OverridesAttribute annoOA = method.getAnnotation(OverridesAttribute.class);
+            if (annoOA != null) {
+                parseConstraintOverride(method.getName(), annoOA);
+            }
+        }
+    }
+
+    private void parseConstraintOverride(String methodName, OverridesAttribute oa) {
+        ConstraintOverrides target = findOverride(oa.constraint(), oa.constraintIndex());
+        if (target == null) {
+            target = new ConstraintOverrides(oa.constraint(), oa.constraintIndex());
+            overrides.add(target);
+        }
+        target.values.put(oa.name(), constraintValidation.getAttributes().get(methodName));
+    }
+
+    private ConstraintOverrides findOverride(Class<? extends Annotation> constraint, int constraintIndex) {
+        for (ConstraintOverrides each : overrides) {
+            if (each.constraintType == constraint && each.constraintIndex == constraintIndex) {
+                return each;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Holds the values to override in a composed constraint during creation of
+     * a composed ConstraintValidation
+     */
+    private static final class ConstraintOverrides {
+        final Class<? extends Annotation> constraintType;
+        final int constraintIndex;
+
+        /** key = attributeName, value = overridden value */
+        final Map<String, Object> values;
+
+        private ConstraintOverrides(Class<? extends Annotation> constraintType, int constraintIndex) {
+            this.constraintType = constraintType;
+            this.constraintIndex = constraintIndex;
+            values = new HashMap<String, Object>();
+        }
+
+        @SuppressWarnings("unchecked")
+        private void applyOn(ConstraintValidation<?> composite) {
+            // Update the attributes
+            composite.getAttributes().putAll(values);
+
+            // And the annotation
+            Annotation originalAnnot = composite.getAnnotation();
+            AnnotationProxyBuilder<Annotation> apb = new AnnotationProxyBuilder<Annotation>(originalAnnot);
+            for (String key : values.keySet()) {
+                apb.putValue(key, values.get(key));
+            }
+            Annotation newAnnot = apb.createAnnotation();
+            ((ConstraintValidation<Annotation>) composite).setAnnotation(newAnnot);
+        }
+    }
+
+    private static class Pair {
+        private int a;
+        private int b;
+
+        private Pair(int a, int b) {
+            this.a = a;
+            this.b = b;
+        }
+    }
+}

Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/AnnotationProcessor.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,306 @@
+/*
+ * 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 org.apache.bval.model.Features;
+import org.apache.bval.model.Meta;
+import org.apache.bval.model.MetaBean;
+import org.apache.bval.util.AccessStrategy;
+import org.apache.bval.util.reflection.Reflection;
+import org.apache.commons.lang3.ArrayUtils;
+
+import javax.validation.Constraint;
+import javax.validation.ConstraintValidator;
+import javax.validation.Valid;
+import javax.validation.constraintvalidation.SupportedValidationTarget;
+import javax.validation.constraintvalidation.ValidationTarget;
+import javax.validation.groups.ConvertGroup;
+import javax.validation.groups.Default;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * Description: implements uniform handling of JSR303 {@link Constraint}
+ * annotations, including composed constraints and the resolution of
+ * {@link ConstraintValidator} implementations.
+ */
+public final class AnnotationProcessor {
+    /** {@link ApacheFactoryContext} used */
+    private final ApacheFactoryContext factoryContext;
+
+    /**
+     * Create a new {@link AnnotationProcessor} instance.
+     * 
+     * @param factoryContext
+     */
+    public AnnotationProcessor(ApacheFactoryContext factoryContext) {
+        this.factoryContext = factoryContext;
+    }
+
+    /**
+     * Process JSR303 annotations.
+     * 
+     * @param prop
+     *            potentially null
+     * @param owner
+     *            bean type
+     * @param element
+     *            whose annotations to read
+     * @param access
+     *            strategy for <code>prop</code>
+     * @param appender
+     *            handling accumulation
+     * @return whether any processing took place
+     * @throws IllegalAccessException
+     * @throws InvocationTargetException
+     */
+    public boolean processAnnotations(Meta prop, Class<?> owner, AnnotatedElement element,
+        AccessStrategy access, AppendValidation appender) throws IllegalAccessException, InvocationTargetException {
+
+        boolean changed = false;
+        for (final Annotation annotation : element.getDeclaredAnnotations()) {
+            final Class<?> type = annotation.annotationType();
+            if (type.getName().startsWith("java.lang.annotation.")) {
+                continue;
+            }
+            changed |= processAnnotation(annotation, prop, owner, access, appender, true);
+        }
+        return changed;
+    }
+
+    /**
+     * Process a single annotation.
+     * 
+     * @param <A>
+     *            annotation type
+     * @param annotation
+     *            to process
+     * @param prop
+     *            potentially null
+     * @param owner
+     *            bean type
+     * @param access
+     *            strategy for <code>prop</code>
+     * @param appender
+     *            handling accumulation
+     * @return whether any processing took place
+     * @throws IllegalAccessException
+     * @throws InvocationTargetException
+     */
+    public <A extends Annotation> boolean processAnnotation(A annotation, Meta prop, Class<?> owner,
+        AccessStrategy access, AppendValidation appender, boolean reflection) throws IllegalAccessException, InvocationTargetException {
+        if (annotation instanceof Valid) {
+            return addAccessStrategy(prop, access);
+        }
+
+        if (ConvertGroup.class.isInstance(annotation) || ConvertGroup.List.class.isInstance(annotation)) {
+            if (!reflection) {
+                Collection<Annotation> annotations = prop.getFeature(JsrFeatures.Property.ANNOTATIONS_TO_PROCESS);
+                if (annotations == null) {
+                    annotations = new ArrayList<Annotation>();
+                    prop.putFeature(JsrFeatures.Property.ANNOTATIONS_TO_PROCESS, annotations);
+                }
+                annotations.add(annotation);
+            }
+            return true;
+        }
+
+        /**
+         * An annotation is considered a constraint definition if its retention
+         * policy contains RUNTIME and if the annotation itself is annotated
+         * with javax.validation.Constraint.
+         */
+        Constraint vcAnno = annotation.annotationType().getAnnotation(Constraint.class);
+        if (vcAnno != null) {
+            Class<? extends ConstraintValidator<A, ?>>[] validatorClasses;
+            validatorClasses = findConstraintValidatorClasses(annotation, vcAnno);
+            return applyConstraint(annotation, validatorClasses, prop, owner, access, appender);
+        }
+        /**
+         * Multi-valued constraints: To support this requirement, the bean
+         * validation provider treats regular annotations (annotations not
+         * annotated by @Constraint) whose value element has a return type of an
+         * array of constraint annotations in a special way.
+         */
+        final Object result = Reflection.INSTANCE.getAnnotationValue(annotation, ConstraintAnnotationAttributes.VALUE.getAttributeName());
+        if (result instanceof Annotation[]) {
+            boolean changed = false;
+            for (final Annotation each : (Annotation[]) result) {
+                if (each.annotationType().getName().startsWith("java.lang.annotation")) {
+                    continue;
+                }
+
+                changed |= processAnnotation(each, prop, owner, access, appender, reflection);
+            }
+            return changed;
+        }
+        return false;
+    }
+
+    /**
+     * Add the specified {@link AccessStrategy} to <code>prop</code>; noop if
+     * <code>prop == null</code>.
+     * 
+     * @param prop
+     * @param access
+     * @return whether anything took place.
+     */
+    public boolean addAccessStrategy(Meta prop, AccessStrategy access) {
+        if (prop == null) {
+            return false;
+        }
+        AccessStrategy[] strategies = prop.getFeature(Features.Property.REF_CASCADE);
+        if (strategies == null) {
+            strategies = new AccessStrategy[] { access };
+            prop.putFeature(Features.Property.REF_CASCADE, strategies);
+        } else if (!ArrayUtils.contains(strategies, access)) {
+            AccessStrategy[] newStrategies = new AccessStrategy[strategies.length + 1];
+            System.arraycopy(strategies, 0, newStrategies, 0, strategies.length);
+            newStrategies[strategies.length] = access;
+            prop.putFeature(Features.Property.REF_CASCADE, newStrategies);
+        }
+        return true;
+    }
+
+    /**
+     * Find available {@link ConstraintValidation} classes for a given
+     * constraint annotation.
+     * 
+     * @param annotation
+     * @param vcAnno
+     * @return {@link ConstraintValidation} implementation class array
+     */
+    @SuppressWarnings("unchecked")
+    private <A extends Annotation> Class<? extends ConstraintValidator<A, ?>>[] findConstraintValidatorClasses(
+        A annotation, Constraint vcAnno) {
+        if (vcAnno == null) {
+            vcAnno = annotation.annotationType().getAnnotation(Constraint.class);
+        }
+        Class<? extends ConstraintValidator<A, ?>>[] validatorClasses;
+        Class<A> annotationType = (Class<A>) annotation.annotationType();
+        validatorClasses = factoryContext.getFactory().getConstraintsCache().getConstraintValidators(annotationType);
+        if (validatorClasses == null) {
+            validatorClasses = (Class<? extends ConstraintValidator<A, ?>>[]) vcAnno.validatedBy();
+            if (validatorClasses.length == 0) {
+                validatorClasses =
+                    factoryContext.getFactory().getDefaultConstraints().getValidatorClasses(annotationType);
+            }
+        }
+        return validatorClasses;
+    }
+
+    /**
+     * Apply a constraint to the specified <code>appender</code>.
+     * 
+     * @param annotation
+     *            constraint annotation
+     * @param rawConstraintClasses
+     *            known {@link ConstraintValidator} implementation classes for
+     *            <code>annotation</code>
+     * @param prop
+     *            meta-property
+     * @param owner
+     *            type
+     * @param access
+     *            strategy
+     * @param appender
+     * @return success flag
+     * @throws IllegalAccessException
+     * @throws InvocationTargetException
+     */
+    private <A extends Annotation> boolean applyConstraint(A annotation,
+        Class<? extends ConstraintValidator<A, ?>>[] rawConstraintClasses, Meta prop, Class<?> owner,
+        AccessStrategy access, AppendValidation appender) throws IllegalAccessException, InvocationTargetException {
+
+        Class<? extends ConstraintValidator<A, ?>>[] constraintClasses = select(rawConstraintClasses, access);
+        if (constraintClasses != null && constraintClasses.length == 0 && rawConstraintClasses.length > 0) {
+            return false;
+        }
+
+        final AnnotationConstraintBuilder<A> builder =
+            new AnnotationConstraintBuilder<A>(factoryContext.getConstraintValidatorFactory(), constraintClasses, annotation, owner, access, null);
+
+        // JSR-303 3.4.4: Add implicit groups
+        if (prop != null && prop.getParentMetaBean() != null) {
+            MetaBean parentMetaBean = prop.getParentMetaBean();
+            // If:
+            // - the owner is an interface
+            // - the class of the metabean being build is different than the
+            // owner
+            // - and only the Default group is defined
+            // Then: add the owner interface as implicit groups
+            if (builder.getConstraintValidation().getOwner().isInterface()
+                && parentMetaBean.getBeanClass() != builder.getConstraintValidation().getOwner()
+                && builder.getConstraintValidation().getGroups().size() == 1
+                && builder.getConstraintValidation().getGroups().contains(Default.class)) {
+                Set<Class<?>> groups = builder.getConstraintValidation().getGroups();
+                groups.add(builder.getConstraintValidation().getOwner());
+                builder.getConstraintValidation().setGroups(groups);
+            }
+        }
+
+        // If already building a constraint composition tree, ensure that:
+        // - the parent groups are inherited
+        // - the parent payload is inherited
+        if (appender instanceof AppendValidationToBuilder) {
+            AppendValidationToBuilder avb = (AppendValidationToBuilder) appender;
+            builder.getConstraintValidation().setGroups(avb.getInheritedGroups());
+            builder.getConstraintValidation().setPayload(avb.getInheritedPayload());
+        }
+
+        // process composed constraints:
+        // here are not other superclasses possible, because annotations do not
+        // inherit!
+        processAnnotations(prop, owner, annotation.annotationType(), access, new AppendValidationToBuilder(builder));
+
+        // Even if the validator is null, it must be added to mimic the RI impl
+        appender.append(builder.getConstraintValidation());
+        return true;
+    }
+
+    private static <A extends Annotation> Class<? extends ConstraintValidator<A, ?>>[] select(
+            final Class<? extends ConstraintValidator<A, ?>>[] rawConstraintClasses, final AccessStrategy access) {
+        final boolean isReturn = ReturnAccess.class.isInstance(access);
+        final boolean isParam = ParametersAccess.class.isInstance(access);
+        if (rawConstraintClasses != null && (isReturn || isParam)) {
+            final Collection<Class<? extends ConstraintValidator<A, ?>>> selected = new ArrayList<Class<? extends ConstraintValidator<A, ?>>>();
+            for (final Class<? extends ConstraintValidator<A, ?>> constraint : rawConstraintClasses) {
+                final SupportedValidationTarget target = constraint.getAnnotation(SupportedValidationTarget.class);
+                if (target == null && isReturn) {
+                    selected.add(constraint);
+                } else if (target != null) {
+                    for (final ValidationTarget validationTarget : target.value()) {
+                        if (isReturn && ValidationTarget.ANNOTATED_ELEMENT.equals(validationTarget)) {
+                            selected.add(constraint);
+                        } else if (isParam && ValidationTarget.PARAMETERS.equals(validationTarget)) {
+                            selected.add(constraint);
+                        }
+                    }
+            }
+            }
+            return selected.toArray(new Class[selected.size()]);
+        }
+        return rawConstraintClasses;
+    }
+
+}

Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheFactoryContext.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,302 @@
+/*
+ * 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 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.util.reflection.Reflection;
+import org.apache.bval.xml.XMLMetaBeanBuilder;
+import org.apache.bval.xml.XMLMetaBeanFactory;
+import org.apache.bval.xml.XMLMetaBeanManager;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.reflect.ConstructorUtils;
+
+import javax.validation.ConstraintValidatorFactory;
+import javax.validation.MessageInterpolator;
+import javax.validation.ParameterNameProvider;
+import javax.validation.TraversableResolver;
+import javax.validation.ValidationException;
+import javax.validation.Validator;
+import javax.validation.ValidatorContext;
+import java.lang.reflect.Constructor;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Description: Represents the context that is used to create
+ * <code>ClassValidator</code> instances.<br/>
+ */
+public class ApacheFactoryContext implements ValidatorContext {
+    private final ApacheValidatorFactory factory;
+    private final MetaBeanFinder metaBeanFinder;
+
+    private MessageInterpolator messageInterpolator;
+    private TraversableResolver traversableResolver;
+    private ParameterNameProvider parameterNameProvider;
+    private ConstraintValidatorFactory constraintValidatorFactory;
+
+    /**
+     * Create a new ApacheFactoryContext instance.
+     * 
+     * @param factory validator factory
+     */
+    public ApacheFactoryContext(ApacheValidatorFactory factory) {
+        this.factory = factory;
+        this.metaBeanFinder = buildMetaBeanFinder();
+    }
+
+    /**
+     * Create a new ApacheFactoryContext instance.
+     * 
+     * @param factory validator factory
+     * @param metaBeanFinder meta finder
+     */
+    protected ApacheFactoryContext(ApacheValidatorFactory factory, MetaBeanFinder metaBeanFinder) {
+        this.factory = factory;
+        this.metaBeanFinder = metaBeanFinder;
+    }
+
+    /**
+     * Get the {@link ApacheValidatorFactory} used by this
+     * {@link ApacheFactoryContext}.
+     * 
+     * @return {@link ApacheValidatorFactory}
+     */
+    public ApacheValidatorFactory getFactory() {
+        return factory;
+    }
+
+    /**
+     * Get the metaBeanFinder.
+     * 
+     * @return {@link MetaBeanFinder}
+     */
+    public final MetaBeanFinder getMetaBeanFinder() {
+        return metaBeanFinder;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ValidatorContext messageInterpolator(MessageInterpolator messageInterpolator) {
+        this.messageInterpolator = messageInterpolator;
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ValidatorContext traversableResolver(TraversableResolver traversableResolver) {
+        this.traversableResolver = traversableResolver;
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ValidatorContext constraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) {
+        this.constraintValidatorFactory = constraintValidatorFactory;
+        return this;
+    }
+
+    public ValidatorContext parameterNameProvider(ParameterNameProvider parameterNameProvider) {
+        this.parameterNameProvider = parameterNameProvider;
+        return this;
+    }
+
+    /**
+     * Get the {@link ConstraintValidatorFactory}.
+     * 
+     * @return {@link ConstraintValidatorFactory}
+     */
+    public ConstraintValidatorFactory getConstraintValidatorFactory() {
+        return constraintValidatorFactory == null ? factory.getConstraintValidatorFactory()
+            : constraintValidatorFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Validator getValidator() {
+        ClassValidator validator = new ClassValidator(this);
+        if (Boolean.parseBoolean(factory.getProperties().get(
+            ApacheValidatorConfiguration.Properties.TREAT_MAPS_LIKE_BEANS))) {
+            validator.setTreatMapsLikeBeans(true);
+        }
+        return validator;
+    }
+
+    /**
+     * Get the {@link MessageInterpolator}.
+     * 
+     * @return {@link MessageInterpolator}
+     */
+    public MessageInterpolator getMessageInterpolator() {
+        return messageInterpolator == null ? factory.getMessageInterpolator() : messageInterpolator;
+    }
+
+    /**
+     * Get the {@link TraversableResolver}.
+     * 
+     * @return {@link TraversableResolver}
+     */
+    public TraversableResolver getTraversableResolver() {
+        return traversableResolver == null ? factory.getTraversableResolver() : traversableResolver;
+    }
+
+    public ParameterNameProvider getParameterNameProvider() {
+        return parameterNameProvider == null ? factory.getParameterNameProvider() : parameterNameProvider;
+    }
+
+    /**
+     * Create MetaBeanManager that uses factories:
+     * <ol>
+     * <li>if enabled by
+     * {@link ApacheValidatorConfiguration.Properties#ENABLE_INTROSPECTOR}, an
+     * {@link IntrospectorMetaBeanFactory}</li>
+     * <li>{@link MetaBeanFactory} types (if any) specified by
+     * {@link ApacheValidatorConfiguration.Properties#METABEAN_FACTORY_CLASSNAMES}
+     * </li>
+     * <li>if no {@link JsrMetaBeanFactory} has yet been specified (this
+     * allows factory order customization), a {@link JsrMetaBeanFactory}
+     * which handles both JSR303-XML and JSR303-Annotations</li>
+     * <li>if enabled by
+     * {@link ApacheValidatorConfiguration.Properties#ENABLE_METABEANS_XML}, an
+     * {@link XMLMetaBeanFactory}</li>
+     * </ol>
+     * 
+     * @return a new instance of MetaBeanManager with adequate MetaBeanFactories
+     */
+    protected MetaBeanFinder buildMetaBeanFinder() {
+        List<MetaBeanFactory> builders = new ArrayList<MetaBeanFactory>();
+        if (Boolean.parseBoolean(factory.getProperties().get(
+            ApacheValidatorConfiguration.Properties.ENABLE_INTROSPECTOR))) {
+            builders.add(new IntrospectorMetaBeanFactory());
+        }
+        String[] factoryClassNames =
+            StringUtils.split(
+                factory.getProperties().get(ApacheValidatorConfiguration.Properties.METABEAN_FACTORY_CLASSNAMES));
+        if (factoryClassNames != null) {
+            for (String clsName : factoryClassNames) {
+                // cast, relying on #createMetaBeanFactory to throw the exception if incompatible:
+                @SuppressWarnings("unchecked")
+                Class<? extends MetaBeanFactory> factoryClass = (Class<? extends MetaBeanFactory>) loadClass(clsName);
+                builders.add(createMetaBeanFactory(factoryClass));
+            }
+        }
+        boolean jsrFound = false;
+        for (MetaBeanFactory builder : builders) {
+            jsrFound |= builder instanceof JsrMetaBeanFactory;
+        }
+        if (!jsrFound) {
+            builders.add(new JsrMetaBeanFactory(this));
+        }
+        @SuppressWarnings("deprecation")
+        boolean enableMetaBeansXml = Boolean.parseBoolean(factory.getProperties().get(
+            ApacheValidatorConfiguration.Properties.ENABLE_METABEANS_XML));
+        if (enableMetaBeansXml) {
+            XMLMetaBeanManagerCreator.addFactory(builders);
+        }
+        return createMetaBeanManager(builders);
+    }
+
+    /**
+     * Create a {@link MetaBeanManager} using the specified builders.
+     * 
+     * @param builders
+     *            {@link MetaBeanFactory} {@link List}
+     * @return {@link MetaBeanManager}
+     */
+    @SuppressWarnings("deprecation")
+    protected MetaBeanFinder createMetaBeanManager(List<MetaBeanFactory> builders) {
+        // as long as we support both: jsr (in the builders list) and xstream-xml metabeans:
+        if (Boolean.parseBoolean(factory.getProperties().get(
+            ApacheValidatorConfiguration.Properties.ENABLE_METABEANS_XML))) {
+            return XMLMetaBeanManagerCreator.createXMLMetaBeanManager(builders);
+        }
+        return new MetaBeanManager(new MetaBeanBuilder(builders.toArray(new MetaBeanFactory[builders.size()])));
+    }
+
+    private <F extends MetaBeanFactory> F createMetaBeanFactory(final Class<F> cls) {
+        if (System.getSecurityManager() == null) {
+            return doCreateMetaBeanFactory(cls);
+        }
+        return AccessController.doPrivileged(new PrivilegedAction<F>() {
+            public F run() {
+                return doCreateMetaBeanFactory(cls);
+            }
+        });
+    }
+
+    private <F extends MetaBeanFactory> F doCreateMetaBeanFactory(final Class<F> cls) {
+        try {
+            Constructor<F> c = ConstructorUtils.getMatchingAccessibleConstructor(cls, ApacheFactoryContext.this.getClass());
+            if (c != null) {
+                return c.newInstance(ApacheFactoryContext.this);
+            }
+            c = ConstructorUtils.getMatchingAccessibleConstructor(cls, getFactory().getClass());
+            if (c != null) {
+                return c.newInstance(getFactory());
+            }
+            return cls.newInstance();
+        } catch (Exception e) {
+            throw new ValidationException(e);
+        }
+    }
+
+    /**
+     * 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 {
+
+        static void addFactory(List<MetaBeanFactory> builders) {
+            builders.add(new XMLMetaBeanFactory());
+        }
+
+        /**
+         * Create the {@link MetaBeanManager} to process JSR303 XML. Requires
+         * bval-xstream at RT.
+         * 
+         * @param builders meta bean builders
+         * @return {@link MetaBeanManager}
+         */
+        // NOTE - We return MetaBeanManager instead of XMLMetaBeanManager to
+        // keep
+        // bval-xstream an optional module.
+        protected static MetaBeanManager createXMLMetaBeanManager(List<MetaBeanFactory> builders) {
+            return new XMLMetaBeanManager(
+                new XMLMetaBeanBuilder(builders.toArray(new MetaBeanFactory[builders.size()])));
+        }
+    }
+
+    private Class<?> loadClass(final String className) {
+        try {
+            return Class.forName(className, true, Reflection.INSTANCE.getClassLoader(ApacheFactoryContext.class));
+        } catch (ClassNotFoundException ex) {
+            throw new ValidationException("Unable to load class: " + className, ex);
+        }
+    }
+}

Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidationProvider.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidationProvider.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidationProvider.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidationProvider.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,119 @@
+/*
+ * 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 org.apache.commons.lang3.ClassUtils;
+
+import javax.validation.Configuration;
+import javax.validation.ValidationException;
+import javax.validation.ValidatorFactory;
+import javax.validation.spi.BootstrapState;
+import javax.validation.spi.ConfigurationState;
+import javax.validation.spi.ValidationProvider;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Description: Implementation of {@link ValidationProvider} for jsr
+ * implementation of the apache-validation framework.
+ * <p/>
+ * <br/>
+ * User: roman.stumm <br/>
+ * Date: 29.10.2008 <br/>
+ * Time: 14:45:41 <br/>
+ */
+public class ApacheValidationProvider implements ValidationProvider<ApacheValidatorConfiguration> {
+
+    /**
+     * Learn whether a particular builder class is suitable for this
+     * {@link ValidationProvider}.
+     * 
+     * @param builderClass
+     * @return boolean suitability
+     */
+    public boolean isSuitable(Class<? extends Configuration<?>> builderClass) {
+        return ApacheValidatorConfiguration.class.equals(builderClass);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ApacheValidatorConfiguration createSpecializedConfiguration(BootstrapState state) {
+        return new ConfigurationImpl(state, this);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Configuration<?> createGenericConfiguration(BootstrapState state) {
+        return new ConfigurationImpl(state, null);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @throws javax.validation.ValidationException
+     *             if the ValidatorFactory cannot be built
+     */
+    public ValidatorFactory buildValidatorFactory(final ConfigurationState configuration) {
+        final Class<? extends ValidatorFactory> validatorFactoryClass;
+        try {
+            String validatorFactoryClassname =
+                configuration.getProperties().get(ApacheValidatorConfiguration.Properties.VALIDATOR_FACTORY_CLASSNAME);
+
+            if (validatorFactoryClassname == null) {
+                validatorFactoryClass = ApacheValidatorFactory.class;
+            } else {
+                validatorFactoryClass =
+                    ClassUtils.getClass(validatorFactoryClassname).asSubclass(ValidatorFactory.class);
+            }
+        } catch (ValidationException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            throw new ValidationException("error building ValidatorFactory", ex);
+        }
+
+        // FIXME 2011-03-27 jw:
+        // Should not use privileged action, but to avoid breaking things
+        // doing it here like the former version of this class did.
+        //
+        // The privileged action should be applied by the ValidatorFactory
+        // itself, if required.
+        // No privileges should be required to access the constructor,
+        // because the classloader of ApacheValidationProvider will always
+        // be an ancestor of the loader of validatorFactoryClass.
+        return (System.getSecurityManager() == null)
+            ? instantiateValidatorFactory(validatorFactoryClass, configuration) : AccessController
+                .doPrivileged(new PrivilegedAction<ValidatorFactory>() {
+                    public ValidatorFactory run() {
+                        return instantiateValidatorFactory(validatorFactoryClass, configuration);
+                    }
+                });
+    }
+
+    private static ValidatorFactory instantiateValidatorFactory(
+        final Class<? extends ValidatorFactory> validatorFactoryClass, final ConfigurationState configuration) {
+        try {
+            return validatorFactoryClass.getConstructor(ConfigurationState.class).newInstance(configuration);
+        } catch (final Exception ex) {
+            throw new ValidationException("Cannot instantiate : " + validatorFactoryClass, ex);
+        }
+    }
+
+}

Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorConfiguration.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,93 @@
+/*
+ * 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 javax.validation.Configuration;
+import javax.validation.ValidatorContext;
+import javax.validation.ValidatorFactory;
+import javax.validation.spi.ConfigurationState;
+
+/**
+ * Description: Uniquely identify Apache BVal in the Bean Validation bootstrap
+ * strategy. Also contains Apache BVal specific configurations<br/>
+ */
+public interface ApacheValidatorConfiguration
+      extends Configuration<ApacheValidatorConfiguration> {
+
+    /**
+     * Proprietary property keys for {@link ConfigurationImpl}  
+     */
+    public interface Properties {
+        /**
+         * the location where to look for the validation.xml file.
+         * default: "META-INF/validation.xml"
+         */
+        String VALIDATION_XML_PATH = "apache.bval.validation-xml-path";
+
+        /**
+         * true/false. use Introspector (java beans) metadata additionally
+         * to build metadata with JSR303.<br>
+         * This means that all properties exist that are java-bean properties and
+         * and that some features (Hidden, Readonly) are taken from Introspector
+         * to create the meta data.<br>
+         * default: false
+         */
+        String ENABLE_INTROSPECTOR = "apache.bval.enable-introspector";
+
+        /**
+         * true/false. use Apache metaBeans xml format additionally to
+         * build metadata with JSR303.
+         * default: false
+         *
+         * @deprecated we could decide to drop this feature in the future.
+         * we keep it as long as we support both: jsr and xstream-xml meta data at
+         * the same time (and potentially for the same domain classes)
+         */
+        String ENABLE_METABEANS_XML = "apache.bval.enable-metabeans-xml";
+
+        /**
+         * BeanValidator.treatMapsLikeBeans.
+         * default: false
+         */
+        String TREAT_MAPS_LIKE_BEANS = "apache.bval.treat-maps-like-beans";
+
+        /**
+         * Specifies the classname of the {@link ValidatorFactory} to use: this
+         * class is presumed have a constructor that accepts a single
+         * {@link ConfigurationState} argument.
+         */
+         String VALIDATOR_FACTORY_CLASSNAME = "apache.bval.validator-factory-classname";
+
+        /**
+         * Specifies the names, delimited by whitespace, of
+         * {@link MetaBeanFactory} classes that should be added to collaborate
+         * with an {@link ApacheFactoryContext}'s {@link MetaBeanFinder}. These
+         * are instantiated per {@link ValidatorContext}, attempting to use
+         * constructor arguments of decreasing specificity:
+         * <ol>
+         * <li>assignable from the creating {@link ApacheFactoryContext}</li>
+         * <li>assignable from the associated {@link ApacheValidatorFactory}</li>
+         * <li>default (no-args) constructor</li>
+         * </ol>
+         */
+         String METABEAN_FACTORY_CLASSNAMES = "apache.bval.metabean-factory-classnames";
+
+        String EXECUTABLE_VALIDATION_TYPES = "apache.bval.executable-validation.types";
+    }
+}

Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,424 @@
+/*
+ * 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 org.apache.bval.jsr.xml.AnnotationIgnores;
+import org.apache.bval.jsr.xml.MetaConstraint;
+import org.apache.bval.jsr.xml.ValidationMappingParser;
+import org.apache.bval.util.AccessStrategy;
+import org.apache.bval.util.reflection.Reflection;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.ClassUtils;
+
+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.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/>
+ * This instance is not thread-safe.<br/>
+ */
+public class ApacheValidatorFactory implements ValidatorFactory, Cloneable {
+    private static volatile ApacheValidatorFactory DEFAULT_FACTORY;
+    private static final ConstraintDefaults defaultConstraints = new ConstraintDefaults();
+
+    private MessageInterpolator messageResolver;
+    private TraversableResolver traversableResolver;
+    private ConstraintValidatorFactory constraintValidatorFactory;
+    private ParameterNameProvider parameterNameProvider;
+    private final Map<String, String> properties;
+
+    /**
+     * information from xml parsing
+     */
+    private final AnnotationIgnores annotationIgnores = new AnnotationIgnores();
+    private final ConstraintCached constraintsCache = new ConstraintCached();
+    private final Map<Class<?>, Class<?>[]> defaultSequences;
+
+    /**
+     * access strategies for properties with cascade validation @Valid support
+     */
+    private final ConcurrentMap<Class<?>, List<AccessStrategy>> validAccesses;
+    private final ConcurrentMap<Class<?>, List<MetaConstraint<?, ? extends Annotation>>> constraintMap;
+
+    private final Collection<Closeable> toClose = new ArrayList<Closeable>();
+
+    /**
+     * Convenience method to retrieve a default global ApacheValidatorFactory
+     *
+     * @return {@link ApacheValidatorFactory}
+     */
+    public static ApacheValidatorFactory getDefault() {
+        if (DEFAULT_FACTORY == null) {
+            synchronized (ApacheValidatorFactory.class) {
+                if (DEFAULT_FACTORY == null) {
+                    DEFAULT_FACTORY = Validation.byProvider(ApacheValidationProvider.class).configure()
+                        .buildValidatorFactory().unwrap(ApacheValidatorFactory.class);
+                }
+            }
+        }
+        return DEFAULT_FACTORY;
+    }
+
+    /**
+     * Set a particular {@link ApacheValidatorFactory} instance as the default.
+     *
+     * @param aDefaultFactory
+     */
+    public static void setDefault(ApacheValidatorFactory aDefaultFactory) {
+        DEFAULT_FACTORY = aDefaultFactory;
+    }
+
+    /**
+     * Create a new ApacheValidatorFactory instance.
+     */
+    public ApacheValidatorFactory(ConfigurationState configurationState) {
+        properties = new HashMap<String, String>();
+        defaultSequences = new HashMap<Class<?>, Class<?>[]>();
+        validAccesses = new ConcurrentHashMap<Class<?>, List<AccessStrategy>>();
+        constraintMap = new ConcurrentHashMap<Class<?>, List<MetaConstraint<?, ? extends Annotation>>>();
+        configure(configurationState);
+    }
+
+    /**
+     * Configure this {@link ApacheValidatorFactory} from a
+     * {@link ConfigurationState}.
+     *
+     * @param configuration
+     */
+    protected void configure(final ConfigurationState configuration) {
+        getProperties().putAll(configuration.getProperties());
+        setParameterNameProvider(configuration.getParameterNameProvider());
+        setMessageInterpolator(configuration.getMessageInterpolator());
+        setTraversableResolver(configuration.getTraversableResolver());
+        setConstraintValidatorFactory(configuration.getConstraintValidatorFactory());
+
+        if (ConfigurationImpl.class.isInstance(configuration)) {
+            final ConfigurationImpl impl = ConfigurationImpl.class.cast(configuration);
+            toClose.add(impl.getClosable());
+        }
+
+        new ValidationMappingParser(this).processMappingConfig(configuration.getMappingStreams());
+    }
+
+    /**
+     * Get the property map of this {@link ApacheValidatorFactory}.
+     *
+     * @return Map<String, String>
+     */
+    public Map<String, String> getProperties() {
+        return properties;
+    }
+
+    /**
+     * Shortcut method to create a new Validator instance with factory's
+     * settings
+     *
+     * @return the new validator instance
+     */
+    public Validator getValidator() {
+        return usingContext().getValidator();
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @return the validator factory's context
+     */
+    public ApacheFactoryContext usingContext() {
+        return new ApacheFactoryContext(this);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public synchronized ApacheValidatorFactory clone() {
+        try {
+            return (ApacheValidatorFactory) super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new InternalError(); // VM bug.
+        }
+    }
+
+    /**
+     * Set the {@link MessageInterpolator} used.
+     *
+     * @param messageResolver
+     */
+    public final void setMessageInterpolator(MessageInterpolator messageResolver) {
+        if (messageResolver != null) {
+            this.messageResolver = messageResolver;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public MessageInterpolator getMessageInterpolator() {
+        return messageResolver;
+    }
+
+    /**
+     * Set the {@link TraversableResolver} used.
+     *
+     * @param traversableResolver
+     */
+    public final void setTraversableResolver(
+            TraversableResolver traversableResolver) {
+        if (traversableResolver != null) {
+            this.traversableResolver = traversableResolver;
+        }
+    }
+
+    public void setParameterNameProvider(final ParameterNameProvider parameterNameProvider) {
+        if (parameterNameProvider != null) {
+            this.parameterNameProvider = parameterNameProvider;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public TraversableResolver getTraversableResolver() {
+        return traversableResolver;
+    }
+
+    /**
+     * Set the {@link ConstraintValidatorFactory} used.
+     *
+     * @param constraintValidatorFactory
+     */
+    public final void setConstraintValidatorFactory(
+            ConstraintValidatorFactory constraintValidatorFactory) {
+        if (constraintValidatorFactory != null) {
+            this.constraintValidatorFactory = constraintValidatorFactory;
+            if (DefaultConstraintValidatorFactory.class.isInstance(constraintValidatorFactory)) {
+                toClose.add(Closeable.class.cast(constraintValidatorFactory));
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ConstraintValidatorFactory getConstraintValidatorFactory() {
+        return constraintValidatorFactory;
+    }
+
+    public ParameterNameProvider getParameterNameProvider() {
+        return parameterNameProvider;
+    }
+
+    public void close() {
+        try {
+            for (final Closeable c : toClose) {
+                c.close();
+            }
+            toClose.clear();
+        } catch (final Exception e) {
+            // no-op
+        }
+    }
+
+    /**
+     * 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.
+     * @return an instance of the specified class
+     * @throws ValidationException if the provider does not support the call.
+     */
+    public <T> T unwrap(final Class<T> type) {
+        if (type.isInstance(this)) {
+            return (T) this;
+        }
+
+        // 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.isInterface() || Modifier.isAbstract(type
+                .getModifiers()))) {
+            return newInstance(type);
+        }
+        try {
+            Class<?> cls = ClassUtils.getClass(type.getName() + "Impl");
+            if (type.isAssignableFrom(cls)) {
+                @SuppressWarnings("unchecked")
+                T result = (T) newInstance(cls);
+                return result;
+            }
+        } catch (ClassNotFoundException e) {
+            // do nothing
+        }
+        throw new ValidationException("Type " + type + " not supported");
+    }
+
+    private <T> T newInstance(final Class<T> cls) {
+        try {
+            return Reflection.INSTANCE.newInstance(cls);
+        } catch (final RuntimeException e) {
+            throw new ValidationException(e.getCause());
+        }
+    }
+
+    /**
+     * Get the detected {@link ConstraintDefaults}.
+     *
+     * @return ConstraintDefaults
+     */
+    public ConstraintDefaults getDefaultConstraints() {
+        return defaultConstraints;
+    }
+
+    /**
+     * Get the detected {@link AnnotationIgnores}.
+     *
+     * @return AnnotationIgnores
+     */
+    public AnnotationIgnores getAnnotationIgnores() {
+        return annotationIgnores;
+    }
+
+    /**
+     * Get the constraint cache used.
+     *
+     * @return {@link ConstraintCached}
+     */
+    public ConstraintCached getConstraintsCache() {
+        return constraintsCache;
+    }
+
+    /**
+     * Add a meta-constraint to this {@link ApacheValidatorFactory}'s runtime
+     * customizations.
+     *
+     * @param beanClass
+     * @param metaConstraint
+     */
+    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>>();
+            final List<MetaConstraint<?, ? extends Annotation>> old = constraintMap.putIfAbsent(beanClass, slot);
+            if (old != null) {
+                slot = old;
+            }
+        }
+        slot.add(metaConstraint);
+    }
+
+    /**
+     * Mark a property of <code>beanClass</code> for nested validation.
+     *
+     * @param beanClass
+     * @param accessStrategy
+     *            defining the property to validate
+     */
+    public void addValid(Class<?> beanClass, AccessStrategy accessStrategy) {
+        List<AccessStrategy> slot = validAccesses.get(beanClass);
+        if (slot == null) {
+            slot = new ArrayList<AccessStrategy>();
+            final List<AccessStrategy> old = validAccesses.putIfAbsent(beanClass, slot);
+            if (old != null) {
+                slot = old;
+            }
+        }
+        slot.add(accessStrategy);
+    }
+
+    /**
+     * Set the default group sequence for a particular bean class.
+     *
+     * @param beanClass
+     * @param groupSequence
+     */
+    public void addDefaultSequence(Class<?> beanClass, Class<?>... groupSequence) {
+        defaultSequences.put(beanClass, safeArray(groupSequence));
+    }
+
+    /**
+     * Retrieve the runtime constraint configuration for a given class.
+     *
+     * @param <T>
+     * @param beanClass
+     * @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);
+        if (slot == null) {
+            return Collections.emptyList();
+        }
+        // noinspection RedundantCast
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        final List<MetaConstraint<T, ? extends Annotation>> result = (List) slot;
+        return Collections.unmodifiableList(result);
+    }
+
+    /**
+     * 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);
+    }
+
+    /**
+     * Get the default group sequence configured for <code>beanClass</code>.
+     *
+     * @param beanClass
+     * @return group Class array
+     */
+    public Class<?>[] getDefaultSequence(Class<?> beanClass) {
+        return safeArray(defaultSequences.get(beanClass));
+    }
+
+    private static Class<?>[] safeArray(Class<?>... array) {
+        return ArrayUtils.isEmpty(array) ? ArrayUtils.EMPTY_CLASS_ARRAY : ArrayUtils.clone(array);
+    }
+}

Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/AppendValidation.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/AppendValidation.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/AppendValidation.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/AppendValidation.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,32 @@
+/*
+ *  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.annotation.Annotation;
+
+/**
+ * Description: unified interface to accumulate {@link ConstraintValidation}s
+ * to varied targets.<br/>
+ */
+public interface AppendValidation {
+    /**
+     * Append a {@link ConstraintValidation}.
+     * @param <T>
+     * @param validation
+     */
+    <T extends Annotation> void append(ConstraintValidation<T> validation);
+}

Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/AppendValidationToBuilder.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/AppendValidationToBuilder.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/AppendValidationToBuilder.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/AppendValidationToBuilder.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,89 @@
+/*
+ *  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 org.apache.bval.jsr.xml.AnnotationProxyBuilder;
+
+import javax.validation.Payload;
+import java.lang.annotation.Annotation;
+import java.util.Set;
+
+/**
+ * Description: Adapt {@link AnnotationConstraintBuilder} to the {@link AppendValidation} interface.<br/>
+ */
+public class AppendValidationToBuilder extends BaseAppendValidation {
+    private final AnnotationConstraintBuilder<?> builder;
+
+    /**
+     * Create a new AppendValidationToBuilder instance.
+     * @param builder
+     */
+    public AppendValidationToBuilder(AnnotationConstraintBuilder<?> builder) {
+        this.builder = builder;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public <T extends Annotation> void preProcessValidation(ConstraintValidation<T> validation) {
+        // JSR-303 2.3:
+        // Groups from the main constraint annotation are inherited by the composing annotations.
+        // Any groups definition on a composing annotation is ignored.
+        Set<Class<?>> inheritedGroups = builder.getConstraintValidation().getGroups();
+        validation.setGroups(inheritedGroups);
+        
+        // JSR-303 2.3 p:
+        // Payloads are also inherited
+        Set<Class<? extends Payload>> inheritedPayload = builder.getConstraintValidation().getPayload();
+        validation.setPayload(inheritedPayload);
+
+        // Inherited groups and payload values must also be replicated in the 
+        // annotation, so it has to be substituted with a new proxy.
+        T originalAnnot = validation.getAnnotation();
+        AnnotationProxyBuilder<T> apb = new AnnotationProxyBuilder<T>(originalAnnot);
+        apb.putValue(ConstraintAnnotationAttributes.GROUPS.getAttributeName(),
+            inheritedGroups.toArray(new Class[inheritedGroups.size()]));
+        apb.putValue(ConstraintAnnotationAttributes.PAYLOAD.getAttributeName(),
+            inheritedPayload.toArray(new Class[inheritedPayload.size()]));
+        T newAnnot = apb.createAnnotation();
+        validation.setAnnotation(newAnnot);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public <T extends Annotation> void performAppend(ConstraintValidation<T> validation) {
+        builder.addComposed(validation);
+    }
+
+    /**
+     * Get inherited groups.
+     * @return The set of groups from the parent constraint.
+     */
+    public Set<Class<?>> getInheritedGroups() {
+        return builder.getConstraintValidation().getGroups();
+    }
+
+    /**
+     * Get inherited payload.
+     * @return The set of payloads from the parent constraint.
+     */
+    public Set<Class<? extends Payload>> getInheritedPayload() {
+        return builder.getConstraintValidation().getPayload();
+    }
+
+}



Mime
View raw message