http://git-wip-us.apache.org/repos/asf/bval/blob/5c09f0dd/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java b/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java index 7b9b14f..bed2e10 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/xml/ValidationParser.java @@ -22,12 +22,14 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Collection; -import java.util.Enumeration; +import java.util.Collections; +import java.util.EnumSet; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; +import java.util.Optional; +import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; import java.util.logging.Level; @@ -40,59 +42,34 @@ import javax.validation.TraversableResolver; import javax.validation.ValidationException; import javax.validation.executable.ExecutableType; import javax.validation.spi.ValidationProvider; -import javax.xml.XMLConstants; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; import org.apache.bval.jsr.BootstrapConfigurationImpl; import org.apache.bval.jsr.ConfigurationImpl; -import org.apache.bval.jsr.util.IOs; +import org.apache.bval.jsr.metadata.XmlBuilder; +import org.apache.bval.util.Exceptions; import org.apache.bval.util.reflection.Reflection; import org.apache.commons.weaver.privilizer.Privileged; import org.apache.commons.weaver.privilizer.Privilizing; import org.apache.commons.weaver.privilizer.Privilizing.CallTo; -import org.xml.sax.SAXException; +import org.xml.sax.InputSource; /** * Description: uses jaxb to parse validation.xml<br/> */ @Privilizing(@CallTo(Reflection.class)) public class ValidationParser { + private static final String DEFAULT_VALIDATION_XML_FILE = "META-INF/validation.xml"; - private static final String VALIDATION_CONFIGURATION_XSD = "META-INF/validation-configuration-1.1.xsd"; private static final Logger log = Logger.getLogger(ValidationParser.class.getName()); - private static final ConcurrentMap<String, Schema> SCHEMA_CACHE = new ConcurrentHashMap<String, Schema>(1); - - private ValidationConfigType xmlConfig; - private BootstrapConfigurationImpl bootstrap; - private Collection<ValidationException> exceptions = new CopyOnWriteArrayList<ValidationException>(); - - private ValidationParser() { - // no-op - } - public void applyConfigWithInstantiation(ConfigurationImpl targetConfig) { - if (xmlConfig == null) { - return; - } - - applyProviderClass(xmlConfig, targetConfig); - applyMessageInterpolator(xmlConfig, targetConfig); - applyTraversableResolver(xmlConfig, targetConfig); - applyConstraintFactory(xmlConfig, targetConfig); - applyParameterNameProvider(xmlConfig, targetConfig); - applyMappingStreams(xmlConfig, targetConfig); - applyProperties(xmlConfig, targetConfig); - } - - public BootstrapConfigurationImpl getBootstrap() { - return bootstrap; - } + private static final SchemaManager SCHEMA_MANAGER = new SchemaManager.Builder() + .add(null, "http://jboss.org/xml/ns/javax/validation/configuration", + "META-INF/validation-configuration-1.0.xsd") + .add(XmlBuilder.Version.v11.getId(), "http://jboss.org/xml/ns/javax/validation/configuration", + "META-INF/validation-configuration-1.1.xsd") + .add(XmlBuilder.Version.v20.getId(), "http://xmlns.jcp.org/xml/ns/javax/validation/configuration", + "META-INF/validation-configuration-2.0.xsd") + .build(); public static String getValidationXmlFile(String file) { if (file == null) { @@ -101,19 +78,30 @@ public class ValidationParser { return file; } - public static ValidationParser processValidationConfig(final String file, final ConfigurationImpl targetConfig, final boolean ignoreXml) { + public static ValidationParser processValidationConfig(final String file, final ConfigurationImpl targetConfig, + final boolean ignoreXml) { final ValidationParser parser = new ValidationParser(); if (!ignoreXml) { parser.xmlConfig = parseXmlConfig(file); } - if (parser.xmlConfig != null) { + if (parser.xmlConfig == null) { // default config + final CopyOnWriteArraySet<ExecutableType> executableTypes = new CopyOnWriteArraySet<>(); + executableTypes.add(ExecutableType.CONSTRUCTORS); + executableTypes.add(ExecutableType.NON_GETTER_METHODS); + + parser.bootstrap = new BootstrapConfigurationImpl(null, null, null, null, null, Collections.emptySet(), + true, executableTypes, Collections.emptyMap(), null, Collections.emptySet()); + + targetConfig.setExecutableValidation(executableTypes); + } else { if (parser.xmlConfig.getExecutableValidation() == null) { final ExecutableValidationType value = new ExecutableValidationType(); value.setEnabled(true); - final DefaultValidatedExecutableTypesType defaultValidatedExecutableTypes = new DefaultValidatedExecutableTypesType(); + final DefaultValidatedExecutableTypesType defaultValidatedExecutableTypes = + new DefaultValidatedExecutableTypesType(); value.setDefaultValidatedExecutableTypes(defaultValidatedExecutableTypes); defaultValidatedExecutableTypes.getExecutableType().add(ExecutableType.CONSTRUCTORS); defaultValidatedExecutableTypes.getExecutableType().add(ExecutableType.NON_GETTER_METHODS); @@ -123,35 +111,19 @@ public class ValidationParser { applySimpleConfig(parser.xmlConfig, targetConfig); - parser.bootstrap = new BootstrapConfigurationImpl( - parser.xmlConfig.getDefaultProvider(), - parser.xmlConfig.getConstraintValidatorFactory(), - parser.xmlConfig.getMessageInterpolator(), - parser.xmlConfig.getTraversableResolver(), - parser.xmlConfig.getParameterNameProvider(), - new CopyOnWriteArraySet<String>(parser.xmlConfig.getConstraintMapping()), - parser.xmlConfig.getExecutableValidation().getEnabled(), - new CopyOnWriteArraySet<ExecutableType>(targetConfig.getExecutableValidation()), - toMap(parser.xmlConfig.getProperty())); - } else { // default config - final CopyOnWriteArraySet<ExecutableType> executableTypes = new CopyOnWriteArraySet<ExecutableType>(); - executableTypes.add(ExecutableType.CONSTRUCTORS); - executableTypes.add(ExecutableType.NON_GETTER_METHODS); - - parser.bootstrap = new BootstrapConfigurationImpl( - null, null, null, null, null, - new CopyOnWriteArraySet<String>(), - true, - executableTypes, - new HashMap<String, String>()); - - targetConfig.setExecutableValidation(executableTypes); + parser.bootstrap = new BootstrapConfigurationImpl(parser.xmlConfig.getDefaultProvider(), + parser.xmlConfig.getConstraintValidatorFactory(), parser.xmlConfig.getMessageInterpolator(), + parser.xmlConfig.getTraversableResolver(), parser.xmlConfig.getParameterNameProvider(), + new HashSet<>(parser.xmlConfig.getConstraintMapping()), + parser.xmlConfig.getExecutableValidation().getEnabled(), + new HashSet<>(targetConfig.getExecutableValidation()), toMap(parser.xmlConfig.getProperty()), + parser.xmlConfig.getClockProvider(), new HashSet<>(parser.xmlConfig.getValueExtractor())); } return parser; } private static Map<String, String> toMap(final List<PropertyType> property) { - final Map<String, String> map = new HashMap<String, String>(); + final Map<String, String> map = new HashMap<>(); if (property != null) { for (final PropertyType p : property) { map.put(p.getName(), p.getValue()); @@ -162,78 +134,26 @@ public class ValidationParser { @Privileged private static ValidationConfigType parseXmlConfig(final String validationXmlFile) { - InputStream inputStream = null; - try { - inputStream = getInputStream(getValidationXmlFile(validationXmlFile)); + try (InputStream inputStream = getInputStream(getValidationXmlFile(validationXmlFile))) { if (inputStream == null) { - log.log(Level.FINEST, String.format("No %s found. Using annotation based configuration only.", validationXmlFile)); + log.log(Level.FINEST, + String.format("No %s found. Using annotation based configuration only.", validationXmlFile)); return null; } - log.log(Level.FINEST, String.format("%s found.", validationXmlFile)); - Schema schema = getSchema(); - JAXBContext jc = JAXBContext.newInstance(ValidationConfigType.class); - Unmarshaller unmarshaller = jc.createUnmarshaller(); - unmarshaller.setSchema(schema); - StreamSource stream = new StreamSource(inputStream); - JAXBElement<ValidationConfigType> root = - unmarshaller.unmarshal(stream, ValidationConfigType.class); - return root.getValue(); - } catch (JAXBException e) { - throw new ValidationException("Unable to parse " + validationXmlFile, e); - } catch (IOException e) { + return SCHEMA_MANAGER.unmarshal(new InputSource(inputStream), ValidationConfigType.class); + } catch (Exception e) { throw new ValidationException("Unable to parse " + validationXmlFile, e); - } finally { - IOs.closeQuietly(inputStream); } } protected static InputStream getInputStream(final String path) throws IOException { final ClassLoader loader = Reflection.getClassLoader(ValidationParser.class); - final InputStream inputStream = loader.getResourceAsStream(path); - - if (inputStream != null) { - // spec says: If more than one META-INF/validation.xml file - // is found in the classpath, a ValidationException is raised. - final Enumeration<URL> urls = loader.getResources(path); - if (urls.hasMoreElements()) { - final String url = urls.nextElement().toString(); - while (urls.hasMoreElements()) { - if (!url.equals(urls.nextElement().toString())) { // complain when first duplicate found - throw new ValidationException("More than one " + path + " is found in the classpath"); - } - } - } - } - - return IOs.convertToMarkableInputStream(inputStream); - } - - private static Schema getSchema() { - return getSchema(VALIDATION_CONFIGURATION_XSD); - } - - static Schema getSchema(final String xsd) { - final Schema schema = SCHEMA_CACHE.get(xsd); - if (schema != null) { - return schema; - } - - final ClassLoader loader = Reflection.getClassLoader(ValidationParser.class); - final SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); - final URL schemaUrl = loader.getResource(xsd); - try { - Schema s = sf.newSchema(schemaUrl); - final Schema old = SCHEMA_CACHE.putIfAbsent(xsd, s); - if (old != null) { - s = old; - } - return s; - } catch (SAXException e) { - log.log(Level.WARNING, String.format("Unable to parse schema: %s", xsd), e); - return null; - } + final List<URL> urls = Collections.list(loader.getResources(path)); + Exceptions.raiseIf(urls.stream().distinct().count() > 1, ValidationException::new, + "More than one %s is found in the classpath", path); + return urls.isEmpty() ? null : urls.get(0).openStream(); } public static void applySimpleConfig(ValidationConfigType xmlConfig, ConfigurationImpl targetConfig) { @@ -246,37 +166,84 @@ public class ValidationParser { } } - private static void applyExecutableValidation(final ValidationConfigType xmlConfig, final ConfigurationImpl targetConfig) { - final CopyOnWriteArrayList<ExecutableType> executableTypes = new CopyOnWriteArrayList<ExecutableType>(); - if (xmlConfig.getExecutableValidation() != null && xmlConfig.getExecutableValidation().getEnabled() - && xmlConfig.getExecutableValidation().getDefaultValidatedExecutableTypes() != null) { - executableTypes.addAll(xmlConfig.getExecutableValidation().getDefaultValidatedExecutableTypes().getExecutableType()); - } + private static void applyExecutableValidation(final ValidationConfigType xmlConfig, + final ConfigurationImpl targetConfig) { + + final Set<ExecutableType> executableTypes = Optional.of(xmlConfig) + .map(ValidationConfigType::getExecutableValidation).filter(vc -> Boolean.TRUE.equals(vc.getEnabled())) + .map(ExecutableValidationType::getDefaultValidatedExecutableTypes) + .map(DefaultValidatedExecutableTypesType::getExecutableType).map(EnumSet::copyOf) + .orElseGet(() -> EnumSet.noneOf(ExecutableType.class)); if (executableTypes.contains(ExecutableType.ALL)) { executableTypes.clear(); executableTypes.add(ExecutableType.CONSTRUCTORS); executableTypes.add(ExecutableType.NON_GETTER_METHODS); executableTypes.add(ExecutableType.GETTER_METHODS); - } else if (executableTypes.contains(ExecutableType.NONE)) { // if both are present ALL gains + } else if (executableTypes.contains(ExecutableType.NONE)) { // if both are present ALL trumps NONE executableTypes.clear(); } + targetConfig.setExecutableValidation(Collections.unmodifiableSet(executableTypes)); + } + + private static void applyMappingStreams(ValidationConfigType xmlConfig, ConfigurationImpl target) { + for (String rawMappingFileName : xmlConfig.getConstraintMapping()) { + String mappingFileName = rawMappingFileName; + if (mappingFileName.charAt(0) == '/') { + // Classloader needs a path without a starting / + mappingFileName = mappingFileName.substring(1); + } + log.log(Level.FINEST, String.format("Trying to open input stream for %s", mappingFileName)); + try { + final InputStream in = getInputStream(mappingFileName); + Exceptions.raiseIf(in == null, ValidationException::new, + "Unable to open input stream for mapping file %s", mappingFileName); + target.addMapping(in); + } catch (IOException e) { + Exceptions.raise(ValidationException::new, e, "Unable to open input stream for mapping file %s", + mappingFileName); + } + } + } + + private ValidationConfigType xmlConfig; + private BootstrapConfigurationImpl bootstrap; + private Collection<ValidationException> exceptions = new CopyOnWriteArrayList<ValidationException>(); + + private ValidationParser() { + // no-op + } + + public void applyConfigWithInstantiation(ConfigurationImpl targetConfig) { + if (xmlConfig == null) { + return; + } - targetConfig.setExecutableValidation(executableTypes); + applyProviderClass(xmlConfig, targetConfig); + applyMessageInterpolator(xmlConfig, targetConfig); + applyTraversableResolver(xmlConfig, targetConfig); + applyConstraintFactory(xmlConfig, targetConfig); + applyParameterNameProvider(xmlConfig, targetConfig); + applyMappingStreams(xmlConfig, targetConfig); + applyProperties(xmlConfig, targetConfig); + } + + public BootstrapConfigurationImpl getBootstrap() { + return bootstrap; } - private void applyParameterNameProvider(final ValidationConfigType xmlConfig, final ConfigurationImpl targetConfig) { + private void applyParameterNameProvider(final ValidationConfigType xmlConfig, + final ConfigurationImpl targetConfig) { final String parameterNameProvider = xmlConfig.getParameterNameProvider(); - if (targetConfig.getParameterNameProvider() == targetConfig.getDefaultParameterNameProvider()) { // ref == - if (parameterNameProvider != null) { - final Class<?> loaded = loadClass(parameterNameProvider); - if (loaded == null) { - log.log(Level.SEVERE, "Can't load " + parameterNameProvider); - } else { - final Class<? extends ParameterNameProvider> clazz = loaded.asSubclass(ParameterNameProvider.class); - targetConfig.parameterNameProviderClass(clazz); - log.log(Level.INFO, String.format("Using %s as validation provider.", parameterNameProvider)); - } + if (targetConfig.getParameterNameProvider() == targetConfig.getDefaultParameterNameProvider() + && parameterNameProvider != null) { + final Class<?> loaded = loadClass(parameterNameProvider); + if (loaded == null) { + log.log(Level.SEVERE, "Can't load " + parameterNameProvider); + } else { + final Class<? extends ParameterNameProvider> clazz = loaded.asSubclass(ParameterNameProvider.class); + targetConfig.parameterNameProviderClass(clazz); + log.log(Level.INFO, String.format("Using %s as validation provider.", parameterNameProvider)); } } } @@ -293,65 +260,36 @@ public class ValidationParser { } @SuppressWarnings("unchecked") - private void applyMessageInterpolator(ValidationConfigType xmlConfig, - ConfigurationImpl target) { + private void applyMessageInterpolator(ValidationConfigType xmlConfig, ConfigurationImpl target) { String messageInterpolatorClass = xmlConfig.getMessageInterpolator(); - if (target.getMessageInterpolator() == target.getDefaultMessageInterpolator()) { // ref == - if (messageInterpolatorClass != null) { - Class<MessageInterpolator> clazz = (Class<MessageInterpolator>) - loadClass(messageInterpolatorClass); - target.messageInterpolatorClass(clazz); - log.log(Level.INFO, String.format("Using %s as message interpolator.", messageInterpolatorClass)); - } + if (target.getMessageInterpolator() == target.getDefaultMessageInterpolator() + && messageInterpolatorClass != null) { + Class<MessageInterpolator> clazz = (Class<MessageInterpolator>) loadClass(messageInterpolatorClass); + target.messageInterpolatorClass(clazz); + log.log(Level.INFO, String.format("Using %s as message interpolator.", messageInterpolatorClass)); } } @SuppressWarnings("unchecked") - private void applyTraversableResolver(ValidationConfigType xmlConfig, - ConfigurationImpl target) { + private void applyTraversableResolver(ValidationConfigType xmlConfig, ConfigurationImpl target) { String traversableResolverClass = xmlConfig.getTraversableResolver(); - if (target.getTraversableResolver() == target.getDefaultTraversableResolver() && traversableResolverClass != null) { - Class<TraversableResolver> clazz = (Class<TraversableResolver>) - loadClass(traversableResolverClass); - target.traversableResolverClass(clazz); - log.log(Level.INFO, String.format("Using %s as traversable resolver.", traversableResolverClass)); - } + if (target.getTraversableResolver() == target.getDefaultTraversableResolver() + && traversableResolverClass != null) { + Class<TraversableResolver> clazz = (Class<TraversableResolver>) loadClass(traversableResolverClass); + target.traversableResolverClass(clazz); + log.log(Level.INFO, String.format("Using %s as traversable resolver.", traversableResolverClass)); + } } @SuppressWarnings("unchecked") - private void applyConstraintFactory(ValidationConfigType xmlConfig, - ConfigurationImpl target) { + private void applyConstraintFactory(ValidationConfigType xmlConfig, ConfigurationImpl target) { String constraintFactoryClass = xmlConfig.getConstraintValidatorFactory(); - if (target.getConstraintValidatorFactory() == target.getDefaultConstraintValidatorFactory() && constraintFactoryClass != null) { - Class<ConstraintValidatorFactory> clazz = (Class<ConstraintValidatorFactory>) - loadClass(constraintFactoryClass); - target.constraintValidatorFactoryClass(clazz); - log.log(Level.INFO, String.format("Using %s as constraint factory.", constraintFactoryClass)); - } - } - - private static void applyMappingStreams(ValidationConfigType xmlConfig, - ConfigurationImpl target) { - for (String rawMappingFileName : xmlConfig.getConstraintMapping()) { - String mappingFileName = rawMappingFileName; - if (mappingFileName.startsWith("/")) { - // Classloader needs a path without a starting / - mappingFileName = mappingFileName.substring(1); - } - log.log(Level.FINEST, String.format("Trying to open input stream for %s", mappingFileName)); - InputStream in; - try { - in = getInputStream(mappingFileName); - if (in == null) { - throw new ValidationException( - "Unable to open input stream for mapping file " + - mappingFileName); - } - } catch (IOException e) { - throw new ValidationException("Unable to open input stream for mapping file " + - mappingFileName, e); - } - target.addMapping(in); + if (target.getConstraintValidatorFactory() == target.getDefaultConstraintValidatorFactory() + && constraintFactoryClass != null) { + Class<ConstraintValidatorFactory> clazz = + (Class<ConstraintValidatorFactory>) loadClass(constraintFactoryClass); + target.constraintValidatorFactoryClass(clazz); + log.log(Level.INFO, String.format("Using %s as constraint factory.", constraintFactoryClass)); } }
http://git-wip-us.apache.org/repos/asf/bval/blob/5c09f0dd/bval-jsr/src/main/java/org/apache/bval/jsr/xml/XmlUtils.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/xml/XmlUtils.java b/bval-jsr/src/main/java/org/apache/bval/jsr/xml/XmlUtils.java new file mode 100644 index 0000000..2826174 --- /dev/null +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/xml/XmlUtils.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.bval.jsr.xml; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.xml.XMLConstants; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.helpers.DefaultValidationEventHandler; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import org.apache.bval.util.reflection.Reflection; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +class XmlUtils { + private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY = DocumentBuilderFactory.newInstance(); + private static final Logger log = Logger.getLogger(XmlUtils.class.getName()); + private static final SchemaFactory SCHEMA_FACTORY = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + + static Schema loadSchema(String resource) { + final URL schemaUrl = Reflection.getClassLoader(XmlUtils.class).getResource(resource); + try { + return SCHEMA_FACTORY.newSchema(schemaUrl); + } catch (SAXException e) { + log.log(Level.WARNING, String.format("Unable to parse schema: %s", resource), e); + return null; + } + } + + static Document parse(InputStream in) throws SAXException, IOException, ParserConfigurationException { + return DOCUMENT_BUILDER_FACTORY.newDocumentBuilder().parse(in); + } + + static <T> T unmarshal(Document document, Schema schema, Class<T> type) throws JAXBException { + final JAXBContext jc = JAXBContext.newInstance(type); + final Unmarshaller unmarshaller = jc.createUnmarshaller(); + unmarshaller.setSchema(schema); + unmarshaller.setEventHandler(new DefaultValidationEventHandler()); + final JAXBElement<T> root = unmarshaller.unmarshal(document, type); + return root.getValue(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/bval/blob/5c09f0dd/bval-jsr/src/main/xjb/binding-customization.xjb ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/xjb/binding-customization.xjb b/bval-jsr/src/main/xjb/binding-customization.xjb index 598bd3c..762a058 100644 --- a/bval-jsr/src/main/xjb/binding-customization.xjb +++ b/bval-jsr/src/main/xjb/binding-customization.xjb @@ -19,7 +19,7 @@ --> <jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"> - <jxb:bindings schemaLocation="../xsd/validation-mapping-1.1.xsd" node="/xs:schema"> + <jxb:bindings schemaLocation="../xsd/validation-mapping-2.0.xsd" node="/xs:schema"> <jxb:globalBindings> <xjc:javaType name="java.lang.String" xmlType="xs:string" adapter="javax.xml.bind.annotation.adapters.CollapsedStringAdapter"/> @@ -29,7 +29,7 @@ <jxb:property name="classType"/> </jxb:bindings> </jxb:bindings> - <jxb:bindings schemaLocation="../xsd/validation-configuration-1.1.xsd" node="/xs:schema"> + <jxb:bindings schemaLocation="../xsd/validation-configuration-2.0.xsd" node="/xs:schema"> <jxb:bindings node="//xs:element[@name='executable-type']"> <jxb:javaType name="javax.validation.executable.ExecutableType" parseMethod="javax.validation.executable.ExecutableType.valueOf"/> http://git-wip-us.apache.org/repos/asf/bval/blob/5c09f0dd/bval-jsr/src/main/xsd/validation-configuration-2.0.xsd ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/xsd/validation-configuration-2.0.xsd b/bval-jsr/src/main/xsd/validation-configuration-2.0.xsd new file mode 100644 index 0000000..6fd7874 --- /dev/null +++ b/bval-jsr/src/main/xsd/validation-configuration-2.0.xsd @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<xs:schema attributeFormDefault="unqualified" + elementFormDefault="qualified" + targetNamespace="http://xmlns.jcp.org/xml/ns/javax/validation/configuration" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + xmlns:config="http://xmlns.jcp.org/xml/ns/javax/validation/configuration" + version="2.0"> + <xs:element name="validation-config" type="config:validation-configType" /> + <xs:complexType name="validation-configType"> + <xs:sequence> + <xs:element type="xs:string" name="default-provider" minOccurs="0" /> + <xs:element type="xs:string" name="message-interpolator" minOccurs="0" /> + <xs:element type="xs:string" name="traversable-resolver" minOccurs="0" /> + <xs:element type="xs:string" name="constraint-validator-factory" minOccurs="0" /> + <xs:element type="xs:string" name="parameter-name-provider" minOccurs="0" /> + <xs:element type="xs:string" name="clock-provider" minOccurs="0" /> + <xs:element type="xs:string" name="value-extractor" maxOccurs="unbounded" minOccurs="0" /> + <xs:element type="config:executable-validationType" name="executable-validation" minOccurs="0" /> + <xs:element type="xs:string" name="constraint-mapping" maxOccurs="unbounded" minOccurs="0" /> + <xs:element type="config:propertyType" name="property" maxOccurs="unbounded" minOccurs="0" /> + </xs:sequence> + <xs:attribute name="version" type="config:versionType" fixed="2.0" /> <!-- use="required" --> + </xs:complexType> + <xs:complexType name="executable-validationType"> + <xs:sequence> + <xs:element type="config:default-validated-executable-typesType" name="default-validated-executable-types" minOccurs="0" /> + </xs:sequence> + <xs:attribute name="enabled" use="optional" type="xs:boolean" default="true" /> + </xs:complexType> + <xs:complexType name="default-validated-executable-typesType"> + <xs:sequence> + <xs:element name="executable-type" maxOccurs="unbounded" minOccurs="1"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:enumeration value="NONE" /> + <xs:enumeration value="CONSTRUCTORS" /> + <xs:enumeration value="NON_GETTER_METHODS" /> + <xs:enumeration value="GETTER_METHODS" /> + <xs:enumeration value="ALL" /> + </xs:restriction> + </xs:simpleType> + </xs:element> + </xs:sequence> + </xs:complexType> + <xs:complexType name="propertyType"> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute name="name" use="required" type="xs:string" /> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + <xs:simpleType name="versionType"> + <xs:restriction base="xs:token"> + <xs:pattern value="[0-9]+(\.[0-9]+)*" /> + </xs:restriction> + </xs:simpleType> +</xs:schema> http://git-wip-us.apache.org/repos/asf/bval/blob/5c09f0dd/bval-jsr/src/main/xsd/validation-mapping-2.0.xsd ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/xsd/validation-mapping-2.0.xsd b/bval-jsr/src/main/xsd/validation-mapping-2.0.xsd new file mode 100644 index 0000000..9d16bf3 --- /dev/null +++ b/bval-jsr/src/main/xsd/validation-mapping-2.0.xsd @@ -0,0 +1,297 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<xs:schema attributeFormDefault="unqualified" + elementFormDefault="qualified" + targetNamespace="http://xmlns.jcp.org/xml/ns/javax/validation/mapping" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + xmlns:map="http://xmlns.jcp.org/xml/ns/javax/validation/mapping" + version="2.0"> + <xs:element name="constraint-mappings" type="map:constraint-mappingsType" /> + + <xs:complexType name="payloadType"> + <xs:sequence> + <xs:element type="xs:string" name="value" maxOccurs="unbounded" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + <xs:complexType name="groupsType"> + <xs:sequence> + <xs:element type="xs:string" name="value" maxOccurs="unbounded" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + <xs:complexType name="groupSequenceType"> + <xs:sequence> + <xs:element type="xs:string" name="value" maxOccurs="unbounded" minOccurs="0" /> + </xs:sequence> + </xs:complexType> + <xs:complexType name="groupConversionType"> + <xs:attribute type="xs:string" name="from" use="required" /> + <xs:attribute type="xs:string" name="to" use="required" /> + </xs:complexType> + <xs:complexType name="constraint-mappingsType"> + <xs:sequence> + <xs:element type="xs:string" name="default-package" minOccurs="0" /> + <xs:element type="map:beanType" + name="bean" + maxOccurs="unbounded" + minOccurs="0" /> + <xs:element type="map:constraint-definitionType" + name="constraint-definition" + maxOccurs="unbounded" + minOccurs="0" /> + </xs:sequence> + <xs:attribute name="version" type="map:versionType" fixed="2.0" /> <!-- use="required" --> + </xs:complexType> + <xs:simpleType name="versionType"> + <xs:restriction base="xs:token"> + <xs:pattern value="[0-9]+(\.[0-9]+)*" /> + </xs:restriction> + </xs:simpleType> + <xs:complexType name="validated-byType"> + <xs:sequence> + <xs:element type="xs:string" name="value" maxOccurs="unbounded" minOccurs="0" /> + </xs:sequence> + <xs:attribute type="xs:boolean" name="include-existing-validators" use="optional" /> + </xs:complexType> + <xs:complexType name="constraintType"> + <xs:sequence> + <xs:element type="xs:string" name="message" minOccurs="0" /> + <xs:element type="map:groupsType" + name="groups" + minOccurs="0" /> + <xs:element type="map:payloadType" + name="payload" + minOccurs="0" /> + <xs:element type="map:elementType" + name="element" + maxOccurs="unbounded" + minOccurs="0" /> + </xs:sequence> + <xs:attribute type="xs:string" name="annotation" use="required" /> + </xs:complexType> + <xs:complexType name="elementType" mixed="true"> + <xs:sequence> + <xs:element type="xs:string" name="value" maxOccurs="unbounded" minOccurs="0" /> + <xs:element type="map:annotationType" + name="annotation" + maxOccurs="unbounded" + minOccurs="0" /> + </xs:sequence> + <xs:attribute type="xs:string" name="name" use="required" /> + </xs:complexType> + <xs:complexType name="containerElementTypeType"> + <xs:sequence> + <xs:element type="xs:string" + name="valid" + minOccurs="0" + fixed="" /> + <xs:element type="map:groupConversionType" + name="convert-group" + minOccurs="0" + maxOccurs="unbounded" /> + <xs:element type="map:containerElementTypeType" + name="container-element-type" + minOccurs="0" + maxOccurs="unbounded" /> + <xs:element type="map:constraintType" + name="constraint" + minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + <xs:attribute name="type-argument-index" use="optional"> + <xs:simpleType> + <xs:restriction base="xs:int"> + <xs:minInclusive value="0" /> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + </xs:complexType> + <xs:complexType name="classType"> + <xs:sequence> + <xs:element type="map:groupSequenceType" + name="group-sequence" + minOccurs="0" /> + <xs:element type="map:constraintType" + name="constraint" + maxOccurs="unbounded" + minOccurs="0" /> + </xs:sequence> + <xs:attribute type="xs:boolean" name="ignore-annotations" use="optional" /> + </xs:complexType> + <xs:complexType name="beanType"> + <xs:sequence> + <xs:element type="map:classType" + name="class" + minOccurs="0"> + </xs:element> + <xs:element type="map:fieldType" + name="field" + minOccurs="0" + maxOccurs="unbounded" /> + <xs:element type="map:getterType" + name="getter" + minOccurs="0" + maxOccurs="unbounded" /> + <xs:element type="map:constructorType" + name="constructor" + minOccurs="0" + maxOccurs="unbounded" /> + <xs:element type="map:methodType" + name="method" + minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + <xs:attribute type="xs:string" name="class" use="required" /> + <xs:attribute type="xs:boolean" name="ignore-annotations" use="optional" default="true" /> + </xs:complexType> + <xs:complexType name="annotationType"> + <xs:sequence> + <xs:element type="map:elementType" + name="element" + maxOccurs="unbounded" + minOccurs="0" /> + </xs:sequence> + </xs:complexType> + <xs:complexType name="getterType"> + <xs:sequence> + <xs:element type="xs:string" name="valid" minOccurs="0" fixed="" /> + <xs:element type="map:groupConversionType" + name="convert-group" + minOccurs="0" + maxOccurs="unbounded" /> + <xs:element type="map:containerElementTypeType" + name="container-element-type" + minOccurs="0" + maxOccurs="unbounded" /> + <xs:element type="map:constraintType" + name="constraint" + minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + <xs:attribute type="xs:string" name="name" use="required" /> + <xs:attribute type="xs:boolean" name="ignore-annotations" use="optional" /> + </xs:complexType> + <xs:complexType name="methodType"> + <xs:sequence> + <xs:element type="map:parameterType" + name="parameter" + minOccurs="0" + maxOccurs="unbounded" /> + <xs:element type="map:crossParameterType" + name="cross-parameter" + minOccurs="0" + maxOccurs="1" /> + <xs:element type="map:returnValueType" + name="return-value" + minOccurs="0" + maxOccurs="1" /> + </xs:sequence> + <xs:attribute type="xs:string" name="name" use="required" /> + <xs:attribute type="xs:boolean" name="ignore-annotations" use="optional" /> + </xs:complexType> + <xs:complexType name="constructorType"> + <xs:sequence> + <xs:element type="map:parameterType" + name="parameter" + minOccurs="0" + maxOccurs="unbounded" /> + <xs:element type="map:crossParameterType" + name="cross-parameter" + minOccurs="0" + maxOccurs="1" /> + <xs:element type="map:returnValueType" + name="return-value" + minOccurs="0" + maxOccurs="1" /> + </xs:sequence> + <xs:attribute type="xs:boolean" name="ignore-annotations" use="optional" /> + </xs:complexType> + <xs:complexType name="parameterType"> + <xs:sequence> + <xs:element type="xs:string" name="valid" minOccurs="0" fixed="" /> + <xs:element type="map:groupConversionType" + name="convert-group" + minOccurs="0" + maxOccurs="unbounded" /> + <xs:element type="map:containerElementTypeType" + name="container-element-type" + minOccurs="0" + maxOccurs="unbounded" /> + <xs:element type="map:constraintType" + name="constraint" + minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + <xs:attribute type="xs:string" name="type" use="required" /> + <xs:attribute type="xs:boolean" name="ignore-annotations" use="optional" /> + </xs:complexType> + <xs:complexType name="returnValueType"> + <xs:sequence> + <xs:element type="xs:string" name="valid" minOccurs="0" fixed="" /> + <xs:element type="map:groupConversionType" + name="convert-group" + minOccurs="0" + maxOccurs="unbounded" /> + <xs:element type="map:containerElementTypeType" + name="container-element-type" + minOccurs="0" + maxOccurs="unbounded" /> + <xs:element type="map:constraintType" + name="constraint" + minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + <xs:attribute type="xs:boolean" name="ignore-annotations" use="optional" /> + </xs:complexType> + <xs:complexType name="crossParameterType"> + <xs:sequence> + <xs:element type="map:constraintType" + name="constraint" + minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + <xs:attribute type="xs:boolean" name="ignore-annotations" use="optional" /> + </xs:complexType> + <xs:complexType name="constraint-definitionType"> + <xs:sequence> + <xs:element type="map:validated-byType" + name="validated-by" /> + </xs:sequence> + <xs:attribute type="xs:string" name="annotation" use="required" /> + </xs:complexType> + <xs:complexType name="fieldType"> + <xs:sequence> + <xs:element type="xs:string" name="valid" minOccurs="0" fixed="" /> + <xs:element type="map:groupConversionType" + name="convert-group" + minOccurs="0" + maxOccurs="unbounded" /> + <xs:element type="map:containerElementTypeType" + name="container-element-type" + minOccurs="0" + maxOccurs="unbounded" /> + <xs:element type="map:constraintType" + name="constraint" + minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + <xs:attribute type="xs:string" name="name" use="required" /> + <xs:attribute type="xs:boolean" name="ignore-annotations" use="optional" /> + </xs:complexType> +</xs:schema> http://git-wip-us.apache.org/repos/asf/bval/blob/5c09f0dd/bval-jsr/src/test/java/org/apache/bval/jsr/xml/Demo.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/test/java/org/apache/bval/jsr/xml/Demo.java b/bval-jsr/src/test/java/org/apache/bval/jsr/xml/Demo.java new file mode 100644 index 0000000..02a07a8 --- /dev/null +++ b/bval-jsr/src/test/java/org/apache/bval/jsr/xml/Demo.java @@ -0,0 +1,40 @@ +package org.apache.bval.jsr.xml; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.UnmarshallerHandler; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.junit.Test; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; + +public class Demo { + + @Test + public void test1() throws Exception { + JAXBContext jc = JAXBContext.newInstance(ObjectFactory.class); + + // Set the parent XMLReader on the XMLFilter + SAXParserFactory spf = SAXParserFactory.newInstance(); + spf.setNamespaceAware(true); + SAXParser sp = spf.newSAXParser(); + XMLReader xr = sp.getXMLReader(); + + // Set UnmarshallerHandler as ContentHandler on XMLFilter + + Unmarshaller unmarshaller = jc.createUnmarshaller(); + + UnmarshallerHandler unmarshallerHandler = unmarshaller.getUnmarshallerHandler(); + xr.setContentHandler(unmarshallerHandler); + + // Parse the XML + InputSource xml = new InputSource(getClass().getResourceAsStream("/sample-validation2.xml")); + xr.parse(xml); + JAXBElement<ValidationConfigType> result = (JAXBElement<ValidationConfigType>) unmarshallerHandler.getResult(); + System.out.println(ToStringBuilder.reflectionToString(result.getValue())); + } +} http://git-wip-us.apache.org/repos/asf/bval/blob/5c09f0dd/bval-jsr/src/test/java/org/apache/bval/jsr/xml/ValidationParserTest.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/test/java/org/apache/bval/jsr/xml/ValidationParserTest.java b/bval-jsr/src/test/java/org/apache/bval/jsr/xml/ValidationParserTest.java index 827abae..41d4f13 100644 --- a/bval-jsr/src/test/java/org/apache/bval/jsr/xml/ValidationParserTest.java +++ b/bval-jsr/src/test/java/org/apache/bval/jsr/xml/ValidationParserTest.java @@ -19,6 +19,8 @@ package org.apache.bval.jsr.xml; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @@ -84,6 +86,18 @@ public class ValidationParserTest implements ApacheValidatorConfiguration.Proper } @Test + public void testParseV11() { + ConfigurationImpl config = new ConfigurationImpl(null, new ApacheValidationProvider()); + ValidationParser.processValidationConfig("sample-validation11.xml", config, false); + } + + @Test + public void testParseV20() { + ConfigurationImpl config = new ConfigurationImpl(null, new ApacheValidationProvider()); + ValidationParser.processValidationConfig("sample-validation2.xml", config, false); + } + + @Test public void testConfigureFromXml() { ValidatorFactory factory = getFactory(); assertThat(factory.getMessageInterpolator(), instanceOf(TestMessageInterpolator.class)); @@ -105,8 +119,8 @@ public class ValidationParserTest implements ApacheValidatorConfiguration.Proper bean.setValueCode("illegal"); Validator validator = getFactory().getValidator(); Set<ConstraintViolation<XmlEntitySampleBean>> results = validator.validate(bean); - assertTrue(!results.isEmpty()); - assertTrue(results.size() == 3); + assertFalse(results.isEmpty()); + assertEquals(3, results.size()); bean.setZipCode("123"); bean.setValueCode("20"); http://git-wip-us.apache.org/repos/asf/bval/blob/5c09f0dd/bval-jsr/src/test/resources/sample-validation11.xml ---------------------------------------------------------------------- diff --git a/bval-jsr/src/test/resources/sample-validation11.xml b/bval-jsr/src/test/resources/sample-validation11.xml new file mode 100644 index 0000000..648ba1c --- /dev/null +++ b/bval-jsr/src/test/resources/sample-validation11.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<validation-config + xmlns="http://jboss.org/xml/ns/javax/validation/configuration" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation= + "http://jboss.org/xml/ns/javax/validation/configuration validation-configuration-1.0.xsd" + version="1.1"> + <default-provider>org.apache.bval.jsr.ApacheValidationProvider</default-provider> + <message-interpolator>org.apache.bval.jsr.xml.TestMessageInterpolator</message-interpolator> + <traversable-resolver>org.apache.bval.jsr.resolver.SimpleTraversableResolver</traversable-resolver> + <constraint-validator-factory>org.apache.bval.jsr.xml.TestConstraintValidatorFactory</constraint-validator-factory> + <constraint-mapping>sample-constraints.xml</constraint-mapping> + <property name="test-prop">test-prop-value</property> +</validation-config> http://git-wip-us.apache.org/repos/asf/bval/blob/5c09f0dd/bval-jsr/src/test/resources/sample-validation2.xml ---------------------------------------------------------------------- diff --git a/bval-jsr/src/test/resources/sample-validation2.xml b/bval-jsr/src/test/resources/sample-validation2.xml new file mode 100644 index 0000000..4758454 --- /dev/null +++ b/bval-jsr/src/test/resources/sample-validation2.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<validation-config + xmlns="http://xmlns.jcp.org/xml/ns/javax/validation/configuration" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation= + "http://xmlns.jcp.org/xml/ns/javax/validation/configuration validation-configuration-2.0.xsd" + version="2.0"> + <default-provider>org.apache.bval.jsr.ApacheValidationProvider</default-provider> + <message-interpolator>org.apache.bval.jsr.xml.TestMessageInterpolator</message-interpolator> + <traversable-resolver>org.apache.bval.jsr.resolver.SimpleTraversableResolver</traversable-resolver> + <constraint-validator-factory>org.apache.bval.jsr.xml.TestConstraintValidatorFactory</constraint-validator-factory> + <constraint-mapping>sample-constraints.xml</constraint-mapping> + <property name="test-prop">test-prop-value</property> +</validation-config>
