Return-Path: X-Original-To: apmail-bval-commits-archive@www.apache.org Delivered-To: apmail-bval-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id E844910461 for ; Mon, 26 Aug 2013 14:00:26 +0000 (UTC) Received: (qmail 56802 invoked by uid 500); 26 Aug 2013 14:00:26 -0000 Delivered-To: apmail-bval-commits-archive@bval.apache.org Received: (qmail 56770 invoked by uid 500); 26 Aug 2013 14:00:26 -0000 Mailing-List: contact commits-help@bval.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@bval.apache.org Delivered-To: mailing list commits@bval.apache.org Received: (qmail 56762 invoked by uid 99); 26 Aug 2013 14:00:25 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 26 Aug 2013 14:00:25 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 26 Aug 2013 14:00:21 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id A19C82388BEF; Mon, 26 Aug 2013 13:59:31 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: svn commit: r1517540 [10/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/... Date: Mon, 26 Aug 2013 13:59:20 -0000 To: commits@bval.apache.org From: rmannibucau@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20130826135931.A19C82388BEF@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java?rev=1517540&view=auto ============================================================================== --- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java (added) +++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationMappingParser.java Mon Aug 26 13:59:15 2013 @@ -0,0 +1,787 @@ +/* + * 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 org.apache.bval.jsr.ApacheValidatorFactory; +import org.apache.bval.jsr.ConstraintAnnotationAttributes; +import org.apache.bval.jsr.util.EnumerationConverter; +import org.apache.bval.jsr.util.IOs; +import org.apache.bval.util.FieldAccess; +import org.apache.bval.util.MethodAccess; +import org.apache.bval.util.reflection.Reflection; +import org.apache.commons.beanutils.ConvertUtils; +import org.apache.commons.beanutils.Converter; +import org.apache.commons.lang3.StringUtils; + +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 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.security.AccessController; +import java.security.PrivilegedAction; +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.List; +import java.util.Set; + +/** + * Uses JAXB to parse constraints.xml based on validation-mapping-1.0.xsd.
+ */ +@SuppressWarnings("restriction") +public class ValidationMappingParser { + // private static final Log log = LogFactory.getLog(ValidationMappingParser.class); + private static final String VALIDATION_MAPPING_XSD = "META-INF/validation-mapping-1.1.xsd"; + + private static final Set RESERVED_PARAMS = Collections.unmodifiableSet(EnumSet.of( + ConstraintAnnotationAttributes.GROUPS, ConstraintAnnotationAttributes.MESSAGE, + ConstraintAnnotationAttributes.PAYLOAD, ConstraintAnnotationAttributes.VALIDATION_APPLIES_TO)); + + private final Set> processedClasses; + private final ApacheValidatorFactory factory; + + public ValidationMappingParser(ApacheValidatorFactory factory) { + this.factory = factory; + this.processedClasses = new HashSet>(); + } + + /** + * 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 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 potentialMethodName = processPropertyLevel(bean.getGetter(), beanClass, defaultPackage, ignoreAnnotations); + processMethodLevel(bean.getMethod(), beanClass, defaultPackage, ignoreAnnotations, potentialMethodName); + processedClasses.add(beanClass); + } + } + } + + /** @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 root = unmarshaller.unmarshal(stream, ConstraintMappingsType.class); + mappings = root.getValue(); + } catch (final JAXBException 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() + } 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 MetaConstraint createConstraint( + final ConstraintType constraint, final Class beanClass, + final Member member, final String defaultPackage) { + + final Class annotationClass = (Class) loadClass(constraint.getAnnotation(), defaultPackage); + final AnnotationProxyBuilder annoBuilder = new AnnotationProxyBuilder(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(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 Class getAnnotationParameterType( + final Class annotationClass, final String name) { + final Method m = Reflection.INSTANCE.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); + } else { + List values = new ArrayList(); + 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 contentToDelete = new ArrayList(); + 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) { + + Object returnValue; + if (serializable instanceof String) { + String value = (String) serializable; + returnValue = convertToResultType(returnType, value, defaultPackage); + } else if (serializable instanceof JAXBElement && + ((JAXBElement) serializable).getDeclaredType() + .equals(String.class)) { + JAXBElement elem = (JAXBElement) serializable; + String value = (String) elem.getValue(); + returnValue = convertToResultType(returnType, value, defaultPackage); + } else if (serializable instanceof JAXBElement && + ((JAXBElement) serializable).getDeclaredType() + .equals(AnnotationType.class)) { + JAXBElement elem = (JAXBElement) serializable; + AnnotationType annotationType = (AnnotationType) elem.getValue(); + try { + Class annotationClass = (Class) returnType; + returnValue = + createAnnotation(annotationType, annotationClass, defaultPackage); + } catch (ClassCastException e) { + throw new ValidationException("Unexpected parameter value"); + } + } else { + throw new ValidationException("Unexpected parameter value"); + } + return returnValue; + + } + + 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(Class.class)) { + value = toQualifiedClassName(value, defaultPackage); + } else if (Byte.class.equals(returnType) || byte.class.equals(returnType)) { // spec mandates it + return Byte.parseByte(value); + } else if (Short.class.equals(returnType) || short.class.equals(returnType)) { + return Short.parseShort(value); + } else if (Integer.class.equals(returnType) || int.class.equals(returnType)) { + return Integer.parseInt(value); + } else if (Long.class.equals(returnType) || long.class.equals(returnType)) { + return Long.parseLong(value); + } else if (Float.class.equals(returnType) || float.class.equals(returnType)) { + return Float.parseFloat(value); + } else if (Double.class.equals(returnType) || double.class.equals(returnType)) { + return Double.parseDouble(value); + } else if (Boolean.class.equals(returnType) || boolean.class.equals(returnType)) { + return Boolean.parseBoolean(value); + } else 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); + } + + /* Converter lookup */ + Converter converter = ConvertUtils.lookup(returnType); + if (converter == null && returnType.isEnum()) { + converter = EnumerationConverter.getInstance(); + } + + if (converter != null) { + return converter.convert(returnType, value); + } else { + return converter; + } + } + + private Annotation createAnnotation(AnnotationType annotationType, + Class returnType, + String defaultPackage) { + AnnotationProxyBuilder metaAnnotation = new AnnotationProxyBuilder(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 new Class[]{}; + } + + List> groupList = new ArrayList>(); + for (String groupClass : groupsType.getValue()) { + groupList.add(loadClass(groupClass, defaultPackage)); + } + return groupList.toArray(new Class[groupList.size()]); + } + + + @SuppressWarnings("unchecked") + private Class[] getPayload(PayloadType payloadType, + String defaultPackage) { + if (payloadType == null) { + return new Class[]{}; + } + + List> payloadList = new ArrayList>(); + 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"); + } else { + payloadList.add((Class) 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; + } else { + return null; + } + } + + private void processMethodLevel(final List methods, final Class beanClass, final String defaultPackage, final boolean parentIgnoreAnn, final Collection getters) { + final List methodNames = new ArrayList(); + 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()); + } else { + methodNames.add(methodName); + } + final Method method = Reflection.INSTANCE.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 = methodType.getIgnoreAnnotations(); + } else { + ignoreAnn = parentIgnoreAnn; + } + + // 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(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(beanClass, method, new AnnotationProxyBuilder.ConverGroupAnnotation(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(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(beanClass, method, new AnnotationProxyBuilder.ConverGroupAnnotation(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 void processConstructorLevel(final List constructors, final Class beanClass, final String defaultPackage, final boolean parentIgnore) { + for (final ConstructorType constructorType : constructors) { + final Constructor constructor = Reflection.INSTANCE.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 = constructorType.getIgnoreAnnotations(); + } else { + ignoreAnn = parentIgnore; + } + + // 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(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(beanClass, constructor, new AnnotationProxyBuilder.ConverGroupAnnotation(from, to)); + constraint.setIndex(i); + factory.addMetaConstraint(beanClass, constraint); + } + } + + boolean ignoreParametersAnnotation = p.getIgnoreAnnotations() == null ? ignoreMethodAnnotation : p.getIgnoreAnnotations(); + if (ignoreParametersAnnotation || (ignoreMethodAnnotation && p.getIgnoreAnnotations() == null)) { + + } + 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(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(beanClass, constructor, new AnnotationProxyBuilder.ConverGroupAnnotation(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 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 void processFieldLevel(List fields, Class beanClass, + String defaultPackage, boolean ignoreAnnotations) { + final List fieldNames = new ArrayList(); + 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()); + } else { + fieldNames.add(fieldName); + } + final Field field = Reflection.INSTANCE.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(beanClass, field, new AnnotationProxyBuilder.ConverGroupAnnotation(from, to)); + factory.addMetaConstraint(beanClass, constraint); + } + + // constraints + for (ConstraintType constraintType : fieldType.getConstraint()) { + MetaConstraint constraint = + createConstraint(constraintType, beanClass, field, defaultPackage); + factory.addMetaConstraint(beanClass, constraint); + } + } + } + + private Collection processPropertyLevel(List getters, Class beanClass, + String defaultPackage, boolean ignoreAnnotatino) { + List getterNames = new ArrayList(); + 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()); + } else { + 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(beanClass, method, new AnnotationProxyBuilder.ConverGroupAnnotation(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 constraintDefinitionList, String defaultPackage) { + for (ConstraintDefinitionType constraintDefinition : constraintDefinitionList) { + String annotationClassName = constraintDefinition.getAnnotation(); + + Class clazz = loadClass(annotationClassName, defaultPackage); + if (!clazz.isAnnotation()) { + throw new ValidationException(annotationClassName + " is not an annotation"); + } + Class annotationClass = (Class) clazz; + + ValidatedByType validatedByType = constraintDefinition.getValidatedBy(); + List>> classes = + new ArrayList>>(); + /* + 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> validatorClass; + validatorClass = (Class>) + loadClass(validatorClassName); + + + if (!ConstraintValidator.class.isAssignableFrom(validatorClass)) { + throw new ValidationException( + validatorClass + " is not a constraint validator 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()])); + } + } + } + + private List>> findConstraintValidatorClasses( + Class annotationType) { + List>> classes = + new ArrayList>>(); + + Class>[] validator = + factory.getDefaultConstraints().getValidatorClasses(annotationType); + if (validator != null) { + classes + .addAll(Arrays.asList(validator)); + } else { + Class>[] validatedBy = annotationType + .getAnnotation(Constraint.class) + .validatedBy(); + classes.addAll(Arrays.asList(validatedBy)); + } + return classes; + } + + private Class loadClass(String className, String defaultPackage) { + return loadClass(toQualifiedClassName(className, defaultPackage)); + } + + private String toQualifiedClassName(String className, String defaultPackage) { + if (!isQualifiedClass(className)) { + if (className.startsWith("[L") && className.endsWith(";")) { + className = "[L" + defaultPackage + "." + className.substring(2); + } else { + className = defaultPackage + "." + className; + } + } + return className; + } + + private boolean isQualifiedClass(String clazz) { + return clazz.contains("."); + } + + private static Method getGetter(final Class clazz, final String propertyName) { + if (System.getSecurityManager() == null) { + return doGetGetter(propertyName, clazz); + } + return AccessController.doPrivileged(new PrivilegedAction() { + public Method run() { + return doGetGetter(propertyName, clazz); + } + }); + + } + + private static Method doGetGetter(String propertyName, Class clazz) { + 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; + } + } + + + private Class loadClass(final String className) { + ClassLoader loader = Reflection.INSTANCE.getClassLoader(ValidationMappingParser.class); + if (loader == null) + loader = getClass().getClassLoader(); + + try { + return Class.forName(className, true, loader); + } 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/xml/ValidationParser.java URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java?rev=1517540&view=auto ============================================================================== --- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java (added) +++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java Mon Aug 26 13:59:15 2013 @@ -0,0 +1,412 @@ +/* + * 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 org.apache.bval.cdi.BValExtension; +import org.apache.bval.jsr.BootstrapConfigurationImpl; +import org.apache.bval.jsr.ConfigurationImpl; +import org.apache.bval.jsr.util.IOs; +import org.apache.bval.util.reflection.Reflection; +import org.xml.sax.SAXException; + +import javax.validation.ConstraintValidatorFactory; +import javax.validation.MessageInterpolator; +import javax.validation.ParameterNameProvider; +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 java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Description: uses jaxb to parse validation.xml
+ */ +@SuppressWarnings("restriction") +public class ValidationParser implements Closeable { + 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 SCHEMA_CACHE = new ConcurrentHashMap(1); + + private ValidationConfigType xmlConfig; + private BootstrapConfigurationImpl bootstrap; + private Collection exceptions = new CopyOnWriteArrayList(); + private Collection releasables = new CopyOnWriteArrayList(); + + 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; + } + + public static String getValidationXmlFile(String file) { + if (file == null) { + return DEFAULT_VALIDATION_XML_FILE; + } + return file; + } + + 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.getExecutableValidation() == null) { + final ExecutableValidationType value = new ExecutableValidationType(); + value.setEnabled(true); + + final DefaultValidatedExecutableTypesType defaultValidatedExecutableTypes = new DefaultValidatedExecutableTypesType(); + value.setDefaultValidatedExecutableTypes(defaultValidatedExecutableTypes); + defaultValidatedExecutableTypes.getExecutableType().add(ExecutableType.CONSTRUCTORS); + defaultValidatedExecutableTypes.getExecutableType().add(ExecutableType.NON_GETTER_METHODS); + + parser.xmlConfig.setExecutableValidation(value); + } + + 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(parser.xmlConfig.getConstraintMapping()), + parser.xmlConfig.getExecutableValidation().getEnabled(), + new CopyOnWriteArraySet(targetConfig.getExecutableValidation()), + toMap(parser.xmlConfig.getProperty())); + return parser; + } else { // default config + final CopyOnWriteArraySet executableTypes = new CopyOnWriteArraySet(); + executableTypes.add(ExecutableType.CONSTRUCTORS); + executableTypes.add(ExecutableType.NON_GETTER_METHODS); + + parser.bootstrap = new BootstrapConfigurationImpl( + null, null, null, null, null, + new CopyOnWriteArraySet(), + true, + executableTypes, + new HashMap()); + + targetConfig.setExecutableValidation(executableTypes); + } + + return parser; + } + + private static Map toMap(final List property) { + final Map map = new HashMap(); + if (property != null) { + for (final PropertyType p : property) { + map.put(p.getName(), p.getValue()); + } + } + return map; + } + + private static ValidationConfigType parseXmlConfig(final String validationXmlFile) { + InputStream inputStream = null; + try { + inputStream = getInputStream(getValidationXmlFile(validationXmlFile)); + if (inputStream == null) { + 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 root = + unmarshaller.unmarshal(stream, ValidationConfigType.class); + return root.getValue(); + } catch (JAXBException e) { + throw new ValidationException("Unable to parse " + validationXmlFile, e); + } catch (IOException 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.INSTANCE.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 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.INSTANCE.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; + } + } + + public static void applySimpleConfig(ValidationConfigType xmlConfig, ConfigurationImpl targetConfig) { + applyExecutableValidation(xmlConfig, targetConfig); + } + + private static void applyProperties(ValidationConfigType xmlConfig, ConfigurationImpl target) { + for (final PropertyType property : xmlConfig.getProperty()) { + target.addProperty(property.getName(), property.getValue()); + } + } + + private static void applyExecutableValidation(final ValidationConfigType xmlConfig, final ConfigurationImpl targetConfig) { + final CopyOnWriteArrayList executableTypes = new CopyOnWriteArrayList(); + if (xmlConfig.getExecutableValidation() != null && xmlConfig.getExecutableValidation().getEnabled() + && xmlConfig.getExecutableValidation().getDefaultValidatedExecutableTypes() != null) { + executableTypes.addAll(xmlConfig.getExecutableValidation().getDefaultValidatedExecutableTypes().getExecutableType()); + } + + 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 + executableTypes.clear(); + } + + targetConfig.setExecutableValidation(executableTypes); + } + + 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 clazz = Class.class.cast(loadClass(parameterNameProvider)); + targetConfig.parameterNameProvider(newInstance(clazz)); + log.log(Level.INFO, String.format("Using %s as validation provider.", parameterNameProvider)); + } + } + } + + @SuppressWarnings("unchecked") + private void applyProviderClass(ValidationConfigType xmlConfig, ConfigurationImpl target) { + String providerClassName = xmlConfig.getDefaultProvider(); + if (providerClassName != null) { + Class> clazz = + (Class>) loadClass(providerClassName); + target.setProviderClass(clazz); + log.log(Level.INFO, String.format("Using %s as validation provider.", providerClassName)); + } + } + + @SuppressWarnings("unchecked") + private void applyMessageInterpolator(ValidationConfigType xmlConfig, + ConfigurationImpl target) { + String messageInterpolatorClass = xmlConfig.getMessageInterpolator(); + if (target.getMessageInterpolator() == target.getDefaultMessageInterpolator()) { // ref == + if (messageInterpolatorClass != null) { + Class clazz = (Class) + loadClass(messageInterpolatorClass); + target.messageInterpolator(newInstance(clazz)); + log.log(Level.INFO, String.format("Using %s as message interpolator.", messageInterpolatorClass)); + } + } + } + + @SuppressWarnings("unchecked") + private void applyTraversableResolver(ValidationConfigType xmlConfig, + ConfigurationImpl target) { + String traversableResolverClass = xmlConfig.getTraversableResolver(); + if (target.getTraversableResolver() == target.getDefaultTraversableResolver()) { // ref == + if (traversableResolverClass != null) { + Class clazz = (Class) + loadClass(traversableResolverClass); + target.traversableResolver(newInstance(clazz)); + log.log(Level.INFO, String.format("Using %s as traversable resolver.", traversableResolverClass)); + } + } + } + + private T newInstance(final Class cls) { + if (System.getSecurityManager() == null) { + return doNewInstance(cls); + } + return AccessController.doPrivileged(new PrivilegedAction() { + public T run() { + return doNewInstance(cls); + } + }); + } + + private T doNewInstance(final Class cls) { + try { + try { + final BValExtension.Releasable releasable = BValExtension.inject(cls); + releasables.add(releasable); + return releasable.getInstance(); + } catch (final Exception e) { + return cls.newInstance(); + } catch (final NoClassDefFoundError error) { + return cls.newInstance(); + } + } catch (final Exception ex) { + exceptions.add(new ValidationException("Cannot instantiate : " + cls, ex)); + return null; // ensure BootstrapConfiguration can be read even if class can't be instantiated + } + } + + @SuppressWarnings("unchecked") + private void applyConstraintFactory(ValidationConfigType xmlConfig, + ConfigurationImpl target) { + String constraintFactoryClass = xmlConfig.getConstraintValidatorFactory(); + if (target.getConstraintValidatorFactory() == target.getDefaultConstraintValidatorFactory()) { // ref == + if (constraintFactoryClass != null) { + Class clazz = (Class) + loadClass(constraintFactoryClass); + target.constraintValidatorFactory(newInstance(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); + } + } + + private Class loadClass(final String className) { + final ClassLoader loader = Reflection.INSTANCE.getClassLoader(ValidationParser.class); + try { + return Class.forName(className, true, loader); + } catch (final ClassNotFoundException ex) { + // TCK check BootstrapConfig is present in all cases + // so throw next exception later + exceptions.add(new ValidationException("Unable to load class: " + className, ex)); + return null; + } + } + + public void ensureValidatorFactoryCanBeBuilt() { + if (!exceptions.isEmpty()) { + throw exceptions.iterator().next(); + } + } + + public void close() throws IOException { + for (final BValExtension.Releasable releasable : releasables) { + releasable.release(); + } + releasables.clear(); + } +} Added: bval/branches/bval-11/bval-jsr/src/main/resources/META-INF/beans.xml URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/resources/META-INF/beans.xml?rev=1517540&view=auto ============================================================================== --- bval/branches/bval-11/bval-jsr/src/main/resources/META-INF/beans.xml (added) +++ bval/branches/bval-11/bval-jsr/src/main/resources/META-INF/beans.xml Mon Aug 26 13:59:15 2013 @@ -0,0 +1,17 @@ + + + Added: bval/branches/bval-11/bval-jsr/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension?rev=1517540&view=auto ============================================================================== --- bval/branches/bval-11/bval-jsr/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension (added) +++ bval/branches/bval-11/bval-jsr/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension Mon Aug 26 13:59:15 2013 @@ -0,0 +1 @@ +org.apache.bval.cdi.BValExtension \ No newline at end of file Added: bval/branches/bval-11/bval-jsr/src/main/resources/META-INF/services/javax.validation.spi.ValidationProvider URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/resources/META-INF/services/javax.validation.spi.ValidationProvider?rev=1517540&view=auto ============================================================================== --- bval/branches/bval-11/bval-jsr/src/main/resources/META-INF/services/javax.validation.spi.ValidationProvider (added) +++ bval/branches/bval-11/bval-jsr/src/main/resources/META-INF/services/javax.validation.spi.ValidationProvider Mon Aug 26 13:59:15 2013 @@ -0,0 +1,17 @@ +# 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. +org.apache.bval.jsr.ApacheValidationProvider Added: bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/DefaultConstraints.properties URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/DefaultConstraints.properties?rev=1517540&view=auto ============================================================================== --- bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/DefaultConstraints.properties (added) +++ bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/DefaultConstraints.properties Mon Aug 26 13:59:15 2013 @@ -0,0 +1,53 @@ +# 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. + +# configuration for mapping of javax.validation.constraints to ConstraintValidator implementations +# the annotations from the JSR303 validation-api are mentioned here, but you could +# also extend the configuration to get a default implementation for other constraint-annotations. +# format: key=constraint-annotation-class value=constraint-validator-class (multiple classes: comma-separated) + +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.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.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.Size=org.apache.bval.constraints.SizeValidatorForCharSequence,\ + org.apache.bval.constraints.SizeValidatorForMap,\ + org.apache.bval.constraints.SizeValidatorForCollection,\ + org.apache.bval.constraints.SizeValidatorForArrayOfBoolean,\ + org.apache.bval.constraints.SizeValidatorForArrayOfByte,\ + org.apache.bval.constraints.SizeValidatorForArrayOfChar,\ + org.apache.bval.constraints.SizeValidatorForArrayOfDouble,\ + org.apache.bval.constraints.SizeValidatorForArrayOfFloat,\ + org.apache.bval.constraints.SizeValidatorForArrayOfInt,\ + org.apache.bval.constraints.SizeValidatorForArrayOfLong,\ + org.apache.bval.constraints.SizeValidatorForArrayOfObject,\ + org.apache.bval.constraints.SizeValidatorForArrayOfShort +javax.validation.constraints.Pattern=org.apache.bval.constraints.PatternValidator Added: bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages.properties URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages.properties?rev=1517540&view=auto ============================================================================== --- bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages.properties (added) +++ bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages.properties Mon Aug 26 13:59:15 2013 @@ -0,0 +1,37 @@ +# 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. + +# The properties listed below are resolved by the default message resolver. + +# standard +javax.validation.constraints.Null.message=must be null +javax.validation.constraints.NotNull.message=may not be null +javax.validation.constraints.AssertTrue.message=must be true +javax.validation.constraints.AssertFalse.message=must be false +javax.validation.constraints.Min.message=must be greater than or equal to {value} +javax.validation.constraints.Max.message=must be less than or equal to {value} +javax.validation.constraints.Size.message=size must be between {min} and {max} +javax.validation.constraints.Digits.message=numeric value out of bounds (<{integer} digits>.<{fraction} digits> expected) +javax.validation.constraints.Past.message=must be a past date +javax.validation.constraints.Future.message=must be a future date +javax.validation.constraints.Pattern.message=must match the following regular expression: {regexp} +javax.validation.constraints.DecimalMax.message=must be less than or equal to {value} +javax.validation.constraints.DecimalMin.message=must be greater than or equal to {value} + +# additional built-ins +org.apache.bval.constraints.NotEmpty.message=may not be empty +org.apache.bval.constraints.Email.message=not a well-formed email address Added: bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages_de.properties URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages_de.properties?rev=1517540&view=auto ============================================================================== --- bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages_de.properties (added) +++ bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages_de.properties Mon Aug 26 13:59:15 2013 @@ -0,0 +1,37 @@ +# 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. + +# The properties listed below are resolved by the default message resolver. + +# standard +javax.validation.constraints.Null.message=muss "null" sein +javax.validation.constraints.NotNull.message=darf nicht "null" sein +javax.validation.constraints.AssertTrue.message=muss "true" sein +javax.validation.constraints.AssertFalse.message=muss "false" sein +javax.validation.constraints.Min.message=muss gr\u00F6\u00DFer oder gleich {value} sein +javax.validation.constraints.Max.message=muss kleiner oder gleich {value} sein +javax.validation.constraints.Size.message=Gr\u00F6\u00DFe muss zwischen {min} und {max} liegen +javax.validation.constraints.Digits.message=numerischer Wert au\u00DFerhalb des G\u00FCltigkeitsbereiches (erwarte: <{integer} digits>.<{fraction} digits>) +javax.validation.constraints.Past.message=muss Datum in der Vergangenheit sein +javax.validation.constraints.Future.message=muss Datum in der Zukunft sein +javax.validation.constraints.Pattern.message=Muss mit regul\u00E4rem Ausdruck \u00FCbereinstimmen: {regexp} +javax.validation.constraints.DecimalMax.message=muss kleiner oder gleich {value} sein +javax.validation.constraints.DecimalMin.message=muss gr\u00F6\u00DFer oder gleich {value} sein + +# additional built-ins +org.apache.bval.constraints.NotEmpty.message=darf nicht leer sein +org.apache.bval.constraints.Email.message=muss g\u00FCltiges Format einer EMail-Adresse sein Added: bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages_en.properties URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages_en.properties?rev=1517540&view=auto ============================================================================== --- bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages_en.properties (added) +++ bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages_en.properties Mon Aug 26 13:59:15 2013 @@ -0,0 +1,20 @@ +# 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. + +# intentionally empty, because english messages are located in the default bundle. +# this file ensures, that a lookup with an english locale uses the default bundle and not the +# bundle of the default locale, which is platform specific \ No newline at end of file Added: bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages_es.properties URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages_es.properties?rev=1517540&view=auto ============================================================================== --- bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages_es.properties (added) +++ bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages_es.properties Mon Aug 26 13:59:15 2013 @@ -0,0 +1,37 @@ +# 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. + +# The properties listed below are resolved by the default message resolver. + +# standard +javax.validation.constraints.Null.message=tiene que ser null +javax.validation.constraints.NotNull.message=no puede ser null +javax.validation.constraints.AssertTrue.message=tiene que ser true +javax.validation.constraints.AssertFalse.message=tiene que ser false +javax.validation.constraints.Min.message=tiene que ser menor o igual que {value} +javax.validation.constraints.Max.message=tiene que ser mayor o igual que {value} +javax.validation.constraints.Size.message=el tamaño tiene que estar comprendido entre {min} y {max} +javax.validation.constraints.Digits.message=valor numérico fuera de los límites (se espera <{integer} cifras>.<{fraction} cifras>) +javax.validation.constraints.Past.message=tiene que ser una fecha en el pasado +javax.validation.constraints.Future.message=tiene que ser una fecha en el futuro +javax.validation.constraints.Pattern.message=tiene que corresponder a la expresión regular "{regexp}" +javax.validation.constraints.DecimalMax.message=tiene que ser mayor o igual que {value} +javax.validation.constraints.DecimalMin.message=tiene que ser menor o igual que {value} + +# additional built-ins +org.apache.bval.constraints.NotEmpty.message=no puede ser vacio +org.apache.bval.constraints.Email.message=tiene que ser un correo email bien formado Added: bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages_it.properties URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages_it.properties?rev=1517540&view=auto ============================================================================== --- bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages_it.properties (added) +++ bval/branches/bval-11/bval-jsr/src/main/resources/org/apache/bval/jsr/ValidationMessages_it.properties Mon Aug 26 13:59:15 2013 @@ -0,0 +1,37 @@ +# 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. + +# The properties listed below are resolved by the default message resolver. + +# standard +javax.validation.constraints.Null.message=deve essere null +javax.validation.constraints.NotNull.message=non pu\u00F2 essere null +javax.validation.constraints.AssertTrue.message=deve essere true +javax.validation.constraints.AssertFalse.message=deve essere false +javax.validation.constraints.Min.message=deve essere minore o uguale di {value} +javax.validation.constraints.Max.message=deve essere maggiore o uguale di {value} +javax.validation.constraints.Size.message=le dimensioni devono essere tra {min} e {max} +javax.validation.constraints.Digits.message=valore numerico fuori dai limiti (atteso <{integer} cifre>.<{fraction} cifre>) +javax.validation.constraints.Past.message=deve essere una data nel passato +javax.validation.constraints.Future.message=deve essere una data futura +javax.validation.constraints.Pattern.message=deve corrispondere all'espressione regolare "{regexp}" +javax.validation.constraints.DecimalMax.message=deve essere maggiore o uguale di {value} +javax.validation.constraints.DecimalMin.message=deve essere minore o uguale di {value} + +# additional built-ins +org.apache.bval.constraints.NotEmpty.message=non pu\u00F2 essere vuoto +org.apache.bval.constraints.Email.message=non \u00E8 un indirizzo email ben formato Added: bval/branches/bval-11/bval-jsr/src/main/xjb/binding-customization.xjb URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/xjb/binding-customization.xjb?rev=1517540&view=auto ============================================================================== --- bval/branches/bval-11/bval-jsr/src/main/xjb/binding-customization.xjb (added) +++ bval/branches/bval-11/bval-jsr/src/main/xjb/binding-customization.xjb Mon Aug 26 13:59:15 2013 @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + Added: bval/branches/bval-11/bval-jsr/src/main/xsd/validation-configuration-1.0.xsd URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/xsd/validation-configuration-1.0.xsd?rev=1517540&view=auto ============================================================================== --- bval/branches/bval-11/bval-jsr/src/main/xsd/validation-configuration-1.0.xsd (added) +++ bval/branches/bval-11/bval-jsr/src/main/xsd/validation-configuration-1.0.xsd Mon Aug 26 13:59:15 2013 @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + Added: bval/branches/bval-11/bval-jsr/src/main/xsd/validation-configuration-1.1.xsd URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/xsd/validation-configuration-1.1.xsd?rev=1517540&view=auto ============================================================================== --- bval/branches/bval-11/bval-jsr/src/main/xsd/validation-configuration-1.1.xsd (added) +++ bval/branches/bval-11/bval-jsr/src/main/xsd/validation-configuration-1.1.xsd Mon Aug 26 13:59:15 2013 @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +