From 6b69a608b5ffef54d483bae2e932949ce733119a Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 4 Apr 2018 16:43:11 +0200 Subject: [PATCH 001/393] Prepare master for 6.1 developments --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 3687fd8c44..6b70540803 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 6e3d9a3cff..021058c8f5 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index 08d7f43ccb..02535a0199 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index a8d1f5afdd..09afdfb706 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 4cfd462026..1d0dff51df 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index e615c850cd..903f7878ed 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index adb617610a..2195ede544 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index fe3bec7170..0ed8f9d55a 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 7ce49d4fb6..e98de4737b 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 869857cb10..36961223a5 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index d7df970c38..1b9ec9f304 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index e54c36050d..fc4f7e3a85 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index 37f1726e70..f621823843 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index bc05e88713..fdf19d6603 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index c78e4a08d7..3f99228d35 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index 5346ffb489..acc9a54560 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index f8b6393a23..d793ee6b6e 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index a237283b0a..c2eba20d47 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index f8b8ce054d..6516654b3f 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index d637abbde5..5e2587ff5a 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index c7c34f94ee..3b0766e5c7 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.0.10-SNAPSHOT + 6.1.0-SNAPSHOT hibernate-validator-test-utils From 56b3111362283b2b6ee844594bafcffc4b2c72bf Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Fri, 23 Mar 2018 16:54:45 +0100 Subject: [PATCH 002/393] HV-1577 Move from JAXB to Stax for XML configuration --- .../internal/engine/ConfigurationImpl.java | 4 +- .../validator/internal/util/logging/Log.java | 3 + .../internal/xml/AbstractStaxBuilder.java | 88 +++++ .../xml/CloseIgnoringInputStream.java | 2 +- .../internal/xml/ValidationXmlParser.java | 274 ---------------- .../internal/xml/XmlParserHelper.java | 2 +- .../BootstrapConfigurationImpl.java | 4 +- .../{ => config}/ResourceLoaderHelper.java | 2 +- .../ValidationBootstrapParameters.java | 2 +- .../config/ValidationConfigStaxBuilder.java | 307 ++++++++++++++++++ .../xml/config/ValidationXmlParser.java | 161 +++++++++ 11 files changed, 567 insertions(+), 282 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/AbstractStaxBuilder.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/ValidationXmlParser.java rename engine/src/main/java/org/hibernate/validator/internal/xml/{ => config}/BootstrapConfigurationImpl.java (98%) rename engine/src/main/java/org/hibernate/validator/internal/xml/{ => config}/ResourceLoaderHelper.java (98%) rename engine/src/main/java/org/hibernate/validator/internal/xml/{ => config}/ValidationBootstrapParameters.java (99%) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationConfigStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationXmlParser.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java index 5fe13d90f0..863467d48a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java @@ -49,8 +49,8 @@ import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader; import org.hibernate.validator.internal.util.privilegedactions.GetInstancesFromServiceLoader; import org.hibernate.validator.internal.util.privilegedactions.SetContextClassLoader; -import org.hibernate.validator.internal.xml.ValidationBootstrapParameters; -import org.hibernate.validator.internal.xml.ValidationXmlParser; +import org.hibernate.validator.internal.xml.config.ValidationBootstrapParameters; +import org.hibernate.validator.internal.xml.config.ValidationXmlParser; import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; import org.hibernate.validator.resourceloading.PlatformResourceBundleLocator; import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 816e30a440..4479ec69d2 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -841,4 +841,7 @@ ValidationException getUnableToAccessMethodException(Lookup lookup, @FormatWith( @LogMessage(level = DEBUG) @Message(id = 240, value = "Constraint validator payload set to %1$s.") void logConstraintValidatorPayload(Object payload); + + @Message(id = 241, value = "Encountered unsupported element %1$s while parsing the XML configuration.") + ValidationException logUnknownElementInXmlConfiguration(String tag); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/AbstractStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/AbstractStaxBuilder.java new file mode 100644 index 0000000000..bbe5f22108 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/AbstractStaxBuilder.java @@ -0,0 +1,88 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml; + +import java.util.Optional; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +/** + * Other Stax xml builders should extend from this one. + * Provides some common functionality like reading an attribute value + * or value of a simple tag. + * + * @author Marko Bekhta + */ +public abstract class AbstractStaxBuilder { + + protected abstract String getAcceptableQName(); + + /** + * Checks if the given {@link XMLEvent} is a {@link StartElement} and if the + * corresponding xml tag can be processed based on a tag name. + * + * @param xmlEvent an event to check + * + * @return {@code true} if corresponding event can be processed by current builder, + * {@code false} otherwise + */ + protected boolean accept(XMLEvent xmlEvent) { + return xmlEvent.isStartElement() && xmlEvent.asStartElement().getName().getLocalPart().equals( getAcceptableQName() ); + } + + public boolean process(XMLEventReader xmlEventReader, XMLEvent xmlEvent) { + if ( accept( xmlEvent ) ) { + try { + add( xmlEventReader, xmlEvent ); + } + catch (XMLStreamException e) { + throw new IllegalStateException( e ); + } + return true; + } + return false; + } + + protected abstract void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException; + + /** + * Reads a value between a simple tag element. In case of a {@code some-value} will + * return {@code some-value} as a string. + * + * @param xmlEventReader a current {@link XMLEventReader} + * + * @return a value of a current xml tag as a string + */ + protected String readSingleElement(XMLEventReader xmlEventReader) throws XMLStreamException { + // trimming the string value as it might contain leading/trailing spaces or \n + XMLEvent xmlEvent = xmlEventReader.nextEvent(); + StringBuilder stringBuilder = new StringBuilder( xmlEvent.asCharacters().getData() ); + while ( xmlEventReader.peek().isCharacters() ) { + xmlEvent = xmlEventReader.nextEvent(); + stringBuilder.append( xmlEvent.asCharacters().getData() ); + } + return stringBuilder.toString().trim(); + } + + /** + * Reads a value of an attribute of a given element. + * + * @param startElement an element to get an attribute from + * @param qName a {@link QName} of an attribute to read + * + * @return a value of an attribute if it is present, {@link Optional#empty()} otherwise + */ + protected Optional readAttribute(StartElement startElement, QName qName) { + Attribute attribute = startElement.getAttributeByName( qName ); + return Optional.ofNullable( attribute ).map( Attribute::getValue ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/CloseIgnoringInputStream.java b/engine/src/main/java/org/hibernate/validator/internal/xml/CloseIgnoringInputStream.java index 7db4d6fc7b..e5def26adc 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/CloseIgnoringInputStream.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/CloseIgnoringInputStream.java @@ -17,7 +17,7 @@ * * @author Guillaume Smet */ -class CloseIgnoringInputStream extends FilterInputStream { +public class CloseIgnoringInputStream extends FilterInputStream { public CloseIgnoringInputStream(InputStream in) { super( in ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/ValidationXmlParser.java b/engine/src/main/java/org/hibernate/validator/internal/xml/ValidationXmlParser.java deleted file mode 100644 index 8d7dd550b0..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/ValidationXmlParser.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.xml; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.invoke.MethodHandles; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedExceptionAction; -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.Set; - -import javax.validation.BootstrapConfiguration; -import javax.validation.executable.ExecutableType; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.Unmarshaller; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLStreamException; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.Validator; - -import org.hibernate.validator.HibernateValidatorConfiguration; -import org.hibernate.validator.internal.util.CollectionHelper; -import org.hibernate.validator.internal.util.logging.Log; -import org.hibernate.validator.internal.util.logging.LoggerFactory; -import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader; -import org.hibernate.validator.internal.util.privilegedactions.NewJaxbContext; -import org.hibernate.validator.internal.util.privilegedactions.SetContextClassLoader; -import org.hibernate.validator.internal.util.privilegedactions.Unmarshal; -import org.hibernate.validator.internal.xml.binding.DefaultValidatedExecutableTypesType; -import org.hibernate.validator.internal.xml.binding.ExecutableValidationType; -import org.hibernate.validator.internal.xml.binding.PropertyType; -import org.hibernate.validator.internal.xml.binding.ValidationConfigType; - -import org.xml.sax.SAXException; - -/** - * Parser for validation.xml using JAXB. - * - * @author Hardy Ferentschik - * @author Gunnar Morling - */ -public class ValidationXmlParser { - - private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - - private static final String VALIDATION_XML_FILE = "META-INF/validation.xml"; - private static final Map SCHEMAS_BY_VERSION = Collections.unmodifiableMap( getSchemasByVersion() ); - - private final ClassLoader externalClassLoader; - - private static Map getSchemasByVersion() { - Map schemasByVersion = CollectionHelper.newHashMap( 3 ); - - schemasByVersion.put( "1.0", "META-INF/validation-configuration-1.0.xsd" ); - schemasByVersion.put( "1.1", "META-INF/validation-configuration-1.1.xsd" ); - schemasByVersion.put( "2.0", "META-INF/validation-configuration-2.0.xsd" ); - - return schemasByVersion; - } - - public ValidationXmlParser(ClassLoader externalClassLoader) { - this.externalClassLoader = externalClassLoader; - } - - /** - * Tries to check whether a validation.xml file exists and parses it. - * - * @return The parameters parsed out of validation.xml wrapped in an instance of {@code ConfigurationImpl.ValidationBootstrapParameters}. - */ - public final BootstrapConfiguration parseValidationXml() { - InputStream in = getValidationXmlInputStream(); - if ( in == null ) { - return BootstrapConfigurationImpl.getDefaultBootstrapConfiguration(); - } - - ClassLoader previousTccl = run( GetClassLoader.fromContext() ); - - try { - run( SetContextClassLoader.action( ValidationXmlParser.class.getClassLoader() ) ); - - // HV-970 The parser helper is only loaded if there actually is a validation.xml file; - // this avoids accessing javax.xml.stream.* (which does not exist on Android) when not actually - // working with the XML configuration - XmlParserHelper xmlParserHelper = new XmlParserHelper(); - - // the InputStream supports mark and reset - in.mark( Integer.MAX_VALUE ); - - XMLEventReader xmlEventReader = xmlParserHelper.createXmlEventReader( VALIDATION_XML_FILE, new CloseIgnoringInputStream( in ) ); - String schemaVersion = xmlParserHelper.getSchemaVersion( VALIDATION_XML_FILE, xmlEventReader ); - xmlEventReader.close(); - - in.reset(); - - // The validation is done first as we manipulate the XML document before pushing it to the unmarshaller - // and it might not be valid anymore as we might have switched the namespace to the latest namespace - // supported. - Schema schema = getSchema( xmlParserHelper, schemaVersion ); - Validator validator = schema.newValidator(); - validator.validate( new StreamSource( new CloseIgnoringInputStream( in ) ) ); - - in.reset(); - - xmlEventReader = xmlParserHelper.createXmlEventReader( VALIDATION_XML_FILE, new CloseIgnoringInputStream( in ) ); - ValidationConfigType validationConfig = unmarshal( xmlEventReader ); - xmlEventReader.close(); - - return createBootstrapConfiguration( validationConfig ); - } - catch (XMLStreamException | IOException | SAXException e) { - throw LOG.getUnableToParseValidationXmlFileException( VALIDATION_XML_FILE, e ); - } - finally { - run( SetContextClassLoader.action( previousTccl ) ); - closeStream( in ); - } - } - - private InputStream getValidationXmlInputStream() { - LOG.debugf( "Trying to load %s for XML based Validator configuration.", VALIDATION_XML_FILE ); - InputStream inputStream = ResourceLoaderHelper.getResettableInputStreamForPath( VALIDATION_XML_FILE, externalClassLoader ); - - if ( inputStream != null ) { - return inputStream; - } - else { - LOG.debugf( "No %s found. Using annotation based configuration only.", VALIDATION_XML_FILE ); - return null; - } - } - - private Schema getSchema(XmlParserHelper xmlParserHelper, String schemaVersion) { - String schemaResource = SCHEMAS_BY_VERSION.get( schemaVersion ); - - if ( schemaResource == null ) { - throw LOG.getUnsupportedSchemaVersionException( VALIDATION_XML_FILE, schemaVersion ); - } - - return xmlParserHelper.getSchema( schemaResource ); - } - - private ValidationConfigType unmarshal(XMLEventReader xmlEventReader) { - LOG.parsingXMLFile( VALIDATION_XML_FILE ); - - try { - // JAXBContext#newInstance() requires several permissions internally and doesn't use any privileged blocks - // itself; Wrapping it here avoids that all calling code bases need to have these permissions as well - JAXBContext jc = run( NewJaxbContext.action( ValidationConfigType.class ) ); - Unmarshaller unmarshaller = jc.createUnmarshaller(); - - // Unmashaller#unmarshal() requires several permissions internally and doesn't use any privileged blocks - // itself; Wrapping it here avoids that all calling code bases need to have these permissions as well - JAXBElement root = run( Unmarshal.action( unmarshaller, xmlEventReader, ValidationConfigType.class ) ); - return root.getValue(); - } - catch (Exception e) { - throw LOG.getUnableToParseValidationXmlFileException( VALIDATION_XML_FILE, e ); - } - } - - private void closeStream(InputStream inputStream) { - try { - inputStream.close(); - } - catch (IOException io) { - LOG.unableToCloseXMLFileInputStream( VALIDATION_XML_FILE ); - } - } - - private BootstrapConfiguration createBootstrapConfiguration(ValidationConfigType config) { - Map properties = new HashMap<>(); - for ( PropertyType property : config.getProperty() ) { - if ( LOG.isDebugEnabled() ) { - LOG.debugf( - "Found property '%s' with value '%s' in validation.xml.", - property.getName(), - property.getValue() - ); - } - properties.put( property.getName(), property.getValue() ); - } - - ExecutableValidationType executableValidationType = config.getExecutableValidation(); - EnumSet defaultValidatedExecutableTypes = executableValidationType == null - ? getValidatedExecutableTypes( null ) - : getValidatedExecutableTypes( executableValidationType.getDefaultValidatedExecutableTypes() ); - boolean executableValidationEnabled = executableValidationType == null || executableValidationType.getEnabled(); - - return new BootstrapConfigurationImpl( - config.getDefaultProvider(), - config.getConstraintValidatorFactory(), - config.getMessageInterpolator(), - config.getTraversableResolver(), - config.getParameterNameProvider(), - config.getClockProvider(), - getScriptEvaluatorFactoryClassProperty( config.getProperty() ), - getValueExtractorClassNames( config ), - defaultValidatedExecutableTypes, - executableValidationEnabled, - new HashSet<>( config.getConstraintMapping() ), - properties - ); - } - - private String getScriptEvaluatorFactoryClassProperty(List properties) { - return properties.stream() - .filter( property -> HibernateValidatorConfiguration.SCRIPT_EVALUATOR_FACTORY_CLASSNAME.equals( property.getName() ) ) - .map( PropertyType::getValue ) - .findFirst().orElse( null ); - } - - private Set getValueExtractorClassNames(ValidationConfigType config) { - Set valueExtractorClassNames = CollectionHelper.newHashSet( config.getValueExtractor().size() ); - for ( String className : config.getValueExtractor() ) { - if ( !valueExtractorClassNames.add( className ) ) { - throw LOG.getDuplicateDefinitionsOfValueExtractorException( className ); - } - } - return valueExtractorClassNames; - } - - /** - * Returns an enum set with the executable types corresponding to the given - * XML configuration, considering the special elements - * {@link ExecutableType#ALL} and {@link ExecutableType#NONE}. - * - * @param validatedExecutables Schema type with executable types. - * - * @return An enum set representing the given executable types. - */ - private EnumSet getValidatedExecutableTypes(DefaultValidatedExecutableTypesType validatedExecutables) { - if ( validatedExecutables == null ) { - return null; - } - - EnumSet executableTypes = EnumSet.noneOf( ExecutableType.class ); - executableTypes.addAll( validatedExecutables.getExecutableType() ); - - return executableTypes; - } - - /** - * Runs the given privileged action, using a privileged block if required. - *

- * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary - * privileged actions within HV's protection domain. - */ - private static T run(PrivilegedAction action) { - return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); - } - - /** - * Runs the given privileged action, using a privileged block if required. - *

- * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary - * privileged actions within HV's protection domain. - */ - private T run(PrivilegedExceptionAction action) throws Exception { - return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); - } -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/XmlParserHelper.java b/engine/src/main/java/org/hibernate/validator/internal/xml/XmlParserHelper.java index a2001c4c03..6ba3ba1762 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/XmlParserHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/XmlParserHelper.java @@ -143,7 +143,7 @@ private StartElement getRootElement(XMLEventReader xmlEventReader) throws XMLStr * @return the schema identified by the given resource name or {@code null} if the resource was not found or could * not be loaded. */ - Schema getSchema(String schemaResource) { + public Schema getSchema(String schemaResource) { Schema schema = schemaCache.get( schemaResource ); if ( schema != null ) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/BootstrapConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/xml/config/BootstrapConfigurationImpl.java similarity index 98% rename from engine/src/main/java/org/hibernate/validator/internal/xml/BootstrapConfigurationImpl.java rename to engine/src/main/java/org/hibernate/validator/internal/xml/config/BootstrapConfigurationImpl.java index 0c6f03a914..57a7639e51 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/BootstrapConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/config/BootstrapConfigurationImpl.java @@ -4,7 +4,7 @@ * License: Apache License, Version 2.0 * See the license.txt file in the root directory or . */ -package org.hibernate.validator.internal.xml; +package org.hibernate.validator.internal.xml.config; import java.util.Collections; import java.util.EnumSet; @@ -23,7 +23,7 @@ * * @author Hardy Ferentschik */ -public class BootstrapConfigurationImpl implements BootstrapConfiguration { +class BootstrapConfigurationImpl implements BootstrapConfiguration { /** * The executable types validated by default. diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/ResourceLoaderHelper.java b/engine/src/main/java/org/hibernate/validator/internal/xml/config/ResourceLoaderHelper.java similarity index 98% rename from engine/src/main/java/org/hibernate/validator/internal/xml/ResourceLoaderHelper.java rename to engine/src/main/java/org/hibernate/validator/internal/xml/config/ResourceLoaderHelper.java index db36ca736a..442113cc00 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/ResourceLoaderHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/config/ResourceLoaderHelper.java @@ -4,7 +4,7 @@ * License: Apache License, Version 2.0 * See the license.txt file in the root directory or . */ -package org.hibernate.validator.internal.xml; +package org.hibernate.validator.internal.xml.config; import java.io.BufferedInputStream; import java.io.InputStream; diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/ValidationBootstrapParameters.java b/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationBootstrapParameters.java similarity index 99% rename from engine/src/main/java/org/hibernate/validator/internal/xml/ValidationBootstrapParameters.java rename to engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationBootstrapParameters.java index 4460711659..47925728c7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/ValidationBootstrapParameters.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationBootstrapParameters.java @@ -4,7 +4,7 @@ * License: Apache License, Version 2.0 * See the license.txt file in the root directory or . */ -package org.hibernate.validator.internal.xml; +package org.hibernate.validator.internal.xml.config; import java.io.InputStream; import java.lang.invoke.MethodHandles; diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationConfigStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationConfigStaxBuilder.java new file mode 100644 index 0000000000..cce3774050 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationConfigStaxBuilder.java @@ -0,0 +1,307 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.config; + +import java.lang.invoke.MethodHandles; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import javax.validation.BootstrapConfiguration; +import javax.validation.executable.ExecutableType; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import org.hibernate.validator.HibernateValidatorConfiguration; +import org.hibernate.validator.internal.util.CollectionHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.internal.xml.AbstractStaxBuilder; + +/** + * Stax parser/builder for {@code validation.xml} that reads {@code } + * information and creates {@link BootstrapConfiguration}. + * + * @author Marko Bekhta + */ +class ValidationConfigStaxBuilder extends AbstractStaxBuilder { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + private static final String VALIDATION_CONFIG_QNAME = "validation-config"; + + private final SimpleConfigurationsStaxBuilder simpleConfigurationsStaxBuilder = new SimpleConfigurationsStaxBuilder(); + private final PropertyStaxBuilder propertyStaxBuilder = new PropertyStaxBuilder(); + private final ValueExtractorsStaxBuilder valueExtractorsStaxBuilder = new ValueExtractorsStaxBuilder(); + private final ConstraintMappingsStaxBuilder constraintMappingsStaxBuilder = new ConstraintMappingsStaxBuilder(); + private final ExecutableValidationStaxBuilder executableValidationStaxBuilder = new ExecutableValidationStaxBuilder(); + + private final Map builders; + + public ValidationConfigStaxBuilder(XMLEventReader xmlEventReader) throws XMLStreamException { + builders = new HashMap<>(); + builders.put( propertyStaxBuilder.getAcceptableQName(), propertyStaxBuilder ); + builders.put( valueExtractorsStaxBuilder.getAcceptableQName(), valueExtractorsStaxBuilder ); + builders.put( constraintMappingsStaxBuilder.getAcceptableQName(), constraintMappingsStaxBuilder ); + builders.put( executableValidationStaxBuilder.getAcceptableQName(), executableValidationStaxBuilder ); + for ( String name : SimpleConfigurationsStaxBuilder.getProcessedElementNames() ) { + builders.put( name, simpleConfigurationsStaxBuilder ); + } + + while ( xmlEventReader.hasNext() ) { + process( xmlEventReader, xmlEventReader.nextEvent() ); + } + } + + @Override + protected String getAcceptableQName() { + return VALIDATION_CONFIG_QNAME; + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( VALIDATION_CONFIG_QNAME ) ) ) { + XMLEvent currentEvent = xmlEventReader.nextEvent(); + xmlEvent = currentEvent; + if ( currentEvent.isStartElement() ) { + StartElement startElement = currentEvent.asStartElement(); + String localPart = startElement.getName().getLocalPart(); + AbstractStaxBuilder builder = builders.get( localPart ); + if ( builder != null ) { + builder.process( xmlEventReader, xmlEvent ); + } + else { + LOG.logUnknownElementInXmlConfiguration( localPart ); + } + } + } + } + + public BootstrapConfiguration build() { + Map properties = propertyStaxBuilder.build(); + return new BootstrapConfigurationImpl( + simpleConfigurationsStaxBuilder.getDefaultProvider(), + simpleConfigurationsStaxBuilder.getConstraintValidatorFactory(), + simpleConfigurationsStaxBuilder.getMessageInterpolator(), + simpleConfigurationsStaxBuilder.getTraversableResolver(), + simpleConfigurationsStaxBuilder.getParameterNameProvider(), + simpleConfigurationsStaxBuilder.getClockProvider(), + properties.get( HibernateValidatorConfiguration.SCRIPT_EVALUATOR_FACTORY_CLASSNAME ), + valueExtractorsStaxBuilder.build(), + executableValidationStaxBuilder.build(), + executableValidationStaxBuilder.isEnabled(), + constraintMappingsStaxBuilder.build(), + properties + ); + } + + private static class SimpleConfigurationsStaxBuilder extends AbstractStaxBuilder { + + /** + * Single occurrence elements: + */ + private static final String DEFAULT_PROVIDER = "default-provider"; + private static final String MESSAGE_INTERPOLATOR = "message-interpolator"; + private static final String TRAVERSABLE_RESOLVER = "traversable-resolver"; + private static final String CONSTRAINT_VALIDATOR_FACTORY = "constraint-validator-factory"; + private static final String PARAMETER_NAME_PROVIDER = "parameter-name-provider"; + private static final String CLOCK_PROVIDER = "clock-provider"; + + private static final Set SINGLE_ELEMENTS = CollectionHelper.toImmutableSet( + CollectionHelper.asSet( + DEFAULT_PROVIDER, MESSAGE_INTERPOLATOR, TRAVERSABLE_RESOLVER, + CONSTRAINT_VALIDATOR_FACTORY, PARAMETER_NAME_PROVIDER, CLOCK_PROVIDER + ) + ); + + /** + * Map that contains any of the {@link this#SINGLE_ELEMENTS} elements. + */ + private final Map singleValuedElements = new HashMap<>(); + + @Override + protected String getAcceptableQName() { + throw new UnsupportedOperationException( "this method shouldn't be called" ); + } + + @Override + protected boolean accept(XMLEvent xmlEvent) { + return xmlEvent.isStartElement() + && SINGLE_ELEMENTS.contains( xmlEvent.asStartElement().getName().getLocalPart() ); + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + String localPart = xmlEvent.asStartElement().getName().getLocalPart(); + singleValuedElements.put( localPart, readSingleElement( xmlEventReader ) ); + } + + public String getDefaultProvider() { + return singleValuedElements.get( DEFAULT_PROVIDER ); + } + + public String getMessageInterpolator() { + return singleValuedElements.get( MESSAGE_INTERPOLATOR ); + } + + public String getTraversableResolver() { + return singleValuedElements.get( TRAVERSABLE_RESOLVER ); + } + + public String getClockProvider() { + return singleValuedElements.get( CLOCK_PROVIDER ); + } + + public String getConstraintValidatorFactory() { + return singleValuedElements.get( CONSTRAINT_VALIDATOR_FACTORY ); + } + + public String getParameterNameProvider() { + return singleValuedElements.get( PARAMETER_NAME_PROVIDER ); + } + + public static Set getProcessedElementNames() { + return SINGLE_ELEMENTS; + } + } + + private static class PropertyStaxBuilder extends AbstractStaxBuilder { + + private static final String PROPERTY_QNAME_LOCAL_PART = "property"; + private static final QName NAME_QNAME = new QName( "name" ); + + private final Map properties; + + private PropertyStaxBuilder() { + properties = new HashMap<>(); + } + + @Override + protected String getAcceptableQName() { + return PROPERTY_QNAME_LOCAL_PART; + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + StartElement startElement = xmlEvent.asStartElement(); + String name = readAttribute( startElement, NAME_QNAME ).get(); + String value = readSingleElement( xmlEventReader ); + if ( LOG.isDebugEnabled() ) { + LOG.debugf( + "Found property '%s' with value '%s' in validation.xml.", + name, + value + ); + } + properties.put( name, value ); + } + + public Map build() { + return properties; + } + } + + private static class ValueExtractorsStaxBuilder extends AbstractStaxBuilder { + + private static final String VALUE_EXTRACTOR_QNAME_LOCAL_PART = "value-extractor"; + + private final Set valueExtractors = new HashSet<>(); + + @Override + protected String getAcceptableQName() { + return VALUE_EXTRACTOR_QNAME_LOCAL_PART; + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + String value = readSingleElement( xmlEventReader ); + if ( !valueExtractors.add( value ) ) { + throw LOG.getDuplicateDefinitionsOfValueExtractorException( value ); + } + } + + public Set build() { + return valueExtractors; + } + } + + private static class ConstraintMappingsStaxBuilder extends AbstractStaxBuilder { + + private static final String CONSTRAINT_MAPPING_QNAME_LOCAL_PART = "constraint-mapping"; + + private final Set constraintMappings = new HashSet<>(); + + @Override + protected String getAcceptableQName() { + return CONSTRAINT_MAPPING_QNAME_LOCAL_PART; + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + String value = readSingleElement( xmlEventReader ); + constraintMappings.add( value ); + } + + public Set build() { + return constraintMappings; + } + } + + private static class ExecutableValidationStaxBuilder extends AbstractStaxBuilder { + + private static final String EXECUTABLE_VALIDATION_QNAME_LOCAL_PART = "executable-validation"; + private static final String EXECUTABLE_TYPE_QNAME_LOCAL_PART = "executable-type"; + + private static final QName ENABLED_QNAME = new QName( "enabled" ); + + private Boolean enabled; + + private EnumSet executableTypes = EnumSet.noneOf( ExecutableType.class ); + + @Override + protected String getAcceptableQName() { + return EXECUTABLE_VALIDATION_QNAME_LOCAL_PART; + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + Optional enabledAttribute = readAttribute( xmlEvent.asStartElement(), ENABLED_QNAME ); + if ( enabledAttribute.isPresent() ) { + enabled = Boolean.parseBoolean( enabledAttribute.get() ); + } + + while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( EXECUTABLE_VALIDATION_QNAME_LOCAL_PART ) ) ) { + XMLEvent currentEvent = xmlEventReader.nextEvent(); + xmlEvent = currentEvent; + if ( currentEvent.isStartElement() && currentEvent.asStartElement().getName().getLocalPart().equals( EXECUTABLE_TYPE_QNAME_LOCAL_PART ) ) { + executableTypes.add( ExecutableType.valueOf( readSingleElement( xmlEventReader ) ) ); + } + } + } + + public boolean isEnabled() { + return enabled == null ? true : enabled; + } + + /** + * Returns an enum set with the executable types corresponding to the given + * XML configuration, considering the special elements + * {@link ExecutableType#ALL} and {@link ExecutableType#NONE}. + * + * @return An enum set representing the given executable types. + */ + public EnumSet build() { + return executableTypes.isEmpty() ? null : executableTypes; + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationXmlParser.java b/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationXmlParser.java new file mode 100644 index 0000000000..059ae6df1c --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationXmlParser.java @@ -0,0 +1,161 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.config; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.invoke.MethodHandles; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collections; +import java.util.Map; + +import javax.validation.BootstrapConfiguration; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.Validator; + +import org.hibernate.validator.internal.util.CollectionHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader; +import org.hibernate.validator.internal.util.privilegedactions.SetContextClassLoader; +import org.hibernate.validator.internal.xml.CloseIgnoringInputStream; +import org.hibernate.validator.internal.xml.XmlParserHelper; + +import org.xml.sax.SAXException; + +/** + * Parser for validation.xml using JAXB. + * + * @author Hardy Ferentschik + * @author Gunnar Morling + */ +public class ValidationXmlParser { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + private static final String VALIDATION_XML_FILE = "META-INF/validation.xml"; + private static final Map SCHEMAS_BY_VERSION = Collections.unmodifiableMap( getSchemasByVersion() ); + + private final ClassLoader externalClassLoader; + + private static Map getSchemasByVersion() { + Map schemasByVersion = CollectionHelper.newHashMap( 3 ); + + schemasByVersion.put( "1.0", "META-INF/validation-configuration-1.0.xsd" ); + schemasByVersion.put( "1.1", "META-INF/validation-configuration-1.1.xsd" ); + schemasByVersion.put( "2.0", "META-INF/validation-configuration-2.0.xsd" ); + + return schemasByVersion; + } + + public ValidationXmlParser(ClassLoader externalClassLoader) { + this.externalClassLoader = externalClassLoader; + } + + /** + * Tries to check whether a validation.xml file exists and parses it. + * + * @return The parameters parsed out of validation.xml wrapped in an instance of {@code ConfigurationImpl.ValidationBootstrapParameters}. + */ + public final BootstrapConfiguration parseValidationXml() { + InputStream in = getValidationXmlInputStream(); + if ( in == null ) { + return BootstrapConfigurationImpl.getDefaultBootstrapConfiguration(); + } + + ClassLoader previousTccl = run( GetClassLoader.fromContext() ); + + try { + run( SetContextClassLoader.action( ValidationXmlParser.class.getClassLoader() ) ); + + // HV-970 The parser helper is only loaded if there actually is a validation.xml file; + // this avoids accessing javax.xml.stream.* (which does not exist on Android) when not actually + // working with the XML configuration + XmlParserHelper xmlParserHelper = new XmlParserHelper(); + + // the InputStream supports mark and reset + in.mark( Integer.MAX_VALUE ); + + XMLEventReader xmlEventReader = xmlParserHelper.createXmlEventReader( VALIDATION_XML_FILE, new CloseIgnoringInputStream( in ) ); + String schemaVersion = xmlParserHelper.getSchemaVersion( VALIDATION_XML_FILE, xmlEventReader ); + xmlEventReader.close(); + + in.reset(); + + // The validation is done first as StAX builders used below are assuming that the XML file is correct and don't + // do any validation of the input. + Schema schema = getSchema( xmlParserHelper, schemaVersion ); + Validator validator = schema.newValidator(); + validator.validate( new StreamSource( new CloseIgnoringInputStream( in ) ) ); + + in.reset(); + + xmlEventReader = xmlParserHelper.createXmlEventReader( VALIDATION_XML_FILE, new CloseIgnoringInputStream( in ) ); + + ValidationConfigStaxBuilder validationConfigStaxBuilder = new ValidationConfigStaxBuilder( xmlEventReader ); + + xmlEventReader.close(); + in.reset(); + + return validationConfigStaxBuilder.build(); + } + catch (XMLStreamException | IOException | SAXException e) { + throw LOG.getUnableToParseValidationXmlFileException( VALIDATION_XML_FILE, e ); + } + finally { + run( SetContextClassLoader.action( previousTccl ) ); + closeStream( in ); + } + } + + private InputStream getValidationXmlInputStream() { + LOG.debugf( "Trying to load %s for XML based Validator configuration.", VALIDATION_XML_FILE ); + InputStream inputStream = ResourceLoaderHelper.getResettableInputStreamForPath( VALIDATION_XML_FILE, externalClassLoader ); + + if ( inputStream != null ) { + return inputStream; + } + else { + LOG.debugf( "No %s found. Using annotation based configuration only.", VALIDATION_XML_FILE ); + return null; + } + } + + private Schema getSchema(XmlParserHelper xmlParserHelper, String schemaVersion) { + String schemaResource = SCHEMAS_BY_VERSION.get( schemaVersion ); + + if ( schemaResource == null ) { + throw LOG.getUnsupportedSchemaVersionException( VALIDATION_XML_FILE, schemaVersion ); + } + + return xmlParserHelper.getSchema( schemaResource ); + } + + private void closeStream(InputStream inputStream) { + try { + inputStream.close(); + } + catch (IOException io) { + LOG.unableToCloseXMLFileInputStream( VALIDATION_XML_FILE ); + } + } + + /** + * Runs the given privileged action, using a privileged block if required. + *

+ * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary + * privileged actions within HV's protection domain. + */ + private static T run(PrivilegedAction action) { + return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); + } + +} From 50665fe87ca66fa207f047ca7bcaeb963feccb14 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Sat, 24 Mar 2018 18:27:16 +0100 Subject: [PATCH 003/393] HV-1577 Removed unused scriptEvaluatorFactoryClassName property --- .../internal/xml/config/BootstrapConfigurationImpl.java | 9 --------- .../internal/xml/config/ValidationConfigStaxBuilder.java | 2 -- 2 files changed, 11 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/config/BootstrapConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/xml/config/BootstrapConfigurationImpl.java index 57a7639e51..cf348967c7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/config/BootstrapConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/config/BootstrapConfigurationImpl.java @@ -57,7 +57,6 @@ class BootstrapConfigurationImpl implements BootstrapConfiguration { private final String traversableResolverClassName; private final String parameterNameProviderClassName; private final String clockProviderClassName; - private final String scriptEvaluatorFactoryClassName; private final Set valueExtractorClassNames; private final Set constraintMappingResourcePaths; private final Map properties; @@ -71,7 +70,6 @@ private BootstrapConfigurationImpl() { this.traversableResolverClassName = null; this.parameterNameProviderClassName = null; this.clockProviderClassName = null; - this.scriptEvaluatorFactoryClassName = null; this.valueExtractorClassNames = new HashSet<>(); this.validatedExecutableTypes = DEFAULT_VALIDATED_EXECUTABLE_TYPES; this.isExecutableValidationEnabled = true; @@ -85,7 +83,6 @@ public BootstrapConfigurationImpl(String defaultProviderClassName, String traversableResolverClassName, String parameterNameProviderClassName, String clockProviderClassName, - String scriptEvaluatorFactoryClassName, Set valueExtractorClassNames, EnumSet validatedExecutableTypes, boolean isExecutableValidationEnabled, @@ -97,7 +94,6 @@ public BootstrapConfigurationImpl(String defaultProviderClassName, this.traversableResolverClassName = traversableResolverClassName; this.parameterNameProviderClassName = parameterNameProviderClassName; this.clockProviderClassName = clockProviderClassName; - this.scriptEvaluatorFactoryClassName = scriptEvaluatorFactoryClassName; this.valueExtractorClassNames = valueExtractorClassNames; this.validatedExecutableTypes = prepareValidatedExecutableTypes( validatedExecutableTypes ); this.isExecutableValidationEnabled = isExecutableValidationEnabled; @@ -154,10 +150,6 @@ public String getClockProviderClassName() { return clockProviderClassName; } - public String getScriptEvaluatorFactoryClassName() { - return scriptEvaluatorFactoryClassName; - } - @Override public Set getValueExtractorClassNames() { return new HashSet<>( valueExtractorClassNames ); @@ -195,7 +187,6 @@ public String toString() { sb.append( ", traversableResolverClassName='" ).append( traversableResolverClassName ).append( '\'' ); sb.append( ", parameterNameProviderClassName='" ).append( parameterNameProviderClassName ).append( '\'' ); sb.append( ", clockProviderClassName='" ).append( clockProviderClassName ).append( '\'' ); - sb.append( ", scriptEvaluatorFactoryClassName='" ).append( scriptEvaluatorFactoryClassName ).append( '\'' ); sb.append( ", validatedExecutableTypes='" ).append( validatedExecutableTypes ).append( '\'' ); sb.append( ", constraintMappingResourcePaths=" ).append( constraintMappingResourcePaths ).append( '\'' ); sb.append( ", properties=" ).append( properties ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationConfigStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationConfigStaxBuilder.java index cce3774050..8ea287b9ee 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationConfigStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationConfigStaxBuilder.java @@ -22,7 +22,6 @@ import javax.xml.stream.events.StartElement; import javax.xml.stream.events.XMLEvent; -import org.hibernate.validator.HibernateValidatorConfiguration; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -96,7 +95,6 @@ public BootstrapConfiguration build() { simpleConfigurationsStaxBuilder.getTraversableResolver(), simpleConfigurationsStaxBuilder.getParameterNameProvider(), simpleConfigurationsStaxBuilder.getClockProvider(), - properties.get( HibernateValidatorConfiguration.SCRIPT_EVALUATOR_FACTORY_CLASSNAME ), valueExtractorsStaxBuilder.build(), executableValidationStaxBuilder.build(), executableValidationStaxBuilder.isEnabled(), From 6ed86fc3a3f9f9081eb6287935e3408540a88219 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Sat, 24 Mar 2018 23:05:40 +0100 Subject: [PATCH 004/393] HV-1577 Move from JAXB to Stax for XML mappings --- .../TypeConstraintMappingContextImpl.java | 4 +- .../provider/XmlMetaDataProvider.java | 2 +- .../validator/internal/util/logging/Log.java | 9 +- .../ArrayOfClassesObjectFormatter.java | 32 ++ .../xml/ConstrainedExecutableBuilder.java | 4 +- .../internal/xml/MappingXmlParser.java | 428 --------------- ...AbstractConstrainedElementStaxBuilder.java | 111 ++++ ...nstrainedExecutableElementStaxBuilder.java | 107 ++++ ...AbstractMultiValuedElementStaxBuilder.java | 64 +++ .../AbstractOneLineStringStaxBuilder.java | 35 ++ .../internal/xml/mapping/BeanStaxBuilder.java | 228 ++++++++ .../ClassConstraintTypeStaxBuilder.java | 142 +++++ .../xml/{ => mapping}/ClassLoadingHelper.java | 6 +- .../ConstrainedConstructorStaxBuilder.java | 138 +++++ .../mapping/ConstrainedFieldStaxBuilder.java | 116 ++++ .../mapping/ConstrainedGetterStaxBuilder.java | 123 +++++ .../mapping/ConstrainedMethodStaxBuilder.java | 143 +++++ .../ConstrainedParameterStaxBuilder.java | 102 ++++ .../ConstraintDefinitionStaxBuilder.java | 158 ++++++ .../ConstraintMappingsStaxBuilder.java | 96 ++++ .../mapping/ConstraintTypeStaxBuilder.java | 514 ++++++++++++++++++ ...tainerElementTypeConfigurationBuilder.java | 84 +++ .../ContainerElementTypePath.java | 2 +- .../ContainerElementTypeStaxBuilder.java | 220 ++++++++ .../mapping/CrossParameterStaxBuilder.java | 104 ++++ .../mapping/DefaultPackageStaxBuilder.java | 26 + .../mapping/GroupConversionStaxBuilder.java | 106 ++++ .../xml/mapping/MappingXmlParser.java | 163 ++++++ .../xml/mapping/ReturnValueStaxBuilder.java | 77 +++ .../xml/mapping/ValidStaxBuilder.java | 35 ++ .../internal/xml/MappingXmlParserTest.java | 2 +- 31 files changed, 2939 insertions(+), 442 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/util/logging/formatter/ArrayOfClassesObjectFormatter.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/MappingXmlParser.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractConstrainedElementStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractConstrainedExecutableElementStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractMultiValuedElementStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractOneLineStringStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/BeanStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassConstraintTypeStaxBuilder.java rename engine/src/main/java/org/hibernate/validator/internal/xml/{ => mapping}/ClassLoadingHelper.java (95%) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintDefinitionStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintMappingsStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintTypeStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypeConfigurationBuilder.java rename engine/src/main/java/org/hibernate/validator/internal/xml/{ => mapping}/ContainerElementTypePath.java (96%) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypeStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/DefaultPackageStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/GroupConversionStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ValidStaxBuilder.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java index 82a5403b26..a9037848ab 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java @@ -144,7 +144,7 @@ public MethodConstraintMappingContext method(String name, Class... parameterT Method method = run( GetDeclaredMethod.action( beanClass, name, parameterTypes ) ); if ( method == null || method.getDeclaringClass() != beanClass ) { - throw LOG.getBeanDoesNotContainMethodException( beanClass, name, Arrays.asList( parameterTypes ) ); + throw LOG.getBeanDoesNotContainMethodException( beanClass, name, parameterTypes ); } if ( configuredMembers.contains( method ) ) { @@ -168,7 +168,7 @@ public ConstructorConstraintMappingContext constructor(Class... parameterType if ( constructor == null || constructor.getDeclaringClass() != beanClass ) { throw LOG.getBeanDoesNotContainConstructorException( beanClass, - Arrays.asList( parameterTypes ) + parameterTypes ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlMetaDataProvider.java index bbfc102c7d..9cef432d79 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlMetaDataProvider.java @@ -20,7 +20,7 @@ import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.stereotypes.Immutable; -import org.hibernate.validator.internal.xml.MappingXmlParser; +import org.hibernate.validator.internal.xml.mapping.MappingXmlParser; /** * A {@link MetaDataProvider} providing constraint related meta data based on diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 4479ec69d2..5978c2b603 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -48,6 +48,7 @@ import org.hibernate.validator.internal.engine.messageinterpolation.parser.MessageDescriptorFormatException; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.util.logging.formatter.ArrayOfClassesObjectFormatter; import org.hibernate.validator.internal.util.logging.formatter.ClassObjectFormatter; import org.hibernate.validator.internal.util.logging.formatter.CollectionOfClassesObjectFormatter; import org.hibernate.validator.internal.util.logging.formatter.CollectionOfObjectsToStringFormatter; @@ -55,7 +56,7 @@ import org.hibernate.validator.internal.util.logging.formatter.ExecutableFormatter; import org.hibernate.validator.internal.util.logging.formatter.ObjectArrayFormatter; import org.hibernate.validator.internal.util.logging.formatter.TypeFormatter; -import org.hibernate.validator.internal.xml.ContainerElementTypePath; +import org.hibernate.validator.internal.xml.mapping.ContainerElementTypePath; import org.hibernate.validator.spi.scripting.ScriptEvaluationException; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; import org.hibernate.validator.spi.scripting.ScriptEvaluatorNotFoundException; @@ -379,7 +380,7 @@ RuntimeException getTryingToInstantiateAnnotationWithUnknownAttributesException( ValidationException getIsNotAConstraintValidatorClassException(@FormatWith(ClassObjectFormatter.class) Class validatorClass); @Message(id = 103, value = "%s is configured at least twice in xml.") - ValidationException getBeanClassHasAlreadyBeConfiguredInXmlException(@FormatWith(ClassObjectFormatter.class) Class beanClass); + ValidationException getBeanClassHasAlreadyBeenConfiguredInXmlException(@FormatWith(ClassObjectFormatter.class) Class beanClass); @Message(id = 104, value = "%1$s is defined twice in mapping xml for bean %2$s.") ValidationException getIsDefinedTwiceInMappingXmlForBeanException(String name, @FormatWith(ClassObjectFormatter.class) Class beanClass); @@ -468,14 +469,14 @@ ConstraintDeclarationException getMultipleGroupConversionsForSameSourceException @Message(id = 133, value = "%1$s does not contain a constructor with the parameter types %2$s.") ValidationException getBeanDoesNotContainConstructorException(@FormatWith(ClassObjectFormatter.class) Class beanClass, - @FormatWith(CollectionOfClassesObjectFormatter.class) List> parameterTypes); + @FormatWith(ArrayOfClassesObjectFormatter.class) Class[] parameterTypes); @Message(id = 134, value = "Unable to load parameter of type '%1$s' in %2$s.") ValidationException getInvalidParameterTypeException(String type, @FormatWith(ClassObjectFormatter.class) Class beanClass); @Message(id = 135, value = "%1$s does not contain a method with the name '%2$s' and parameter types %3$s.") ValidationException getBeanDoesNotContainMethodException(@FormatWith(ClassObjectFormatter.class) Class beanClass, String methodName, - @FormatWith(CollectionOfClassesObjectFormatter.class) List> parameterTypes); + @FormatWith(ArrayOfClassesObjectFormatter.class) Class[] parameterTypes); @Message(id = 136, value = "The specified constraint annotation class %1$s cannot be loaded.") ValidationException getUnableToLoadConstraintAnnotationClassException(String constraintAnnotationClassName, @Cause Exception e); diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/formatter/ArrayOfClassesObjectFormatter.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/formatter/ArrayOfClassesObjectFormatter.java new file mode 100644 index 0000000000..9399bf630c --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/formatter/ArrayOfClassesObjectFormatter.java @@ -0,0 +1,32 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.util.logging.formatter; + +import java.util.Arrays; +import java.util.stream.Collectors; + +/** + * Used with JBoss Logging to display array of class names in log messages. + * + * @author Guillaume Smet + * @author Marko Bekhta + */ +public class ArrayOfClassesObjectFormatter { + + private final String stringRepresentation; + + public ArrayOfClassesObjectFormatter(Class[] classes) { + this.stringRepresentation = Arrays.stream( classes ) + .map( c -> c.getName() ) + .collect( Collectors.joining( ", " ) ); + } + + @Override + public String toString() { + return stringRepresentation; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedExecutableBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedExecutableBuilder.java index 382abe3206..8bad5a9511 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedExecutableBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedExecutableBuilder.java @@ -102,7 +102,7 @@ Set buildMethodConstrainedExecutable(List met throw LOG.getBeanDoesNotContainMethodException( beanClass, methodName, - parameterTypes + parameterTypes.toArray( new Class[parameterTypes.size()] ) ); } @@ -157,7 +157,7 @@ Set buildConstructorConstrainedExecutable(List. - */ -package org.hibernate.validator.internal.xml; - -import static org.hibernate.validator.internal.util.CollectionHelper.newHashMap; -import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.annotation.Annotation; -import java.lang.invoke.MethodHandles; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedExceptionAction; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.validation.ConstraintValidator; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLStreamException; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.Validator; - -import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorDescriptor; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions; -import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; -import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; -import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; -import org.hibernate.validator.internal.metadata.raw.ConstrainedField; -import org.hibernate.validator.internal.metadata.raw.ConstrainedType; -import org.hibernate.validator.internal.util.TypeResolutionHelper; -import org.hibernate.validator.internal.util.logging.Log; -import org.hibernate.validator.internal.util.logging.LoggerFactory; -import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader; -import org.hibernate.validator.internal.util.privilegedactions.NewJaxbContext; -import org.hibernate.validator.internal.util.privilegedactions.SetContextClassLoader; -import org.hibernate.validator.internal.util.privilegedactions.Unmarshal; -import org.hibernate.validator.internal.xml.binding.BeanType; -import org.hibernate.validator.internal.xml.binding.ConstraintDefinitionType; -import org.hibernate.validator.internal.xml.binding.ConstraintMappingsType; -import org.hibernate.validator.internal.xml.binding.ValidatedByType; -import org.xml.sax.SAXException; - -/** - * XML parser for validation-mapping files. - * - * @author Hardy Ferentschik - */ -public class MappingXmlParser { - - private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - - private final Set> processedClasses = newHashSet(); - private final ConstraintHelper constraintHelper; - private final TypeResolutionHelper typeResolutionHelper; - private final ValueExtractorManager valueExtractorManager; - private final AnnotationProcessingOptionsImpl annotationProcessingOptions; - private final Map, List>> defaultSequences; - private final Map, Set> constrainedElements; - - private final XmlParserHelper xmlParserHelper; - - private final ClassLoadingHelper classLoadingHelper; - - private static final Map SCHEMAS_BY_VERSION = Collections.unmodifiableMap( getSchemasByVersion() ); - - private static Map getSchemasByVersion() { - Map schemasByVersion = new HashMap<>(); - - schemasByVersion.put( "1.0", "META-INF/validation-mapping-1.0.xsd" ); - schemasByVersion.put( "1.1", "META-INF/validation-mapping-1.1.xsd" ); - schemasByVersion.put( "2.0", "META-INF/validation-mapping-2.0.xsd" ); - - return schemasByVersion; - } - - public MappingXmlParser(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, - ClassLoader externalClassLoader) { - this.constraintHelper = constraintHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; - this.annotationProcessingOptions = new AnnotationProcessingOptionsImpl(); - this.defaultSequences = newHashMap(); - this.constrainedElements = newHashMap(); - this.xmlParserHelper = new XmlParserHelper(); - this.classLoadingHelper = new ClassLoadingHelper( externalClassLoader ); - } - - /** - * Parses the given set of input stream representing XML constraint - * mappings. - * - * @param mappingStreams The streams to parse. Must support the mark/reset contract. - */ - public final void parse(Set mappingStreams) { - try { - // JAXBContext#newInstance() requires several permissions internally and doesn't use any privileged blocks - // itself; Wrapping it here avoids that all calling code bases need to have these permissions as well - JAXBContext jc = run( NewJaxbContext.action( ConstraintMappingsType.class ) ); - - MetaConstraintBuilder metaConstraintBuilder = new MetaConstraintBuilder( - classLoadingHelper, - constraintHelper, - typeResolutionHelper, - valueExtractorManager - ); - GroupConversionBuilder groupConversionBuilder = new GroupConversionBuilder( classLoadingHelper ); - - ConstrainedTypeBuilder constrainedTypeBuilder = new ConstrainedTypeBuilder( - classLoadingHelper, - metaConstraintBuilder, - annotationProcessingOptions, - defaultSequences - ); - ConstrainedFieldBuilder constrainedFieldBuilder = new ConstrainedFieldBuilder( - metaConstraintBuilder, - groupConversionBuilder, - annotationProcessingOptions - ); - ConstrainedExecutableBuilder constrainedExecutableBuilder = new ConstrainedExecutableBuilder( - classLoadingHelper, - metaConstraintBuilder, - groupConversionBuilder, - annotationProcessingOptions - ); - ConstrainedGetterBuilder constrainedGetterBuilder = new ConstrainedGetterBuilder( - metaConstraintBuilder, - groupConversionBuilder, - annotationProcessingOptions - ); - - Set alreadyProcessedConstraintDefinitions = newHashSet(); - for ( InputStream in : mappingStreams ) { - ConstraintMappingsType mapping = unmarshal( jc, in ); - String defaultPackage = mapping.getDefaultPackage(); - - parseConstraintDefinitions( - mapping.getConstraintDefinition(), - defaultPackage, - alreadyProcessedConstraintDefinitions - ); - - for ( BeanType bean : mapping.getBean() ) { - processBeanType( - constrainedTypeBuilder, - constrainedFieldBuilder, - constrainedExecutableBuilder, - constrainedGetterBuilder, - defaultPackage, - bean - ); - } - - in.reset(); - } - } - catch (JAXBException | SAXException | IOException | XMLStreamException e) { - throw LOG.getErrorParsingMappingFileException( e ); - } - } - - private ConstraintMappingsType unmarshal(JAXBContext jc, InputStream in) throws JAXBException, XMLStreamException, IOException, SAXException { - ClassLoader previousTccl = run( GetClassLoader.fromContext() ); - - try { - run( SetContextClassLoader.action( MappingXmlParser.class.getClassLoader() ) ); - - // the InputStreams passed in parameters support mark and reset - in.mark( Integer.MAX_VALUE ); - - XMLEventReader xmlEventReader = xmlParserHelper.createXmlEventReader( "constraint mapping file", new CloseIgnoringInputStream( in ) ); - String schemaVersion = xmlParserHelper.getSchemaVersion( "constraint mapping file", xmlEventReader ); - xmlEventReader.close(); - - in.reset(); - - // The validation is done first as we manipulate the XML document before pushing it to the unmarshaller - // and it might not be valid anymore as we might have switched the namespace to the latest namespace - // supported. - String schemaResourceName = getSchemaResourceName( schemaVersion ); - Schema schema = xmlParserHelper.getSchema( schemaResourceName ); - Validator validator = schema.newValidator(); - validator.validate( new StreamSource( new CloseIgnoringInputStream( in ) ) ); - - in.reset(); - - xmlEventReader = xmlParserHelper.createXmlEventReader( "constraint mapping file", new CloseIgnoringInputStream( in ) ); - Unmarshaller unmarshaller = jc.createUnmarshaller(); - ConstraintMappingsType mapping = getValidationConfig( xmlEventReader, unmarshaller ); - xmlEventReader.close(); - - return mapping; - } - finally { - run( SetContextClassLoader.action( previousTccl ) ); - } - } - - public final Set> getXmlConfiguredClasses() { - return processedClasses; - } - - public final AnnotationProcessingOptions getAnnotationProcessingOptions() { - return annotationProcessingOptions; - } - - public final Set getConstrainedElementsForClass(Class beanClass) { - if ( constrainedElements.containsKey( beanClass ) ) { - return constrainedElements.get( beanClass ); - } - else { - return Collections.emptySet(); - } - } - - public final List> getDefaultSequenceForClass(Class beanClass) { - return defaultSequences.get( beanClass ); - } - - private void processBeanType(ConstrainedTypeBuilder constrainedTypeBuilder, ConstrainedFieldBuilder constrainedFieldBuilder, ConstrainedExecutableBuilder constrainedExecutableBuilder, ConstrainedGetterBuilder constrainedGetterBuilder, String defaultPackage, BeanType bean) { - Class beanClass = classLoadingHelper.loadClass( bean.getClazz(), defaultPackage ); - checkClassHasNotBeenProcessed( processedClasses, beanClass ); - - // update annotation ignores - annotationProcessingOptions.ignoreAnnotationConstraintForClass( - beanClass, - bean.getIgnoreAnnotations() - ); - - ConstrainedType constrainedType = constrainedTypeBuilder.buildConstrainedType( - bean.getClassType(), - beanClass, - defaultPackage - ); - if ( constrainedType != null ) { - addConstrainedElement( beanClass, constrainedType ); - } - - Set constrainedFields = constrainedFieldBuilder.buildConstrainedFields( - bean.getField(), - beanClass, - defaultPackage - ); - addConstrainedElements( beanClass, constrainedFields ); - - Set constrainedGetters = constrainedGetterBuilder.buildConstrainedGetters( - bean.getGetter(), - beanClass, - defaultPackage - - ); - addConstrainedElements( beanClass, constrainedGetters ); - - Set constrainedConstructors = constrainedExecutableBuilder.buildConstructorConstrainedExecutable( - bean.getConstructor(), - beanClass, - defaultPackage - ); - addConstrainedElements( beanClass, constrainedConstructors ); - - Set constrainedMethods = constrainedExecutableBuilder.buildMethodConstrainedExecutable( - bean.getMethod(), - beanClass, - defaultPackage - ); - addConstrainedElements( beanClass, constrainedMethods ); - - processedClasses.add( beanClass ); - } - - @SuppressWarnings("unchecked") - private void parseConstraintDefinitions(List constraintDefinitionList, - String defaultPackage, - Set alreadyProcessedConstraintDefinitions) { - for ( ConstraintDefinitionType constraintDefinition : constraintDefinitionList ) { - String annotationClassName = constraintDefinition.getAnnotation(); - if ( alreadyProcessedConstraintDefinitions.contains( annotationClassName ) ) { - throw LOG.getOverridingConstraintDefinitionsInMultipleMappingFilesException( annotationClassName ); - } - else { - alreadyProcessedConstraintDefinitions.add( annotationClassName ); - } - - Class clazz = classLoadingHelper.loadClass( annotationClassName, defaultPackage ); - if ( !clazz.isAnnotation() ) { - throw LOG.getIsNotAnAnnotationException( clazz ); - } - Class annotationClass = (Class) clazz; - - addValidatorDefinitions( annotationClass, defaultPackage, constraintDefinition.getValidatedBy() ); - } - } - - private void addValidatorDefinitions(Class annotationClass, String defaultPackage, - ValidatedByType validatedByType) { - List> constraintValidatorDescriptors = new ArrayList<>( validatedByType.getValue().size() ); - - for ( String validatorClassName : validatedByType.getValue() ) { - @SuppressWarnings("unchecked") - Class> validatorClass = (Class>) classLoadingHelper - .loadClass( validatorClassName, defaultPackage ); - - if ( !ConstraintValidator.class.isAssignableFrom( validatorClass ) ) { - throw LOG.getIsNotAConstraintValidatorClassException( validatorClass ); - } - - constraintValidatorDescriptors.add( ConstraintValidatorDescriptor.forClass( validatorClass ) ); - } - constraintHelper.putValidatorDescriptors( - annotationClass, - constraintValidatorDescriptors, - Boolean.TRUE.equals( validatedByType.getIncludeExistingValidators() ) - ); - } - - private void checkClassHasNotBeenProcessed(Set> processedClasses, Class beanClass) { - if ( processedClasses.contains( beanClass ) ) { - throw LOG.getBeanClassHasAlreadyBeConfiguredInXmlException( beanClass ); - } - } - - private void addConstrainedElement(Class beanClass, ConstrainedElement constrainedElement) { - if ( constrainedElements.containsKey( beanClass ) ) { - constrainedElements.get( beanClass ).add( constrainedElement ); - } - else { - Set tmpList = newHashSet(); - tmpList.add( constrainedElement ); - constrainedElements.put( beanClass, tmpList ); - } - } - - private void addConstrainedElements(Class beanClass, Set newConstrainedElements) { - if ( constrainedElements.containsKey( beanClass ) ) { - - Set existingConstrainedElements = constrainedElements.get( beanClass ); - - for ( ConstrainedElement constrainedElement : newConstrainedElements ) { - if ( existingConstrainedElements.contains( constrainedElement ) ) { - throw LOG.getConstrainedElementConfiguredMultipleTimesException( - constrainedElement.toString() - ); - } - } - - existingConstrainedElements.addAll( newConstrainedElements ); - } - else { - Set tmpSet = newHashSet(); - tmpSet.addAll( newConstrainedElements ); - constrainedElements.put( beanClass, tmpSet ); - } - } - - private ConstraintMappingsType getValidationConfig(XMLEventReader xmlEventReader, Unmarshaller unmarshaller) { - ConstraintMappingsType constraintMappings; - try { - // Unmashaller#unmarshal() requires several permissions internally and doesn't use any privileged blocks - // itself; Wrapping it here avoids that all calling code bases need to have these permissions as well - JAXBElement root = run( - Unmarshal.action( - unmarshaller, - xmlEventReader, - ConstraintMappingsType.class - ) - ); - constraintMappings = root.getValue(); - } - catch (Exception e) { - throw LOG.getErrorParsingMappingFileException( e ); - } - return constraintMappings; - } - - private String getSchemaResourceName(String schemaVersion) { - String schemaResource = SCHEMAS_BY_VERSION.get( schemaVersion ); - - if ( schemaResource == null ) { - throw LOG.getUnsupportedSchemaVersionException( "constraint mapping file", schemaVersion ); - } - - return schemaResource; - } - - /** - * Runs the given privileged action, using a privileged block if required. - *

- * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary - * privileged actions within HV's protection domain. - */ - private static T run(PrivilegedAction action) { - return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); - } - - /** - * Runs the given privileged action, using a privileged block if required. - *

- * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary - * privileged actions within HV's protection domain. - */ - private T run(PrivilegedExceptionAction action) throws JAXBException { - try { - return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); - } - catch (JAXBException e) { - throw e; - } - catch (Exception e) { - throw LOG.getErrorParsingMappingFileException( e ); - } - } - -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractConstrainedElementStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractConstrainedElementStaxBuilder.java new file mode 100644 index 0000000000..4791436852 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractConstrainedElementStaxBuilder.java @@ -0,0 +1,111 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.xml.AbstractStaxBuilder; +import org.hibernate.validator.internal.xml.mapping.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; + +/** + * Base builder for all constrained element builders that can have constraints or type argument constraints. + * + * @author Marko Bekhta + */ +abstract class AbstractConstrainedElementStaxBuilder extends AbstractStaxBuilder { + + private static final QName IGNORE_ANNOTATIONS_QNAME = new QName( "ignore-annotations" ); + + protected final ClassLoadingHelper classLoadingHelper; + protected final ConstraintHelper constraintHelper; + protected final TypeResolutionHelper typeResolutionHelper; + protected final ValueExtractorManager valueExtractorManager; + protected final DefaultPackageStaxBuilder defaultPackageStaxBuilder; + protected final AnnotationProcessingOptionsImpl annotationProcessingOptions; + + protected String mainAttributeValue; + protected Optional ignoreAnnotations; + protected final GroupConversionStaxBuilder groupConversionBuilder; + protected final ValidStaxBuilder validStaxBuilder; + protected final List constraintTypeStaxBuilders; + protected final ContainerElementTypeConfigurationBuilder containerElementTypeConfigurationBuilder; + + AbstractConstrainedElementStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, + TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions) { + this.classLoadingHelper = classLoadingHelper; + this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; + this.constraintHelper = constraintHelper; + this.typeResolutionHelper = typeResolutionHelper; + this.valueExtractorManager = valueExtractorManager; + + this.groupConversionBuilder = new GroupConversionStaxBuilder( classLoadingHelper, defaultPackageStaxBuilder ); + this.validStaxBuilder = new ValidStaxBuilder(); + this.containerElementTypeConfigurationBuilder = new ContainerElementTypeConfigurationBuilder(); + this.annotationProcessingOptions = annotationProcessingOptions; + + this.constraintTypeStaxBuilders = new ArrayList<>(); + } + + abstract Optional getMainAttributeValueQname(); + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + Optional mainAttributeValueQname = getMainAttributeValueQname(); + if ( mainAttributeValueQname.isPresent() ) { + mainAttributeValue = readAttribute( xmlEvent.asStartElement(), mainAttributeValueQname.get() ).get(); + } + ignoreAnnotations = readAttribute( xmlEvent.asStartElement(), IGNORE_ANNOTATIONS_QNAME ).map( Boolean::parseBoolean ); + ConstraintTypeStaxBuilder constraintTypeStaxBuilder = getNewConstraintTypeStaxBuilder(); + ContainerElementTypeStaxBuilder containerElementTypeStaxBuilder = getNewContainerElementTypeStaxBuilder(); + while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( getAcceptableQName() ) ) ) { + xmlEvent = xmlEventReader.nextEvent(); + validStaxBuilder.process( xmlEventReader, xmlEvent ); + groupConversionBuilder.process( xmlEventReader, xmlEvent ); + if ( constraintTypeStaxBuilder.process( xmlEventReader, xmlEvent ) ) { + constraintTypeStaxBuilders.add( constraintTypeStaxBuilder ); + constraintTypeStaxBuilder = getNewConstraintTypeStaxBuilder(); + } + if ( containerElementTypeStaxBuilder.process( xmlEventReader, xmlEvent ) ) { + containerElementTypeConfigurationBuilder.add( containerElementTypeStaxBuilder ); + containerElementTypeStaxBuilder = getNewContainerElementTypeStaxBuilder(); + } + } + } + + private ConstraintTypeStaxBuilder getNewConstraintTypeStaxBuilder() { + return new ConstraintTypeStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder ); + } + + private ContainerElementTypeStaxBuilder getNewContainerElementTypeStaxBuilder() { + return new ContainerElementTypeStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder ); + } + + protected ContainerElementTypeConfiguration getContainerElementTypeConfiguration(Type type, ConstraintLocation constraintLocation) { + return containerElementTypeConfigurationBuilder.build( constraintLocation, type ); + } + + protected CascadingMetaDataBuilder getCascadingMetaData(Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaData, Type type) { + return CascadingMetaDataBuilder.annotatedObject( type, validStaxBuilder.build(), containerElementTypesCascadingMetaData, groupConversionBuilder.build() ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractConstrainedExecutableElementStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractConstrainedExecutableElementStaxBuilder.java new file mode 100644 index 0000000000..c466e28fec --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractConstrainedExecutableElementStaxBuilder.java @@ -0,0 +1,107 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.xml.AbstractStaxBuilder; + +/** + * A base builder for constraint executables. Provides read logic only. Build logic should be added in implementations. + * + * @author Marko Bekhta + */ +abstract class AbstractConstrainedExecutableElementStaxBuilder extends AbstractStaxBuilder { + + private static final QName IGNORE_ANNOTATIONS_QNAME = new QName( "ignore-annotations" ); + + protected final ClassLoadingHelper classLoadingHelper; + protected final ConstraintHelper constraintHelper; + protected final TypeResolutionHelper typeResolutionHelper; + protected final ValueExtractorManager valueExtractorManager; + protected final DefaultPackageStaxBuilder defaultPackageStaxBuilder; + protected final AnnotationProcessingOptionsImpl annotationProcessingOptions; + + protected String mainAttributeValue; + protected Optional ignoreAnnotations; + protected final List constrainedParameterStaxBuilders; + private CrossParameterStaxBuilder crossParameterStaxBuilder; + private ReturnValueStaxBuilder returnValueStaxBuilder; + + AbstractConstrainedExecutableElementStaxBuilder( + ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, + TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions) { + this.classLoadingHelper = classLoadingHelper; + this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; + this.constraintHelper = constraintHelper; + this.typeResolutionHelper = typeResolutionHelper; + this.valueExtractorManager = valueExtractorManager; + + this.annotationProcessingOptions = annotationProcessingOptions; + + this.constrainedParameterStaxBuilders = new ArrayList<>(); + } + + abstract Optional getMainAttributeValueQname(); + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + Optional mainAttributeValueQname = getMainAttributeValueQname(); + if ( mainAttributeValueQname.isPresent() ) { + mainAttributeValue = readAttribute( xmlEvent.asStartElement(), mainAttributeValueQname.get() ).get(); + } + ignoreAnnotations = readAttribute( xmlEvent.asStartElement(), IGNORE_ANNOTATIONS_QNAME ).map( Boolean::parseBoolean ); + ConstrainedParameterStaxBuilder constrainedParameterStaxBuilder = getNewConstrainedParameterStaxBuilder(); + ReturnValueStaxBuilder localReturnValueStaxBuilder = getNewReturnValueStaxBuilder(); + CrossParameterStaxBuilder localCrossParameterStaxBuilder = getNewCrossParameterStaxBuilder(); + while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( getAcceptableQName() ) ) ) { + xmlEvent = xmlEventReader.nextEvent(); + if ( constrainedParameterStaxBuilder.process( xmlEventReader, xmlEvent ) ) { + constrainedParameterStaxBuilders.add( constrainedParameterStaxBuilder ); + constrainedParameterStaxBuilder = getNewConstrainedParameterStaxBuilder(); + } + else if ( localReturnValueStaxBuilder.process( xmlEventReader, xmlEvent ) ) { + this.returnValueStaxBuilder = localReturnValueStaxBuilder; + } + else if ( localCrossParameterStaxBuilder.process( xmlEventReader, xmlEvent ) ) { + this.crossParameterStaxBuilder = localCrossParameterStaxBuilder; + } + } + } + + private ConstrainedParameterStaxBuilder getNewConstrainedParameterStaxBuilder() { + return new ConstrainedParameterStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + } + + private CrossParameterStaxBuilder getNewCrossParameterStaxBuilder() { + return new CrossParameterStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + } + + private ReturnValueStaxBuilder getNewReturnValueStaxBuilder() { + return new ReturnValueStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + } + + public Optional getReturnValueStaxBuilder() { + return Optional.ofNullable( returnValueStaxBuilder ); + } + + public Optional getCrossParameterStaxBuilder() { + return Optional.ofNullable( crossParameterStaxBuilder ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractMultiValuedElementStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractMultiValuedElementStaxBuilder.java new file mode 100644 index 0000000000..f284261417 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractMultiValuedElementStaxBuilder.java @@ -0,0 +1,64 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import org.hibernate.validator.internal.xml.AbstractStaxBuilder; + +/** + * An abstract builder for an element that could have multiple {@code ... } entries. + * + * @author Marko Bekhta + */ +abstract class AbstractMultiValuedElementStaxBuilder extends AbstractStaxBuilder { + + private static final String VALUE_QNAME_LOCAL_PART = "value"; + + private static final Class[] EMPTY_CLASSES_ARRAY = new Class[0]; + + private final ClassLoadingHelper classLoadingHelper; + private final DefaultPackageStaxBuilder defaultPackageStaxBuilder; + + private final List values; + + protected AbstractMultiValuedElementStaxBuilder(ClassLoadingHelper classLoadingHelper, DefaultPackageStaxBuilder defaultPackageStaxBuilder) { + this.classLoadingHelper = classLoadingHelper; + this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; + + this.values = new ArrayList<>(); + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( getAcceptableQName() ) ) ) { + xmlEvent = xmlEventReader.nextEvent(); + if ( xmlEvent.isStartElement() && xmlEvent.asStartElement().getName().getLocalPart().equals( VALUE_QNAME_LOCAL_PART ) ) { + values.add( readSingleElement( xmlEventReader ) ); + } + } + } + + public Class[] build() { + String defaultPackage = defaultPackageStaxBuilder.build().orElse( "" ); + if ( values.isEmpty() ) { + return EMPTY_CLASSES_ARRAY; + } + + return values.stream() + .map( valueClass -> classLoadingHelper.loadClass( valueClass, defaultPackage ) ) + .peek( this::verifyClass ) + .toArray( Class[]::new ); + } + + public abstract void verifyClass(Class clazz); +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractOneLineStringStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractOneLineStringStaxBuilder.java new file mode 100644 index 0000000000..762872b093 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractOneLineStringStaxBuilder.java @@ -0,0 +1,35 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.util.Optional; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import org.hibernate.validator.internal.xml.AbstractStaxBuilder; + +/** + * An abstract builder to be used for reading simple string element that can + * occur only once in a given block, e.g. {@code } or {@code }. + * + * @author Marko Bekhta + */ +abstract class AbstractOneLineStringStaxBuilder extends AbstractStaxBuilder { + + private String value; + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + this.value = readSingleElement( xmlEventReader ); + } + + public Optional build() { + return Optional.ofNullable( value ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/BeanStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/BeanStaxBuilder.java new file mode 100644 index 0000000000..e551a46485 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/BeanStaxBuilder.java @@ -0,0 +1,228 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; + +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.internal.xml.AbstractStaxBuilder; + +/** + * Builder for definition of all bean constraints. + * + * @author Marko Bekhta + */ +class BeanStaxBuilder extends AbstractStaxBuilder { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + private static final QName IGNORE_ANNOTATIONS_QNAME = new QName( "ignore-annotations" ); + private static final QName CLASS_QNAME = new QName( "class" ); + private static final String BEAN_QNAME_LOCAL_PART = "bean"; + + private final ClassLoadingHelper classLoadingHelper; + private final ConstraintHelper constraintHelper; + private final TypeResolutionHelper typeResolutionHelper; + private final ValueExtractorManager valueExtractorManager; + private final DefaultPackageStaxBuilder defaultPackageStaxBuilder; + private final AnnotationProcessingOptionsImpl annotationProcessingOptions; + private final Map, List>> defaultSequences; + + protected String className; + protected Optional ignoreAnnotations; + private ClassConstraintTypeStaxBuilder classConstraintTypeStaxBuilder; + private final List constrainedFieldStaxBuilders; + private final List constrainedGetterStaxBuilders; + private final List constrainedMethodStaxBuilders; + private final List constrainedConstructorStaxBuilders; + + BeanStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, + TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions, + Map, List>> defaultSequences) { + this.classLoadingHelper = classLoadingHelper; + this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; + this.constraintHelper = constraintHelper; + this.typeResolutionHelper = typeResolutionHelper; + this.valueExtractorManager = valueExtractorManager; + + this.annotationProcessingOptions = annotationProcessingOptions; + this.defaultSequences = defaultSequences; + + this.constrainedFieldStaxBuilders = new ArrayList<>(); + this.constrainedGetterStaxBuilders = new ArrayList<>(); + this.constrainedMethodStaxBuilders = new ArrayList<>(); + this.constrainedConstructorStaxBuilders = new ArrayList<>(); + } + + @Override + protected String getAcceptableQName() { + return BEAN_QNAME_LOCAL_PART; + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + this.className = readAttribute( xmlEvent.asStartElement(), CLASS_QNAME ).get(); + this.ignoreAnnotations = readAttribute( xmlEvent.asStartElement(), IGNORE_ANNOTATIONS_QNAME ).map( Boolean::parseBoolean ); + ConstrainedFieldStaxBuilder fieldStaxBuilder = getNewConstrainedFieldStaxBuilder(); + ConstrainedGetterStaxBuilder getterStaxBuilder = getNewConstrainedGetterStaxBuilder(); + ConstrainedMethodStaxBuilder methodStaxBuilder = getNewConstrainedMethodStaxBuilder(); + ConstrainedConstructorStaxBuilder constructorStaxBuilder = getNewConstrainedConstructorStaxBuilder(); + + ClassConstraintTypeStaxBuilder localClassConstraintTypeStaxBuilder = new ClassConstraintTypeStaxBuilder( + classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, + defaultPackageStaxBuilder, annotationProcessingOptions, defaultSequences + ); + while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( getAcceptableQName() ) ) ) { + xmlEvent = xmlEventReader.nextEvent(); + if ( fieldStaxBuilder.process( xmlEventReader, xmlEvent ) ) { + constrainedFieldStaxBuilders.add( fieldStaxBuilder ); + fieldStaxBuilder = getNewConstrainedFieldStaxBuilder(); + } + else if ( getterStaxBuilder.process( xmlEventReader, xmlEvent ) ) { + constrainedGetterStaxBuilders.add( getterStaxBuilder ); + getterStaxBuilder = getNewConstrainedGetterStaxBuilder(); + } + else if ( methodStaxBuilder.process( xmlEventReader, xmlEvent ) ) { + constrainedMethodStaxBuilders.add( methodStaxBuilder ); + methodStaxBuilder = getNewConstrainedMethodStaxBuilder(); + } + else if ( constructorStaxBuilder.process( xmlEventReader, xmlEvent ) ) { + constrainedConstructorStaxBuilders.add( constructorStaxBuilder ); + constructorStaxBuilder = getNewConstrainedConstructorStaxBuilder(); + } + else if ( localClassConstraintTypeStaxBuilder.process( xmlEventReader, xmlEvent ) ) { + classConstraintTypeStaxBuilder = localClassConstraintTypeStaxBuilder; + } + } + } + + private ConstrainedFieldStaxBuilder getNewConstrainedFieldStaxBuilder() { + return new ConstrainedFieldStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + } + + private ConstrainedGetterStaxBuilder getNewConstrainedGetterStaxBuilder() { + return new ConstrainedGetterStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + } + + private ConstrainedMethodStaxBuilder getNewConstrainedMethodStaxBuilder() { + return new ConstrainedMethodStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + } + + private ConstrainedConstructorStaxBuilder getNewConstrainedConstructorStaxBuilder() { + return new ConstrainedConstructorStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + } + + void build(Set> processedClasses, Map, Set> constrainedElementsByType) { + Class beanClass = classLoadingHelper.loadClass( className, defaultPackageStaxBuilder.build().orElse( "" ) ); + + checkClassHasNotBeenProcessed( processedClasses, beanClass ); + + // update annotation ignores + // NOTE: if there was no ignoreAnnotations attribute specified on a bean + // we use `true` as a default + annotationProcessingOptions.ignoreAnnotationConstraintForClass( + beanClass, + ignoreAnnotations.orElse( true ) + ); + + if ( classConstraintTypeStaxBuilder != null ) { + addConstrainedElements( + constrainedElementsByType, + beanClass, + Collections.singleton( classConstraintTypeStaxBuilder.build( beanClass ) ) + ); + } + + List alreadyProcessedFieldNames = new ArrayList<>( constrainedFieldStaxBuilders.size() ); + addConstrainedElements( + constrainedElementsByType, + beanClass, constrainedFieldStaxBuilders.stream() + .map( builder -> builder.build( beanClass, alreadyProcessedFieldNames ) ) + .collect( Collectors.toList() ) + ); + + List alreadyProcessedGetterNames = new ArrayList<>( constrainedGetterStaxBuilders.size() ); + addConstrainedElements( + constrainedElementsByType, + beanClass, + constrainedGetterStaxBuilders.stream() + .map( builder -> builder.build( beanClass, alreadyProcessedGetterNames ) ) + .collect( Collectors.toList() ) + ); + + List alreadyProcessedMethods = new ArrayList<>( constrainedMethodStaxBuilders.size() ); + addConstrainedElements( + constrainedElementsByType, + beanClass, + constrainedMethodStaxBuilders.stream() + .map( builder -> builder.build( beanClass, alreadyProcessedMethods ) ) + .collect( Collectors.toList() ) + ); + + List> alreadyProcessedConstructors = new ArrayList<>( constrainedConstructorStaxBuilders.size() ); + addConstrainedElements( + constrainedElementsByType, + beanClass, + constrainedConstructorStaxBuilders.stream() + .map( builder -> builder.build( beanClass, alreadyProcessedConstructors ) ) + .collect( Collectors.toList() ) + ); + } + + private void addConstrainedElements(Map, Set> constrainedElementsbyType, Class beanClass, Collection newConstrainedElements) { + if ( constrainedElementsbyType.containsKey( beanClass ) ) { + + Set existingConstrainedElements = constrainedElementsbyType.get( beanClass ); + + for ( ConstrainedElement constrainedElement : newConstrainedElements ) { + if ( existingConstrainedElements.contains( constrainedElement ) ) { + throw LOG.getConstrainedElementConfiguredMultipleTimesException( + constrainedElement.toString() + ); + } + } + + existingConstrainedElements.addAll( newConstrainedElements ); + } + else { + Set tmpSet = newHashSet(); + tmpSet.addAll( newConstrainedElements ); + constrainedElementsbyType.put( beanClass, tmpSet ); + } + } + + private void checkClassHasNotBeenProcessed(Set> processedClasses, Class beanClass) { + if ( processedClasses.contains( beanClass ) ) { + throw LOG.getBeanClassHasAlreadyBeenConfiguredInXmlException( beanClass ); + } + processedClasses.add( beanClass ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassConstraintTypeStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassConstraintTypeStaxBuilder.java new file mode 100644 index 0000000000..c75a851b14 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassConstraintTypeStaxBuilder.java @@ -0,0 +1,142 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; +import org.hibernate.validator.internal.metadata.raw.ConstrainedType; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.xml.AbstractStaxBuilder; + +/** + * Builder for class level constraints. + * + * @author Marko Bekhta + */ +class ClassConstraintTypeStaxBuilder extends AbstractStaxBuilder { + + private static final String CLASS_QNAME_LOCAL_PART = "class"; + private static final QName IGNORE_ANNOTATIONS_QNAME = new QName( "ignore-annotations" ); + + private final ClassLoadingHelper classLoadingHelper; + private final ConstraintHelper constraintHelper; + private final TypeResolutionHelper typeResolutionHelper; + private final ValueExtractorManager valueExtractorManager; + private final DefaultPackageStaxBuilder defaultPackageStaxBuilder; + private final AnnotationProcessingOptionsImpl annotationProcessingOptions; + private final Map, List>> defaultSequences; + + private Optional ignoreAnnotations; + private final List constraintTypeStaxBuilders; + private final GroupSequenceStaxBuilder groupSequenceStaxBuilder; + + ClassConstraintTypeStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, + TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions, + Map, List>> defaultSequences) { + this.classLoadingHelper = classLoadingHelper; + this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; + this.constraintHelper = constraintHelper; + this.typeResolutionHelper = typeResolutionHelper; + this.valueExtractorManager = valueExtractorManager; + + this.annotationProcessingOptions = annotationProcessingOptions; + this.defaultSequences = defaultSequences; + + this.constraintTypeStaxBuilders = new ArrayList<>(); + this.groupSequenceStaxBuilder = new GroupSequenceStaxBuilder( classLoadingHelper, defaultPackageStaxBuilder ); + } + + @Override + protected String getAcceptableQName() { + return CLASS_QNAME_LOCAL_PART; + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + ignoreAnnotations = readAttribute( xmlEvent.asStartElement(), IGNORE_ANNOTATIONS_QNAME ).map( Boolean::parseBoolean ); + + ConstraintTypeStaxBuilder constraintTypeStaxBuilder = getNewConstraintTypeStaxBuilder(); + while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( getAcceptableQName() ) ) ) { + xmlEvent = xmlEventReader.nextEvent(); + groupSequenceStaxBuilder.process( xmlEventReader, xmlEvent ); + if ( constraintTypeStaxBuilder.process( xmlEventReader, xmlEvent ) ) { + constraintTypeStaxBuilders.add( constraintTypeStaxBuilder ); + constraintTypeStaxBuilder = getNewConstraintTypeStaxBuilder(); + } + } + } + + private ConstraintTypeStaxBuilder getNewConstraintTypeStaxBuilder() { + return new ConstraintTypeStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder ); + } + + ConstrainedType build(Class beanClass) { + // group sequence + List> groupSequence = Arrays.asList( groupSequenceStaxBuilder.build() ); + if ( !groupSequence.isEmpty() ) { + defaultSequences.put( beanClass, groupSequence ); + } + + // constraints + ConstraintLocation constraintLocation = ConstraintLocation.forClass( beanClass ); + + Set> metaConstraints = constraintTypeStaxBuilders.stream() + .map( builder -> builder.build( constraintLocation, java.lang.annotation.ElementType.TYPE, null ) ) + .collect( Collectors.toSet() ); + + // ignore annotation + if ( ignoreAnnotations.isPresent() ) { + annotationProcessingOptions.ignoreClassLevelConstraintAnnotations( + beanClass, + ignoreAnnotations.get() + ); + } + + return new ConstrainedType( + ConfigurationSource.XML, + beanClass, + metaConstraints + ); + } + + private static class GroupSequenceStaxBuilder extends AbstractMultiValuedElementStaxBuilder { + + private static final String GROUP_SEQUENCE_QNAME_LOCAL_PART = "group-sequence"; + + private GroupSequenceStaxBuilder(ClassLoadingHelper classLoadingHelper, DefaultPackageStaxBuilder defaultPackageStaxBuilder) { + super( classLoadingHelper, defaultPackageStaxBuilder ); + } + + @Override + public void verifyClass(Class clazz) { + // do nothing + } + + @Override + protected String getAcceptableQName() { + return GROUP_SEQUENCE_QNAME_LOCAL_PART; + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/ClassLoadingHelper.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassLoadingHelper.java similarity index 95% rename from engine/src/main/java/org/hibernate/validator/internal/xml/ClassLoadingHelper.java rename to engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassLoadingHelper.java index 7d5392df18..b7ae1af373 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/ClassLoadingHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassLoadingHelper.java @@ -4,7 +4,7 @@ * License: Apache License, Version 2.0 * See the license.txt file in the root directory or . */ -package org.hibernate.validator.internal.xml; +package org.hibernate.validator.internal.xml.mapping; import static org.hibernate.validator.internal.util.CollectionHelper.newHashMap; @@ -21,7 +21,7 @@ * * @author Gunnar Morling */ -/*package*/ class ClassLoadingHelper { +class ClassLoadingHelper { private static final String PACKAGE_SEPARATOR = "."; private static final String ARRAY_CLASS_NAME_PREFIX = "[L"; @@ -51,7 +51,7 @@ this.externalClassLoader = externalClassLoader; } - /*package*/ Class loadClass(String className, String defaultPackage) { + Class loadClass(String className, String defaultPackage) { if ( PRIMITIVE_NAME_TO_PRIMITIVE.containsKey( className ) ) { return PRIMITIVE_NAME_TO_PRIMITIVE.get( className ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java new file mode 100644 index 0000000000..d29312b7b8 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java @@ -0,0 +1,138 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Constructor; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import javax.xml.namespace.QName; + +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; +import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; +import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; +import org.hibernate.validator.internal.util.CollectionHelper; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredConstructor; + +/** + * Builder for constrained constructors. + * + * @author Hardy Ferentschik + * @author Guillaume Smet + * @author Marko Bekhta + */ +class ConstrainedConstructorStaxBuilder extends AbstractConstrainedExecutableElementStaxBuilder { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + private static final String METHOD_QNAME_LOCAL_PART = "constructor"; + + ConstrainedConstructorStaxBuilder( + ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, + ValueExtractorManager valueExtractorManager, DefaultPackageStaxBuilder defaultPackageStaxBuilder, + AnnotationProcessingOptionsImpl annotationProcessingOptions) { + super( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + } + + @Override + Optional getMainAttributeValueQname() { + return Optional.empty(); + } + + @Override + protected String getAcceptableQName() { + return METHOD_QNAME_LOCAL_PART; + } + + public String getMethodName() { + return mainAttributeValue; + } + + ConstrainedExecutable build(Class beanClass, List> alreadyProcessedConstructors) { + Class[] parameterTypes = constrainedParameterStaxBuilders.stream() + .map( builder -> builder.getParameterType( beanClass ) ) + .toArray( Class[]::new ); + + final Constructor constructor = run( + GetDeclaredConstructor.action( + beanClass, + parameterTypes + ) + ); + + if ( constructor == null ) { + throw LOG.getBeanDoesNotContainConstructorException( + beanClass, + parameterTypes + ); + } + + if ( alreadyProcessedConstructors.contains( constructor ) ) { + throw LOG.getConstructorIsDefinedTwiceInMappingXmlForBeanException( constructor, beanClass ); + } + else { + alreadyProcessedConstructors.add( constructor ); + } + + // ignore annotations + if ( ignoreAnnotations.isPresent() ) { + annotationProcessingOptions.ignoreConstraintAnnotationsOnMember( + constructor, + ignoreAnnotations.get() + ); + } + + List constrainedParameters = CollectionHelper.newArrayList( constrainedParameterStaxBuilders.size() ); + for ( int index = 0; index < constrainedParameterStaxBuilders.size(); index++ ) { + ConstrainedParameterStaxBuilder builder = constrainedParameterStaxBuilders.get( index ); + constrainedParameters.add( builder.build( constructor, index ) ); + } + + Set> crossParameterConstraints = getCrossParameterStaxBuilder() + .map( builder -> builder.build( constructor ) ).orElse( Collections.emptySet() ); + + // parse the return value + Set> returnValueConstraints = new HashSet<>(); + Set> returnValueTypeArgumentConstraints = new HashSet<>(); + CascadingMetaDataBuilder cascadingMetaDataBuilder = getReturnValueStaxBuilder().map( builder -> builder.build( constructor, returnValueConstraints, returnValueTypeArgumentConstraints ) ) + .orElse( CascadingMetaDataBuilder.nonCascading() ); + + return new ConstrainedExecutable( + ConfigurationSource.XML, + constructor, + constrainedParameters, + crossParameterConstraints, + returnValueConstraints, + returnValueTypeArgumentConstraints, + cascadingMetaDataBuilder + ); + } + + /** + * Runs the given privileged action, using a privileged block if required. + * + * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary + * privileged actions within HV's protection domain. + */ + private static T run(PrivilegedAction action) { + return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java new file mode 100644 index 0000000000..8b2a8a97be --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java @@ -0,0 +1,116 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Field; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.xml.namespace.QName; + +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; +import org.hibernate.validator.internal.metadata.raw.ConstrainedField; +import org.hibernate.validator.internal.util.ReflectionHelper; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredField; +import org.hibernate.validator.internal.xml.mapping.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; + +/** + * Builder for constrained fields. + * + * @author Hardy Ferentschik + * @author Guillaume Smet + * @author Marko Bekhta + */ +class ConstrainedFieldStaxBuilder extends AbstractConstrainedElementStaxBuilder { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + private static final String FIELD_QNAME_LOCAL_PART = "field"; + private static final QName NAME_QNAME = new QName( "name" ); + + ConstrainedFieldStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, + TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions) { + super( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + } + + @Override + Optional getMainAttributeValueQname() { + return Optional.of( NAME_QNAME ); + } + + @Override + protected String getAcceptableQName() { + return FIELD_QNAME_LOCAL_PART; + } + + ConstrainedField build(Class beanClass, List alreadyProcessedFieldNames) { + if ( alreadyProcessedFieldNames.contains( mainAttributeValue ) ) { + throw LOG.getIsDefinedTwiceInMappingXmlForBeanException( mainAttributeValue, beanClass ); + } + else { + alreadyProcessedFieldNames.add( mainAttributeValue ); + } + Field field = findField( beanClass, mainAttributeValue ); + ConstraintLocation constraintLocation = ConstraintLocation.forField( field ); + Set> metaConstraints = constraintTypeStaxBuilders.stream() + .map( builder -> builder.build( constraintLocation, java.lang.annotation.ElementType.FIELD, null ) ) + .collect( Collectors.toSet() ); + + ContainerElementTypeConfiguration containerElementTypeConfiguration = getContainerElementTypeConfiguration( + ReflectionHelper.typeOf( field ), constraintLocation ); + + ConstrainedField constrainedField = new ConstrainedField( + ConfigurationSource.XML, + field, + metaConstraints, + containerElementTypeConfiguration.getMetaConstraints(), + getCascadingMetaData( containerElementTypeConfiguration.getTypeParametersCascadingMetaData(), ReflectionHelper.typeOf( field ) ) + ); + + // ignore annotations + if ( ignoreAnnotations.isPresent() ) { + annotationProcessingOptions.ignoreConstraintAnnotationsOnMember( + field, + ignoreAnnotations.get() + ); + } + + return constrainedField; + } + + private static Field findField(Class beanClass, String fieldName) { + final Field field = run( GetDeclaredField.action( beanClass, fieldName ) ); + if ( field == null ) { + throw LOG.getBeanDoesNotContainTheFieldException( beanClass, fieldName ); + } + return field; + } + + /** + * Runs the given privileged action, using a privileged block if required. + * + * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary + * privileged actions within HV's protection domain. + */ + private static T run(PrivilegedAction action) { + return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java new file mode 100644 index 0000000000..92ee72d0de --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java @@ -0,0 +1,123 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.xml.namespace.QName; + +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; +import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; +import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; +import org.hibernate.validator.internal.util.ReflectionHelper; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.internal.util.privilegedactions.GetMethodFromPropertyName; +import org.hibernate.validator.internal.xml.mapping.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; + +/** + * Builder for constrained getters. + * + * @author Hardy Ferentschik + * @author Guillaume Smet + * @author Marko Bekhta + */ +class ConstrainedGetterStaxBuilder extends AbstractConstrainedElementStaxBuilder { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + private static final QName NAME_QNAME = new QName( "name" ); + + private static final String GETTER_QNAME_LOCAL_PART = "getter"; + + ConstrainedGetterStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, + ValueExtractorManager valueExtractorManager, DefaultPackageStaxBuilder defaultPackageStaxBuilder, + AnnotationProcessingOptionsImpl annotationProcessingOptions) { + super( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + } + + @Override + Optional getMainAttributeValueQname() { + return Optional.of( NAME_QNAME ); + } + + @Override + protected String getAcceptableQName() { + return GETTER_QNAME_LOCAL_PART; + } + + ConstrainedExecutable build(Class beanClass, List alreadyProcessedGetterNames) { + if ( alreadyProcessedGetterNames.contains( mainAttributeValue ) ) { + throw LOG.getIsDefinedTwiceInMappingXmlForBeanException( mainAttributeValue, beanClass ); + } + else { + alreadyProcessedGetterNames.add( mainAttributeValue ); + } + Method getter = findGetter( beanClass, mainAttributeValue ); + ConstraintLocation constraintLocation = ConstraintLocation.forGetter( getter ); + + Set> metaConstraints = constraintTypeStaxBuilders.stream() + .map( builder -> builder.build( constraintLocation, java.lang.annotation.ElementType.METHOD, null ) ) + .collect( Collectors.toSet() ); + + ContainerElementTypeConfiguration containerElementTypeConfiguration = getContainerElementTypeConfiguration( + ReflectionHelper.typeOf( getter ), constraintLocation ); + + ConstrainedExecutable constrainedGetter = new ConstrainedExecutable( + ConfigurationSource.XML, + getter, + Collections.emptyList(), + Collections.>emptySet(), + metaConstraints, + containerElementTypeConfiguration.getMetaConstraints(), + getCascadingMetaData( containerElementTypeConfiguration.getTypeParametersCascadingMetaData(), ReflectionHelper.typeOf( getter ) ) + ); + + // ignore annotations + if ( ignoreAnnotations.isPresent() ) { + annotationProcessingOptions.ignoreConstraintAnnotationsOnMember( + getter, + ignoreAnnotations.get() + ); + } + + return constrainedGetter; + } + + private static Method findGetter(Class beanClass, String getterName) { + final Method method = run( GetMethodFromPropertyName.action( beanClass, getterName ) ); + if ( method == null ) { + throw LOG.getBeanDoesNotContainThePropertyException( beanClass, getterName ); + } + + return method; + } + + /** + * Runs the given privileged action, using a privileged block if required. + * + * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary + * privileged actions within HV's protection domain. + */ + private static T run(PrivilegedAction action) { + return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); + } + +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java new file mode 100644 index 0000000000..ede789a730 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java @@ -0,0 +1,143 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import javax.xml.namespace.QName; + +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; +import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; +import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; +import org.hibernate.validator.internal.util.CollectionHelper; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethod; + +/** + * Builder for constrained methods. + * + * @author Hardy Ferentschik + * @author Guillaume Smet + * @author Marko Bekhta + */ +class ConstrainedMethodStaxBuilder extends AbstractConstrainedExecutableElementStaxBuilder { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + private static final String METHOD_QNAME_LOCAL_PART = "method"; + private static final QName NAME_QNAME = new QName( "name" ); + + ConstrainedMethodStaxBuilder( + ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, + ValueExtractorManager valueExtractorManager, DefaultPackageStaxBuilder defaultPackageStaxBuilder, + AnnotationProcessingOptionsImpl annotationProcessingOptions) { + super( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + } + + @Override + Optional getMainAttributeValueQname() { + return Optional.of( NAME_QNAME ); + } + + @Override + protected String getAcceptableQName() { + return METHOD_QNAME_LOCAL_PART; + } + + public String getMethodName() { + return mainAttributeValue; + } + + ConstrainedExecutable build(Class beanClass, List alreadyProcessedMethods) { + Class[] parameterTypes = constrainedParameterStaxBuilders.stream() + .map( builder -> builder.getParameterType( beanClass ) ) + .toArray( Class[]::new ); + + String methodName = getMethodName(); + + final Method method = run( + GetDeclaredMethod.action( + beanClass, + methodName, + parameterTypes + ) + ); + + if ( method == null ) { + throw LOG.getBeanDoesNotContainMethodException( + beanClass, + methodName, + parameterTypes + ); + } + + if ( alreadyProcessedMethods.contains( method ) ) { + throw LOG.getMethodIsDefinedTwiceInMappingXmlForBeanException( method, beanClass ); + } + else { + alreadyProcessedMethods.add( method ); + } + + // ignore annotations + if ( ignoreAnnotations.isPresent() ) { + annotationProcessingOptions.ignoreConstraintAnnotationsOnMember( + method, + ignoreAnnotations.get() + ); + } + + List constrainedParameters = CollectionHelper.newArrayList( constrainedParameterStaxBuilders.size() ); + for ( int index = 0; index < constrainedParameterStaxBuilders.size(); index++ ) { + ConstrainedParameterStaxBuilder builder = constrainedParameterStaxBuilders.get( index ); + constrainedParameters.add( builder.build( method, index ) ); + } + + Set> crossParameterConstraints = getCrossParameterStaxBuilder() + .map( builder -> builder.build( method ) ).orElse( Collections.emptySet() ); + + // parse the return value + Set> returnValueConstraints = new HashSet<>(); + Set> returnValueTypeArgumentConstraints = new HashSet<>(); + CascadingMetaDataBuilder cascadingMetaDataBuilder = getReturnValueStaxBuilder().map( builder -> builder.build( method, returnValueConstraints, returnValueTypeArgumentConstraints ) ) + .orElse( CascadingMetaDataBuilder.nonCascading() ); + + return new ConstrainedExecutable( + ConfigurationSource.XML, + method, + constrainedParameters, + crossParameterConstraints, + returnValueConstraints, + returnValueTypeArgumentConstraints, + cascadingMetaDataBuilder + ); + } + + /** + * Runs the given privileged action, using a privileged block if required. + * + * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary + * privileged actions within HV's protection domain. + */ + private static T run(PrivilegedAction action) { + return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java new file mode 100644 index 0000000000..cf5a77d690 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java @@ -0,0 +1,102 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Executable; +import java.lang.reflect.Type; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.validation.ValidationException; +import javax.xml.namespace.QName; + +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; +import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; +import org.hibernate.validator.internal.util.ReflectionHelper; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.internal.xml.mapping.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; + +/** + * Builder for constrained parameters. + * + * @author Hardy Ferentschik + * @author Guillaume Smet + * @author Marko Bekhta + */ +class ConstrainedParameterStaxBuilder extends AbstractConstrainedElementStaxBuilder { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + private static final String PARAMETER_QNAME_LOCAL_PART = "parameter"; + private static final QName TYPE_QNAME = new QName( "type" ); + + ConstrainedParameterStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, + ValueExtractorManager valueExtractorManager, DefaultPackageStaxBuilder defaultPackageStaxBuilder, + AnnotationProcessingOptionsImpl annotationProcessingOptions) { + super( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + } + + @Override + Optional getMainAttributeValueQname() { + return Optional.of( TYPE_QNAME ); + } + + @Override + protected String getAcceptableQName() { + return PARAMETER_QNAME_LOCAL_PART; + } + + public Class getParameterType(Class beanClass) { + try { + return classLoadingHelper.loadClass( mainAttributeValue, defaultPackageStaxBuilder.build().orElse( "" ) ); + } + catch (ValidationException e) { + throw LOG.getInvalidParameterTypeException( mainAttributeValue, beanClass ); + } + } + + ConstrainedParameter build(Executable executable, int index) { + + ConstraintLocation constraintLocation = ConstraintLocation.forParameter( executable, index ); + Type type = ReflectionHelper.typeOf( executable, index ); + + Set> metaConstraints = constraintTypeStaxBuilders.stream() + .map( builder -> builder.build( constraintLocation, java.lang.annotation.ElementType.PARAMETER, null ) ) + .collect( Collectors.toSet() ); + + ContainerElementTypeConfiguration containerElementTypeConfiguration = getContainerElementTypeConfiguration( type, constraintLocation ); + + // ignore annotations + if ( ignoreAnnotations.isPresent() ) { + annotationProcessingOptions.ignoreConstraintAnnotationsOnParameter( + executable, + index, + ignoreAnnotations.get() + ); + } + + ConstrainedParameter constrainedParameter = new ConstrainedParameter( + ConfigurationSource.XML, + executable, + type, + index, + metaConstraints, + containerElementTypeConfiguration.getMetaConstraints(), + getCascadingMetaData( containerElementTypeConfiguration.getTypeParametersCascadingMetaData(), type ) + ); + return constrainedParameter; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintDefinitionStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintDefinitionStaxBuilder.java new file mode 100644 index 0000000000..69e7af4f55 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintDefinitionStaxBuilder.java @@ -0,0 +1,158 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.lang.annotation.Annotation; +import java.lang.invoke.MethodHandles; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.validation.ConstraintValidator; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorDescriptor; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.internal.xml.AbstractStaxBuilder; + +/** + * Builder for a constraint definition. + * + * @author Marko Bekhta + */ +class ConstraintDefinitionStaxBuilder extends AbstractStaxBuilder { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + private static final String CONSTRAINT_DEFINITION_QNAME_LOCAL_PART = "constraint-definition"; + private static final QName ANNOTATION_QNAME = new QName( "annotation" ); + + private final ClassLoadingHelper classLoadingHelper; + private final ConstraintHelper constraintHelper; + private final DefaultPackageStaxBuilder defaultPackageStaxBuilder; + + private String annotation; + private ValidatedByStaxBuilder validatedByStaxBuilder; + + ConstraintDefinitionStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, DefaultPackageStaxBuilder defaultPackageStaxBuilder) { + this.classLoadingHelper = classLoadingHelper; + this.constraintHelper = constraintHelper; + this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; + + this.validatedByStaxBuilder = new ValidatedByStaxBuilder( classLoadingHelper, defaultPackageStaxBuilder ); + } + + @Override + protected String getAcceptableQName() { + return CONSTRAINT_DEFINITION_QNAME_LOCAL_PART; + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + annotation = readAttribute( xmlEvent.asStartElement(), ANNOTATION_QNAME ).get(); + while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( getAcceptableQName() ) ) ) { + validatedByStaxBuilder.process( xmlEventReader, xmlEvent ); + xmlEvent = xmlEventReader.nextEvent(); + } + } + + @SuppressWarnings("unchecked") + void build(Set alreadyProcessedConstraintDefinitions) { + checkProcessedAnnotations( alreadyProcessedConstraintDefinitions ); + String defaultPackage = defaultPackageStaxBuilder.build().orElse( "" ); + Class clazz = classLoadingHelper.loadClass( annotation, defaultPackage ); + if ( !clazz.isAnnotation() ) { + throw LOG.getIsNotAnAnnotationException( clazz ); + } + Class annotationClass = (Class) clazz; + addValidatorDefinitions( annotationClass ); + } + + private void checkProcessedAnnotations(Set alreadyProcessedConstraintDefinitions) { + if ( alreadyProcessedConstraintDefinitions.contains( annotation ) ) { + throw LOG.getOverridingConstraintDefinitionsInMultipleMappingFilesException( annotation ); + } + else { + alreadyProcessedConstraintDefinitions.add( annotation ); + } + } + + private void addValidatorDefinitions(Class annotationClass) { + constraintHelper.putValidatorDescriptors( + annotationClass, + validatedByStaxBuilder.build( annotationClass ), + validatedByStaxBuilder.isIncludeExistingValidators() + ); + } + + private static class ValidatedByStaxBuilder extends AbstractStaxBuilder { + + private static final String VALIDATED_BY_QNAME_LOCAL_PART = "validated-by"; + private static final String VALUE_QNAME_LOCAL_PART = "value"; + private static final QName INCLUDE_EXISTING_VALIDATORS_QNAME = new QName( "include-existing-validators" ); + + private final ClassLoadingHelper classLoadingHelper; + private final DefaultPackageStaxBuilder defaultPackageStaxBuilder; + + private boolean includeExistingValidators; + private final List values; + + protected ValidatedByStaxBuilder(ClassLoadingHelper classLoadingHelper, DefaultPackageStaxBuilder defaultPackageStaxBuilder) { + this.classLoadingHelper = classLoadingHelper; + this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; + + this.values = new ArrayList<>(); + } + + @Override + protected String getAcceptableQName() { + return VALIDATED_BY_QNAME_LOCAL_PART; + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + includeExistingValidators = readAttribute( xmlEvent.asStartElement(), INCLUDE_EXISTING_VALIDATORS_QNAME ) + .map( Boolean::parseBoolean ).orElse( true ); + + while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( getAcceptableQName() ) ) ) { + if ( xmlEvent.isStartElement() && xmlEvent.asStartElement().getName().getLocalPart().equals( VALUE_QNAME_LOCAL_PART ) ) { + values.add( readSingleElement( xmlEventReader ) ); + } + xmlEvent = xmlEventReader.nextEvent(); + } + } + + @SuppressWarnings("unchecked") + List> build(Class annotation) { + String defaultPackage = defaultPackageStaxBuilder.build().orElse( "" ); + + return values.stream() + .map( value -> classLoadingHelper.loadClass( value, defaultPackage ) ) + .peek( this::checkValidatorAssignability ) + .map( clazz -> (Class>) clazz ) + .map( ConstraintValidatorDescriptor::forClass ) + .collect( Collectors.toList() ); + } + + public boolean isIncludeExistingValidators() { + return includeExistingValidators; + } + + private void checkValidatorAssignability(Class validatorClass) { + if ( !ConstraintValidator.class.isAssignableFrom( validatorClass ) ) { + throw LOG.getIsNotAConstraintValidatorClassException( validatorClass ); + } + } + + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintMappingsStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintMappingsStaxBuilder.java new file mode 100644 index 0000000000..50ac58eeb8 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintMappingsStaxBuilder.java @@ -0,0 +1,96 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.xml.AbstractStaxBuilder; + +/** + * Top level builder for constraint mappings. Reads the whole mapping file and builds the constraint definitions defined + * in it as well as the list of constrained elements per bean. + * + * @author Marko Bekhta + */ +class ConstraintMappingsStaxBuilder extends AbstractStaxBuilder { + + private static final String CONSTRAINT_MAPPINGS_QNAME = "constraint-mappings"; + + private final ClassLoadingHelper classLoadingHelper; + private final ConstraintHelper constraintHelper; + private final TypeResolutionHelper typeResolutionHelper; + private final ValueExtractorManager valueExtractorManager; + private final AnnotationProcessingOptionsImpl annotationProcessingOptions; + private final Map, List>> defaultSequences; + + private final DefaultPackageStaxBuilder defaultPackageStaxBuilder; + private final List beanStaxBuilders; + private final List constraintDefinitionStaxBuilders; + + public ConstraintMappingsStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + AnnotationProcessingOptionsImpl annotationProcessingOptions, Map, List>> defaultSequences) { + this.classLoadingHelper = classLoadingHelper; + this.constraintHelper = constraintHelper; + this.typeResolutionHelper = typeResolutionHelper; + this.valueExtractorManager = valueExtractorManager; + this.annotationProcessingOptions = annotationProcessingOptions; + this.defaultSequences = defaultSequences; + + this.defaultPackageStaxBuilder = new DefaultPackageStaxBuilder(); + this.beanStaxBuilders = new ArrayList<>(); + this.constraintDefinitionStaxBuilders = new ArrayList<>(); + } + + @Override + protected String getAcceptableQName() { + return CONSTRAINT_MAPPINGS_QNAME; + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + BeanStaxBuilder beanStaxBuilder = getNewBeanStaxBuilder(); + ConstraintDefinitionStaxBuilder constraintDefinitionStaxBuilder = getNewConstraintDefinitionStaxBuilder(); + + while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( getAcceptableQName() ) ) ) { + xmlEvent = xmlEventReader.nextEvent(); + if ( beanStaxBuilder.process( xmlEventReader, xmlEvent ) ) { + beanStaxBuilders.add( beanStaxBuilder ); + beanStaxBuilder = getNewBeanStaxBuilder(); + } + else if ( constraintDefinitionStaxBuilder.process( xmlEventReader, xmlEvent ) ) { + constraintDefinitionStaxBuilders.add( constraintDefinitionStaxBuilder ); + constraintDefinitionStaxBuilder = getNewConstraintDefinitionStaxBuilder(); + } + defaultPackageStaxBuilder.process( xmlEventReader, xmlEvent ); + } + } + + private BeanStaxBuilder getNewBeanStaxBuilder() { + return new BeanStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions, defaultSequences ); + } + + private ConstraintDefinitionStaxBuilder getNewConstraintDefinitionStaxBuilder() { + return new ConstraintDefinitionStaxBuilder( classLoadingHelper, constraintHelper, defaultPackageStaxBuilder ); + } + + public void build(Set> processedClasses, Map, Set> constrainedElementsByType, Set alreadyProcessedConstraintDefinitions) { + constraintDefinitionStaxBuilders.forEach( builder -> builder.build( alreadyProcessedConstraintDefinitions ) ); + beanStaxBuilders.forEach( builder -> builder.build( processedClasses, constrainedElementsByType ) ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintTypeStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintTypeStaxBuilder.java new file mode 100644 index 0000000000..862a1226ad --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintTypeStaxBuilder.java @@ -0,0 +1,514 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.lang.annotation.Annotation; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.validation.Payload; +import javax.validation.ValidationException; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.metadata.core.MetaConstraints; +import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.util.annotation.AnnotationDescriptor; +import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.internal.util.privilegedactions.GetMethod; +import org.hibernate.validator.internal.xml.AbstractStaxBuilder; + +/** + * Builder for constraint information. Creates a constraint based on a set of given values. + * + * @author Hardy Ferentschik + * @author Marko Bekhta + */ +class ConstraintTypeStaxBuilder extends AbstractStaxBuilder { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + private static final Pattern IS_ONLY_WHITESPACE = Pattern.compile( "\\s*" ); + + private static final String CONSTRAINT_QNAME_LOCAL_PART = "constraint"; + + private static final QName CONSTRAINT_ANNOTATION_QNAME = new QName( "annotation" ); + + private final ClassLoadingHelper classLoadingHelper; + private final ConstraintHelper constraintHelper; + private final TypeResolutionHelper typeResolutionHelper; + private final ValueExtractorManager valueExtractorManager; + private final DefaultPackageStaxBuilder defaultPackageStaxBuilder; + + // Builders: + private final GroupsStaxBuilder groupsStaxBuilder; + private final PayloadStaxBuilder payloadStaxBuilder; + private final ConstraintParameterStaxBuilder constrainParameterStaxBuilder; + private final MessageStaxBuilder messageStaxBuilder; + + private final List builders; + + private String constraintAnnotation; + + ConstraintTypeStaxBuilder( + ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, + TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + DefaultPackageStaxBuilder defaultPackageStaxBuilder) { + this.classLoadingHelper = classLoadingHelper; + this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; + this.constraintHelper = constraintHelper; + this.typeResolutionHelper = typeResolutionHelper; + this.valueExtractorManager = valueExtractorManager; + + this.groupsStaxBuilder = new GroupsStaxBuilder( classLoadingHelper, defaultPackageStaxBuilder ); + this.payloadStaxBuilder = new PayloadStaxBuilder( classLoadingHelper, defaultPackageStaxBuilder ); + this.constrainParameterStaxBuilder = new ConstraintParameterStaxBuilder( classLoadingHelper, defaultPackageStaxBuilder ); + this.messageStaxBuilder = new MessageStaxBuilder(); + + this.builders = Stream.of( groupsStaxBuilder, payloadStaxBuilder, constrainParameterStaxBuilder, messageStaxBuilder ) + .collect( Collectors.collectingAndThen( Collectors.toList(), Collections::unmodifiableList ) ); + + } + + @Override + protected String getAcceptableQName() { + return CONSTRAINT_QNAME_LOCAL_PART; + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + StartElement startElement = xmlEvent.asStartElement(); + constraintAnnotation = readAttribute( startElement, CONSTRAINT_ANNOTATION_QNAME ).get(); + while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( CONSTRAINT_QNAME_LOCAL_PART ) ) ) { + XMLEvent currentEvent = xmlEvent; + builders.forEach( builder -> builder.process( xmlEventReader, currentEvent ) ); + xmlEvent = xmlEventReader.nextEvent(); + } + } + + @SuppressWarnings("unchecked") + MetaConstraint build(ConstraintLocation constraintLocation, java.lang.annotation.ElementType type, ConstraintDescriptorImpl.ConstraintType constraintType) { + String defaultPackage = defaultPackageStaxBuilder.build().orElse( "" ); + + Class annotationClass; + try { + annotationClass = (Class) classLoadingHelper.loadClass( constraintAnnotation, defaultPackage ); + } + catch (ValidationException e) { + throw LOG.getUnableToLoadConstraintAnnotationClassException( constraintAnnotation, e ); + } + ConstraintAnnotationDescriptor.Builder annotationDescriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( annotationClass ); + + // set common things to all constraints: + Optional message = messageStaxBuilder.build(); + if ( message.isPresent() ) { + annotationDescriptorBuilder.setMessage( message.get() ); + } + annotationDescriptorBuilder.setGroups( groupsStaxBuilder.build() ) + .setPayload( payloadStaxBuilder.build() ); + + // set constraint specific attributes: + Map parameters = constrainParameterStaxBuilder.build( annotationClass ); + for ( Map.Entry parameter : parameters.entrySet() ) { + annotationDescriptorBuilder.setAttribute( parameter.getKey(), parameter.getValue() ); + } + + ConstraintAnnotationDescriptor annotationDescriptor; + try { + annotationDescriptor = annotationDescriptorBuilder.build(); + } + catch (RuntimeException e) { + throw LOG.getUnableToCreateAnnotationForConfiguredConstraintException( e ); + } + + // we set initially ConstraintOrigin.DEFINED_LOCALLY for all xml configured constraints + // later we will make copies of this constraint descriptor when needed and adjust the ConstraintOrigin + ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl( + constraintHelper, constraintLocation.getMember(), annotationDescriptor, type, constraintType + ); + + return MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor, constraintLocation ); + } + + private static class MessageStaxBuilder extends AbstractOneLineStringStaxBuilder { + + private static final String MESSAGE_PACKAGE_QNAME = "message"; + + @Override + protected String getAcceptableQName() { + return MESSAGE_PACKAGE_QNAME; + } + } + + private static class ConstraintParameterStaxBuilder extends AnnotationParameterStaxBuilder { + + private static final String ELEMENT_QNAME_LOCAL_PART = "element"; + private static final QName NAME_QNAME = new QName( "name" ); + + public ConstraintParameterStaxBuilder(ClassLoadingHelper classLoadingHelper, DefaultPackageStaxBuilder defaultPackageStaxBuilder) { + super( classLoadingHelper, defaultPackageStaxBuilder ); + } + + @Override + protected String getAcceptableQName() { + return ELEMENT_QNAME_LOCAL_PART; + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + String name = readAttribute( xmlEvent.asStartElement(), NAME_QNAME ).get(); + while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( ELEMENT_QNAME_LOCAL_PART ) ) ) { + xmlEvent = xmlEventReader.nextEvent(); + readElement( xmlEventReader, xmlEvent, name ); + } + } + + @Override + protected void checkNameIsValid(String name) { + if ( ConstraintHelper.MESSAGE.equals( name ) || ConstraintHelper.GROUPS.equals( name ) || ConstraintHelper.PAYLOAD.equals( name ) ) { + throw LOG.getReservedParameterNamesException( ConstraintHelper.MESSAGE, ConstraintHelper.GROUPS, ConstraintHelper.PAYLOAD ); + } + } + + public Map build(Class annotationClass) { + String defaultPackage = defaultPackageStaxBuilder.build().orElse( "" ); + Map builtParameters = new HashMap<>(); + for ( Map.Entry> parameter : parameters.entrySet() ) { + builtParameters.put( + parameter.getKey(), + getElementValue( parameter.getValue(), annotationClass, parameter.getKey(), defaultPackage ) + ); + } + for ( Map.Entry> parameter : annotationParameters.entrySet() ) { + builtParameters.put( + parameter.getKey(), + getAnnotationElementValue( parameter.getValue(), annotationClass, parameter.getKey(), defaultPackage ) + ); + } + + return builtParameters; + } + } + + private static class AnnotationParameterStaxBuilder extends AbstractStaxBuilder { + + private static final String ANNOTATION_QNAME_LOCAL_PART = "annotation"; + private static final String ELEMENT_QNAME_LOCAL_PART = "element"; + private static final String VALUE_QNAME_LOCAL_PART = "value"; + private static final QName NAME_QNAME = new QName( "name" ); + + private final ClassLoadingHelper classLoadingHelper; + protected final DefaultPackageStaxBuilder defaultPackageStaxBuilder; + + protected Map> parameters; + protected Map> annotationParameters; + + public AnnotationParameterStaxBuilder(ClassLoadingHelper classLoadingHelper, DefaultPackageStaxBuilder defaultPackageStaxBuilder) { + this.classLoadingHelper = classLoadingHelper; + this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; + + this.parameters = new HashMap<>(); + this.annotationParameters = new HashMap<>(); + } + + @Override + protected String getAcceptableQName() { + return ANNOTATION_QNAME_LOCAL_PART; + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( ANNOTATION_QNAME_LOCAL_PART ) ) ) { + xmlEvent = xmlEventReader.nextEvent(); + if ( xmlEvent.isStartElement() ) { + StartElement startElement = xmlEvent.asStartElement(); + if ( startElement.getName().getLocalPart().equals( ELEMENT_QNAME_LOCAL_PART ) ) { + String name = readAttribute( xmlEvent.asStartElement(), NAME_QNAME ).get(); + + // we put empty collection here in case the corresponding string element in xml is empty + // if there will be a value it will get merged in this#addParameterValue() + parameters.put( name, Collections.emptyList() ); + while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( ELEMENT_QNAME_LOCAL_PART ) ) ) { + readElement( xmlEventReader, xmlEvent, name ); + xmlEvent = xmlEventReader.nextEvent(); + } + } + } + } + } + + protected void readElement(XMLEventReader xmlEventReader, XMLEvent xmlEvent, String name) throws XMLStreamException { + // need to check the next element + if ( xmlEvent.isCharacters() && !xmlEvent.asCharacters().getData().trim().isEmpty() ) { + // in case it's a value - read it + StringBuilder stringBuilder = new StringBuilder( xmlEvent.asCharacters().getData() ); + while ( xmlEventReader.peek().isCharacters() ) { + xmlEvent = xmlEventReader.nextEvent(); + stringBuilder.append( xmlEvent.asCharacters().getData() ); + } + addParameterValue( name, stringBuilder.toString().trim() ); + } + else if ( xmlEvent.isStartElement() ) { + StartElement startElement = xmlEvent.asStartElement(); + // in case of multi-valued parameter read value + if ( startElement.getName().getLocalPart().equals( VALUE_QNAME_LOCAL_PART ) ) { + addParameterValue( name, readSingleElement( xmlEventReader ) ); + } + else if ( startElement.getName().getLocalPart().equals( ANNOTATION_QNAME_LOCAL_PART ) ) { + addAnnotationParameterValue( name, xmlEventReader, xmlEvent ); + } + } + } + + protected void addAnnotationParameterValue(String name, XMLEventReader xmlEventReader, XMLEvent xmlEvent) { + checkNameIsValid( name ); + + AnnotationParameterStaxBuilder annotationParameterStaxBuilder = new AnnotationParameterStaxBuilder( classLoadingHelper, defaultPackageStaxBuilder ); + annotationParameterStaxBuilder.process( xmlEventReader, xmlEvent ); + + annotationParameters.merge( + name, + Collections.singletonList( annotationParameterStaxBuilder ), + (v1, v2) -> Stream.concat( v1.stream(), v2.stream() ).collect( Collectors.toList() ) + ); + } + + protected void addParameterValue(String name, String value) { + checkNameIsValid( name ); + parameters.merge( + name, + Collections.singletonList( value ), + (v1, v2) -> Stream.concat( v1.stream(), v2.stream() ).collect( Collectors.toList() ) + ); + } + + protected void checkNameIsValid(String name) { + // in case of simple annotation - any name is acceptable + } + + public Annotation build(Class annotationClass, String defaultPackage) { + AnnotationDescriptor.Builder annotationDescriptorBuilder = new AnnotationDescriptor.Builder<>( annotationClass ); + + for ( Map.Entry> parameter : parameters.entrySet() ) { + annotationDescriptorBuilder.setAttribute( + parameter.getKey(), + getElementValue( parameter.getValue(), annotationClass, parameter.getKey(), defaultPackage ) + ); + } + for ( Map.Entry> parameter : annotationParameters.entrySet() ) { + annotationDescriptorBuilder.setAttribute( + parameter.getKey(), + getAnnotationElementValue( parameter.getValue(), annotationClass, parameter.getKey(), defaultPackage ) + ); + } + + return annotationDescriptorBuilder.build().getAnnotation(); + } + + protected Object getElementValue(List parsedParameters, Class annotationClass, String name, String defaultPackage) { + List parameters = removeEmptyContentElements( parsedParameters ); + + Class returnType = getAnnotationParameterType( annotationClass, name ); + boolean isArray = returnType.isArray(); + if ( !isArray ) { + if ( parameters.size() == 0 ) { + return ""; + } + else if ( parameters.size() > 1 ) { + throw LOG.getAttemptToSpecifyAnArrayWhereSingleValueIsExpectedException(); + } + return convertStringToReturnType( parameters.get( 0 ), returnType, defaultPackage ); + } + else { + return parameters.stream().map( value -> convertStringToReturnType( value, returnType.getComponentType(), defaultPackage ) ) + .toArray( size -> (Object[]) Array.newInstance( returnType.getComponentType(), size ) ); + } + } + + @SuppressWarnings("unchecked") + protected Object getAnnotationElementValue(List parameters, Class annotationClass, String name, String defaultPackage) { + Class returnType = getAnnotationParameterType( annotationClass, name ); + boolean isArray = returnType.isArray(); + if ( !isArray ) { + if ( parameters.size() == 0 ) { + throw LOG.getEmptyElementOnlySupportedWhenCharSequenceIsExpectedExpection(); + } + else if ( parameters.size() > 1 ) { + throw LOG.getAttemptToSpecifyAnArrayWhereSingleValueIsExpectedException(); + } + return parameters.get( 0 ).build( (Class) returnType, defaultPackage ); + } + else { + return parameters.stream().map( value -> value.build( (Class) returnType.getComponentType(), defaultPackage ) ) + .toArray( size -> (Object[]) Array.newInstance( returnType.getComponentType(), size ) ); + } + } + + private static List removeEmptyContentElements(List params) { + return params.stream().filter( content -> !IS_ONLY_WHITESPACE.matcher( content ).matches() ) + .collect( Collectors.toList() ); + } + + private static Class getAnnotationParameterType(Class annotationClass, String name) { + Method m = run( GetMethod.action( annotationClass, name ) ); + if ( m == null ) { + throw LOG.getAnnotationDoesNotContainAParameterException( annotationClass, name ); + } + return m.getReturnType(); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private Object convertStringToReturnType(String value, Class returnType, String defaultPackage) { + Object returnValue; + if ( returnType == byte.class ) { + try { + returnValue = Byte.parseByte( value ); + } + catch (NumberFormatException e) { + throw LOG.getInvalidNumberFormatException( "byte", e ); + } + } + else if ( returnType == short.class ) { + try { + returnValue = Short.parseShort( value ); + } + catch (NumberFormatException e) { + throw LOG.getInvalidNumberFormatException( "short", e ); + } + } + else if ( returnType == int.class ) { + try { + returnValue = Integer.parseInt( value ); + } + catch (NumberFormatException e) { + throw LOG.getInvalidNumberFormatException( "int", e ); + } + } + else if ( returnType == long.class ) { + try { + returnValue = Long.parseLong( value ); + } + catch (NumberFormatException e) { + throw LOG.getInvalidNumberFormatException( "long", e ); + } + } + else if ( returnType == float.class ) { + try { + returnValue = Float.parseFloat( value ); + } + catch (NumberFormatException e) { + throw LOG.getInvalidNumberFormatException( "float", e ); + } + } + else if ( returnType == double.class ) { + try { + returnValue = Double.parseDouble( value ); + } + catch (NumberFormatException e) { + throw LOG.getInvalidNumberFormatException( "double", e ); + } + } + else if ( returnType == boolean.class ) { + returnValue = Boolean.parseBoolean( value ); + } + else if ( returnType == char.class ) { + if ( value.length() != 1 ) { + throw LOG.getInvalidCharValueException( value ); + } + returnValue = value.charAt( 0 ); + } + else if ( returnType == String.class ) { + returnValue = value; + } + else if ( returnType == Class.class ) { + returnValue = classLoadingHelper.loadClass( value, defaultPackage ); + } + else { + try { + Class enumClass = (Class) returnType; + returnValue = Enum.valueOf( enumClass, value ); + } + catch (ClassCastException e) { + throw LOG.getInvalidReturnTypeException( returnType, e ); + } + } + return returnValue; + } + + /** + * Runs the given privileged action, using a privileged block if required. + * + * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary + * privileged actions within HV's protection domain. + */ + private static T run(PrivilegedAction action) { + return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); + } + } + + private static class GroupsStaxBuilder extends AbstractMultiValuedElementStaxBuilder { + + private static final String GROUPS_QNAME_LOCAL_PART = "groups"; + + private GroupsStaxBuilder(ClassLoadingHelper classLoadingHelper, DefaultPackageStaxBuilder defaultPackageStaxBuilder) { + super( classLoadingHelper, defaultPackageStaxBuilder ); + } + + @Override + public void verifyClass(Class clazz) { + // do nothing + } + + @Override + protected String getAcceptableQName() { + return GROUPS_QNAME_LOCAL_PART; + } + } + + private static class PayloadStaxBuilder extends AbstractMultiValuedElementStaxBuilder { + + private static final String PAYLOAD_QNAME_LOCAL_PART = "payload"; + + private PayloadStaxBuilder(ClassLoadingHelper classLoadingHelper, DefaultPackageStaxBuilder defaultPackageStaxBuilder) { + super( classLoadingHelper, defaultPackageStaxBuilder ); + } + + @Override + public void verifyClass(Class payload) { + if ( !Payload.class.isAssignableFrom( payload ) ) { + throw LOG.getWrongPayloadClassException( payload ); + } + } + + @Override + protected String getAcceptableQName() { + return PAYLOAD_QNAME_LOCAL_PART; + } + } + +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypeConfigurationBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypeConfigurationBuilder.java new file mode 100644 index 0000000000..fd424cd664 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypeConfigurationBuilder.java @@ -0,0 +1,84 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; +import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation; + +/** + * Builds the aggregated cascading and type argument constraints configuration from the {@link ContainerElementTypeStaxBuilder} elements. + * + * @author Guillaume Smet + * @author Marko Bekhta + */ +class ContainerElementTypeConfigurationBuilder { + + private final List containerElementTypeStaxBuilders; + private final Set configuredPaths; + + ContainerElementTypeConfigurationBuilder() { + this.containerElementTypeStaxBuilders = new ArrayList<>(); + this.configuredPaths = new HashSet<>(); + } + + public void add(ContainerElementTypeStaxBuilder containerElementTypeStaxBuilder) { + containerElementTypeStaxBuilders.add( containerElementTypeStaxBuilder ); + } + + ContainerElementTypeConfiguration build(ConstraintLocation parentConstraintLocation, Type enclosingType) { + return build( ContainerElementTypePath.root(), parentConstraintLocation, enclosingType ); + } + + private ContainerElementTypeConfiguration build(ContainerElementTypePath parentConstraintElementTypePath, + ConstraintLocation parentConstraintLocation, Type enclosingType) { + return containerElementTypeStaxBuilders.stream() + .map( builder -> builder.build( configuredPaths, parentConstraintElementTypePath, parentConstraintLocation, enclosingType ) ) + .reduce( ContainerElementTypeConfiguration.EMPTY_CONFIGURATION, ContainerElementTypeConfiguration::merge ); + } + + static class ContainerElementTypeConfiguration { + + public static final ContainerElementTypeConfiguration EMPTY_CONFIGURATION = new ContainerElementTypeConfiguration( Collections.emptySet(), Collections.emptyMap() ); + + private final Set> metaConstraints; + + private final Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaDataBuilder; + + ContainerElementTypeConfiguration(Set> metaConstraints, Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaData) { + this.metaConstraints = metaConstraints; + this.containerElementTypesCascadingMetaDataBuilder = containerElementTypesCascadingMetaData; + } + + public Set> getMetaConstraints() { + return metaConstraints; + } + + public Map, CascadingMetaDataBuilder> getTypeParametersCascadingMetaData() { + return containerElementTypesCascadingMetaDataBuilder; + } + + public static ContainerElementTypeConfiguration merge(ContainerElementTypeConfiguration l, ContainerElementTypeConfiguration r) { + return new ContainerElementTypeConfiguration( + Stream.concat( l.metaConstraints.stream(), r.metaConstraints.stream() ).collect( Collectors.toSet() ), + Stream.concat( l.containerElementTypesCascadingMetaDataBuilder.entrySet().stream(), r.containerElementTypesCascadingMetaDataBuilder.entrySet().stream() ) + .collect( Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue ) ) + ); + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/ContainerElementTypePath.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypePath.java similarity index 96% rename from engine/src/main/java/org/hibernate/validator/internal/xml/ContainerElementTypePath.java rename to engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypePath.java index 61333a6017..ce03e3d911 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/ContainerElementTypePath.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypePath.java @@ -4,7 +4,7 @@ * License: Apache License, Version 2.0 * See the license.txt file in the root directory or . */ -package org.hibernate.validator.internal.xml; +package org.hibernate.validator.internal.xml.mapping; import java.util.ArrayList; import java.util.List; diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypeStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypeStaxBuilder.java new file mode 100644 index 0000000000..1c24591a22 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypeStaxBuilder.java @@ -0,0 +1,220 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.lang.invoke.MethodHandles; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import org.hibernate.validator.internal.engine.valueextraction.ArrayElement; +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.util.CollectionHelper; +import org.hibernate.validator.internal.util.ReflectionHelper; +import org.hibernate.validator.internal.util.TypeHelper; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.internal.xml.AbstractStaxBuilder; +import org.hibernate.validator.internal.xml.mapping.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; + +/** + * Builds the cascading and type argument constraints configuration from the {@code } elements. + * + * @author Guillaume Smet + * @author Marko Bekhta + */ +class ContainerElementTypeStaxBuilder extends AbstractStaxBuilder { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + private static final String CONTAINER_ELEMENT_TYPE_QNAME_LOCAL_PART = "container-element-type"; + private static final QName TYPE_ARGUMENT_INDEX_QNAME = new QName( "type-argument-index" ); + + private final ClassLoadingHelper classLoadingHelper; + private final ConstraintHelper constraintHelper; + private final TypeResolutionHelper typeResolutionHelper; + private final ValueExtractorManager valueExtractorManager; + private final DefaultPackageStaxBuilder defaultPackageStaxBuilder; + + private Integer typeArgumentIndex; + private final ValidStaxBuilder validStaxBuilder; + private final List constraintTypeStaxBuilders; + private final GroupConversionStaxBuilder groupConversionBuilder; + private final List containerElementTypeConfigurationStaxBuilders; + + ContainerElementTypeStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, + TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, DefaultPackageStaxBuilder defaultPackageStaxBuilder) { + this.classLoadingHelper = classLoadingHelper; + this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; + this.constraintHelper = constraintHelper; + this.typeResolutionHelper = typeResolutionHelper; + this.valueExtractorManager = valueExtractorManager; + + this.groupConversionBuilder = new GroupConversionStaxBuilder( classLoadingHelper, defaultPackageStaxBuilder ); + this.validStaxBuilder = new ValidStaxBuilder(); + this.constraintTypeStaxBuilders = new ArrayList<>(); + this.containerElementTypeConfigurationStaxBuilders = new ArrayList<>(); + + } + + @Override + protected String getAcceptableQName() { + return CONTAINER_ELEMENT_TYPE_QNAME_LOCAL_PART; + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + Optional typeArgumentIndex = readAttribute( xmlEvent.asStartElement(), TYPE_ARGUMENT_INDEX_QNAME ); + if ( typeArgumentIndex.isPresent() ) { + this.typeArgumentIndex = Integer.parseInt( typeArgumentIndex.get() ); + } + ConstraintTypeStaxBuilder constraintTypeStaxBuilder = getNewConstraintTypeStaxBuilder(); + ContainerElementTypeStaxBuilder containerElementTypeConfigurationStaxBuilder = getNewContainerElementTypeConfigurationStaxBuilder(); + while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( getAcceptableQName() ) ) ) { + xmlEvent = xmlEventReader.nextEvent(); + validStaxBuilder.process( xmlEventReader, xmlEvent ); + groupConversionBuilder.process( xmlEventReader, xmlEvent ); + if ( constraintTypeStaxBuilder.process( xmlEventReader, xmlEvent ) ) { + constraintTypeStaxBuilders.add( constraintTypeStaxBuilder ); + constraintTypeStaxBuilder = getNewConstraintTypeStaxBuilder(); + } + if ( containerElementTypeConfigurationStaxBuilder.process( xmlEventReader, xmlEvent ) ) { + containerElementTypeConfigurationStaxBuilders.add( containerElementTypeConfigurationStaxBuilder ); + containerElementTypeConfigurationStaxBuilder = getNewContainerElementTypeConfigurationStaxBuilder(); + } + } + } + + private ConstraintTypeStaxBuilder getNewConstraintTypeStaxBuilder() { + return new ConstraintTypeStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder ); + } + + private ContainerElementTypeStaxBuilder getNewContainerElementTypeConfigurationStaxBuilder() { + return new ContainerElementTypeStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder ); + } + + public ContainerElementTypeConfiguration build(Set configuredPaths, + ContainerElementTypePath parentConstraintElementTypePath, + ConstraintLocation parentConstraintLocation, Type enclosingType) { + // HV-1428 Container element support is disabled for arrays + if ( TypeHelper.isArray( enclosingType ) ) { + throw LOG.getContainerElementConstraintsAndCascadedValidationNotSupportedOnArraysException( enclosingType ); + } + + if ( !( enclosingType instanceof ParameterizedType ) && !TypeHelper.isArray( enclosingType ) ) { + throw LOG.getTypeIsNotAParameterizedNorArrayTypeException( enclosingType ); + } + + Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaDataBuilder = + CollectionHelper.newHashMap( containerElementTypeConfigurationStaxBuilders.size() ); + + boolean isArray = TypeHelper.isArray( enclosingType ); + TypeVariable[] typeParameters = isArray ? new TypeVariable[0] : ReflectionHelper.getClassFromType( enclosingType ).getTypeParameters(); + + Integer typeArgumentIndex = getTypeArgumentIndex( typeParameters, isArray, enclosingType ); + + ContainerElementTypePath constraintElementTypePath = ContainerElementTypePath.of( parentConstraintElementTypePath, typeArgumentIndex ); + boolean configuredBefore = !configuredPaths.add( constraintElementTypePath ); + if ( configuredBefore ) { + throw LOG.getContainerElementTypeHasAlreadyBeenConfiguredViaXmlMappingConfigurationException( parentConstraintLocation, constraintElementTypePath ); + } + + TypeVariable typeParameter = getTypeParameter( typeParameters, typeArgumentIndex, isArray, enclosingType ); + Type containerElementType = getContainerElementType( enclosingType, typeArgumentIndex, isArray ); + ConstraintLocation containerElementTypeConstraintLocation = ConstraintLocation.forTypeArgument( parentConstraintLocation, typeParameter, + containerElementType + ); + + ContainerElementTypeConfiguration nestedContainerElementTypeConfiguration = containerElementTypeConfigurationStaxBuilders.stream() + .map( nested -> nested.build( configuredPaths, constraintElementTypePath, containerElementTypeConstraintLocation, containerElementType ) ) + .reduce( ContainerElementTypeConfiguration.EMPTY_CONFIGURATION, ContainerElementTypeConfiguration::merge ); + + boolean isCascaded = validStaxBuilder.build(); + + containerElementTypesCascadingMetaDataBuilder.put( typeParameter, new CascadingMetaDataBuilder( enclosingType, typeParameter, isCascaded, + nestedContainerElementTypeConfiguration.getTypeParametersCascadingMetaData(), + groupConversionBuilder.build() + ) + ); + + return new ContainerElementTypeConfiguration( + Stream.concat( + constraintTypeStaxBuilders.stream() + .map( + builder -> builder.build( + containerElementTypeConstraintLocation, + java.lang.annotation.ElementType.TYPE_USE, + null + ) + ), + nestedContainerElementTypeConfiguration.getMetaConstraints().stream() + ).collect( Collectors.toSet() ), + containerElementTypesCascadingMetaDataBuilder + ); + } + + private Integer getTypeArgumentIndex(TypeVariable[] typeParameters, boolean isArray, Type enclosingType) { + if ( isArray ) { + return null; + } + + if ( typeArgumentIndex == null ) { + if ( typeParameters.length > 1 ) { + throw LOG.getNoTypeArgumentIndexIsGivenForTypeWithMultipleTypeArgumentsException( enclosingType ); + } + return 0; + } + + return typeArgumentIndex; + } + + private TypeVariable getTypeParameter(TypeVariable[] typeParameters, Integer typeArgumentIndex, boolean isArray, Type enclosingType) { + TypeVariable typeParameter; + if ( !isArray ) { + if ( typeArgumentIndex > typeParameters.length - 1 ) { + throw LOG.getInvalidTypeArgumentIndexException( enclosingType, typeArgumentIndex ); + } + + typeParameter = typeParameters[typeArgumentIndex]; + } + else { + typeParameter = new ArrayElement( enclosingType ); + } + return typeParameter; + } + + private Type getContainerElementType(Type enclosingType, Integer typeArgumentIndex, boolean isArray) { + Type containerElementType; + if ( !isArray ) { + containerElementType = ( (ParameterizedType) enclosingType ).getActualTypeArguments()[typeArgumentIndex]; + } + else { + containerElementType = TypeHelper.getComponentType( enclosingType ); + } + return containerElementType; + } + + public Integer getTypeArgumentIndex() { + return null; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java new file mode 100644 index 0000000000..30397e1009 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java @@ -0,0 +1,104 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.lang.reflect.Executable; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.xml.AbstractStaxBuilder; + +/** + * Builder for cross parameters. + * + * @author Marko Bekhta + */ +class CrossParameterStaxBuilder extends AbstractStaxBuilder { + + private static final String CROSS_PARAMETER_QNAME_LOCAL_PART = "cross-parameter"; + private static final QName IGNORE_ANNOTATIONS_QNAME = new QName( "ignore-annotations" ); + + protected final ClassLoadingHelper classLoadingHelper; + protected final ConstraintHelper constraintHelper; + protected final TypeResolutionHelper typeResolutionHelper; + protected final ValueExtractorManager valueExtractorManager; + protected final DefaultPackageStaxBuilder defaultPackageStaxBuilder; + protected final AnnotationProcessingOptionsImpl annotationProcessingOptions; + + protected Optional ignoreAnnotations; + protected final List constraintTypeStaxBuilders; + + CrossParameterStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, + TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions) { + this.classLoadingHelper = classLoadingHelper; + this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; + this.constraintHelper = constraintHelper; + this.typeResolutionHelper = typeResolutionHelper; + this.valueExtractorManager = valueExtractorManager; + + this.annotationProcessingOptions = annotationProcessingOptions; + + this.constraintTypeStaxBuilders = new ArrayList<>(); + } + + @Override + protected String getAcceptableQName() { + return CROSS_PARAMETER_QNAME_LOCAL_PART; + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLStreamException { + ignoreAnnotations = readAttribute( xmlEvent.asStartElement(), IGNORE_ANNOTATIONS_QNAME ).map( Boolean::parseBoolean ); + ConstraintTypeStaxBuilder constraintTypeStaxBuilder = getNewConstraintTypeStaxBuilder(); + while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( getAcceptableQName() ) ) ) { + xmlEvent = xmlEventReader.nextEvent(); + if ( constraintTypeStaxBuilder.process( xmlEventReader, xmlEvent ) ) { + constraintTypeStaxBuilders.add( constraintTypeStaxBuilder ); + constraintTypeStaxBuilder = getNewConstraintTypeStaxBuilder(); + } + } + } + + private ConstraintTypeStaxBuilder getNewConstraintTypeStaxBuilder() { + return new ConstraintTypeStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder ); + } + + Set> build(Executable executable) { + + ConstraintLocation constraintLocation = ConstraintLocation.forCrossParameter( executable ); + + Set> crossParameterConstraints = constraintTypeStaxBuilders.stream() + .map( builder -> builder.build( constraintLocation, java.lang.annotation.ElementType.METHOD, ConstraintType.CROSS_PARAMETER ) ) + .collect( Collectors.toSet() ); + + // ignore annotations + if ( ignoreAnnotations.isPresent() ) { + annotationProcessingOptions.ignoreConstraintAnnotationsForCrossParameterConstraint( + executable, + ignoreAnnotations.get() + ); + } + + return crossParameterConstraints; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/DefaultPackageStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/DefaultPackageStaxBuilder.java new file mode 100644 index 0000000000..a676c0e5c4 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/DefaultPackageStaxBuilder.java @@ -0,0 +1,26 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.util.Optional; + +/** + * Builder for default package. Provides a default package name as defined in the xml + * or {@link Optional#empty()} if none was provided. + * + * @author Marko Bekhta + */ +class DefaultPackageStaxBuilder extends AbstractOneLineStringStaxBuilder { + + private static final String DEFAULT_PACKAGE_QNAME = "default-package"; + + @Override + protected String getAcceptableQName() { + return DEFAULT_PACKAGE_QNAME; + } + +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/GroupConversionStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/GroupConversionStaxBuilder.java new file mode 100644 index 0000000000..f3ca903f8a --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/GroupConversionStaxBuilder.java @@ -0,0 +1,106 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.lang.invoke.MethodHandles; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.validation.groups.Default; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.internal.xml.AbstractStaxBuilder; + +/** + * Builder for group conversions. + * + * @author Marko Bekhta + */ +class GroupConversionStaxBuilder extends AbstractStaxBuilder { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + private static final String GROUP_CONVERSION_TYPE_QNAME_LOCAL_PART = "convert-group"; + private static final QName FROM_QNAME = new QName( "from" ); + private static final QName TO_QNAME = new QName( "to" ); + + private static final String DEFAULT_GROUP_NAME = Default.class.getName(); + + private final ClassLoadingHelper classLoadingHelper; + private final DefaultPackageStaxBuilder defaultPackageStaxBuilder; + + private final Map> groupConversionRules; + + GroupConversionStaxBuilder(ClassLoadingHelper classLoadingHelper, DefaultPackageStaxBuilder defaultPackageStaxBuilder) { + this.classLoadingHelper = classLoadingHelper; + this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; + this.groupConversionRules = new HashMap<>(); + } + + @Override + protected String getAcceptableQName() { + return GROUP_CONVERSION_TYPE_QNAME_LOCAL_PART; + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) { + StartElement startElement = xmlEvent.asStartElement(); + String from = readAttribute( startElement, FROM_QNAME ).orElse( DEFAULT_GROUP_NAME ); + String to = readAttribute( startElement, TO_QNAME ).get(); + groupConversionRules.merge( + from, + Collections.singletonList( to ), + (v1, v2) -> Stream.concat( v1.stream(), v2.stream() ).collect( Collectors.toList() ) + ); + } + + Map, Class> build() { + String defaultPackage = defaultPackageStaxBuilder.build().orElse( "" ); + + Map, List>> resultingMapping = groupConversionRules.entrySet().stream() + .collect( + // Using groupingBy collector to prevent possible loss of information + // as a string value in `from` could possibly contain both qualified and non qualified + // version of a same class from the default package. + Collectors.groupingBy( + entry -> classLoadingHelper.loadClass( entry.getKey(), defaultPackage ), + Collectors.collectingAndThen( + Collectors.toList(), + entries -> entries.stream() + .flatMap( entry -> entry.getValue().stream() ) + .map( className -> classLoadingHelper.loadClass( className, defaultPackage ) ) + .collect( Collectors.toList() ) + ) + + ) + ); + // in case of any duplicates in conversion rules we need to throw an exception: + for ( Map.Entry, List>> entry : resultingMapping.entrySet() ) { + if ( entry.getValue().size() > 1 ) { + throw LOG.getMultipleGroupConversionsForSameSourceException( + entry.getKey(), + entry.getValue() + ); + } + } + + return resultingMapping.entrySet().stream() + .collect( Collectors.toMap( + Map.Entry::getKey, + entry -> entry.getValue().get( 0 ) + ) ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java new file mode 100644 index 0000000000..9180582222 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java @@ -0,0 +1,163 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import static org.hibernate.validator.internal.util.CollectionHelper.newHashMap; +import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.invoke.MethodHandles; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.Validator; + +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.internal.xml.CloseIgnoringInputStream; +import org.hibernate.validator.internal.xml.XmlParserHelper; +import org.xml.sax.SAXException; + +/** + * XML parser for validation-mapping files. + * + * @author Hardy Ferentschik + * @author Marko Bekhta + */ +public class MappingXmlParser { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + private final Set> processedClasses = newHashSet(); + private final ConstraintHelper constraintHelper; + private final TypeResolutionHelper typeResolutionHelper; + private final ValueExtractorManager valueExtractorManager; + private final AnnotationProcessingOptionsImpl annotationProcessingOptions; + private final Map, List>> defaultSequences; + private final Map, Set> constrainedElements; + + private final XmlParserHelper xmlParserHelper; + + private final ClassLoadingHelper classLoadingHelper; + + private static final Map SCHEMAS_BY_VERSION = Collections.unmodifiableMap( getSchemasByVersion() ); + + private static Map getSchemasByVersion() { + Map schemasByVersion = new HashMap<>(); + + schemasByVersion.put( "1.0", "META-INF/validation-mapping-1.0.xsd" ); + schemasByVersion.put( "1.1", "META-INF/validation-mapping-1.1.xsd" ); + schemasByVersion.put( "2.0", "META-INF/validation-mapping-2.0.xsd" ); + + return schemasByVersion; + } + + public MappingXmlParser(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + ClassLoader externalClassLoader) { + this.constraintHelper = constraintHelper; + this.typeResolutionHelper = typeResolutionHelper; + this.valueExtractorManager = valueExtractorManager; + this.annotationProcessingOptions = new AnnotationProcessingOptionsImpl(); + this.defaultSequences = newHashMap(); + this.constrainedElements = newHashMap(); + this.xmlParserHelper = new XmlParserHelper(); + this.classLoadingHelper = new ClassLoadingHelper( externalClassLoader ); + } + + /** + * Parses the given set of input stream representing XML constraint + * mappings. + * + * @param mappingStreams The streams to parse. Must support the mark/reset contract. + */ + public final void parse(Set mappingStreams) { + try { + Set alreadyProcessedConstraintDefinitions = newHashSet(); + for ( InputStream in : mappingStreams ) { + // the InputStreams passed in parameters support mark and reset + in.mark( Integer.MAX_VALUE ); + + XMLEventReader xmlEventReader = xmlParserHelper.createXmlEventReader( "constraint mapping file", new CloseIgnoringInputStream( in ) ); + String schemaVersion = xmlParserHelper.getSchemaVersion( "constraint mapping file", xmlEventReader ); + xmlEventReader.close(); + + in.reset(); + + // The validation is done first as StAX builders used below are assuming that the XML file is correct and don't + // do any validation of the input. + String schemaResourceName = getSchemaResourceName( schemaVersion ); + Schema schema = xmlParserHelper.getSchema( schemaResourceName ); + Validator validator = schema.newValidator(); + validator.validate( new StreamSource( new CloseIgnoringInputStream( in ) ) ); + + in.reset(); + + ConstraintMappingsStaxBuilder constraintMappingsStaxBuilder = new ConstraintMappingsStaxBuilder( + classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, + annotationProcessingOptions, defaultSequences + ); + + xmlEventReader = xmlParserHelper.createXmlEventReader( "constraint mapping file", new CloseIgnoringInputStream( in ) ); + + while ( xmlEventReader.hasNext() ) { + constraintMappingsStaxBuilder.process( xmlEventReader, xmlEventReader.nextEvent() ); + } + constraintMappingsStaxBuilder.build( processedClasses, constrainedElements, alreadyProcessedConstraintDefinitions ); + xmlEventReader.close(); + in.reset(); + } + } + catch (IOException | XMLStreamException | SAXException e) { + throw LOG.getErrorParsingMappingFileException( e ); + } + } + + public final Set> getXmlConfiguredClasses() { + return processedClasses; + } + + public final AnnotationProcessingOptions getAnnotationProcessingOptions() { + return annotationProcessingOptions; + } + + public final Set getConstrainedElementsForClass(Class beanClass) { + if ( constrainedElements.containsKey( beanClass ) ) { + return constrainedElements.get( beanClass ); + } + else { + return Collections.emptySet(); + } + } + + public final List> getDefaultSequenceForClass(Class beanClass) { + return defaultSequences.get( beanClass ); + } + + private String getSchemaResourceName(String schemaVersion) { + String schemaResource = SCHEMAS_BY_VERSION.get( schemaVersion ); + + if ( schemaResource == null ) { + throw LOG.getUnsupportedSchemaVersionException( "constraint mapping file", schemaVersion ); + } + + return schemaResource; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java new file mode 100644 index 0000000000..85cae903e2 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java @@ -0,0 +1,77 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import java.lang.reflect.Executable; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.xml.namespace.QName; + +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.util.ExecutableHelper; +import org.hibernate.validator.internal.util.ReflectionHelper; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.xml.mapping.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; + +/** + * Builder for constraints on return value. + * + * @author Marko Bekhta + */ +class ReturnValueStaxBuilder extends AbstractConstrainedElementStaxBuilder { + + private static final String RETURN_VALUE_QNAME_LOCAL_PART = "return-value"; + + ReturnValueStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, + TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions) { + super( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + } + + @Override + Optional getMainAttributeValueQname() { + return Optional.empty(); + } + + @Override + protected String getAcceptableQName() { + return RETURN_VALUE_QNAME_LOCAL_PART; + } + + CascadingMetaDataBuilder build( + Executable executable, + Set> returnValueConstraints, + Set> returnValueTypeArgumentConstraints) { + + ConstraintLocation constraintLocation = ConstraintLocation.forReturnValue( executable ); + returnValueConstraints.addAll( constraintTypeStaxBuilders.stream() + .map( builder -> builder.build( constraintLocation, ExecutableHelper.getElementType( executable ), ConstraintDescriptorImpl.ConstraintType.GENERIC ) ) + .collect( Collectors.toSet() ) ); + + ContainerElementTypeConfiguration containerElementTypeConfiguration = getContainerElementTypeConfiguration( ReflectionHelper.typeOf( executable ), constraintLocation ); + + returnValueTypeArgumentConstraints.addAll( containerElementTypeConfiguration.getMetaConstraints() ); + + // ignore annotations + if ( ignoreAnnotations.isPresent() ) { + annotationProcessingOptions.ignoreConstraintAnnotationsForReturnValue( + executable, + ignoreAnnotations.get() + ); + } + + return getCascadingMetaData( containerElementTypeConfiguration.getTypeParametersCascadingMetaData(), ReflectionHelper.typeOf( executable ) ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ValidStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ValidStaxBuilder.java new file mode 100644 index 0000000000..7310645fdd --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ValidStaxBuilder.java @@ -0,0 +1,35 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.xml.mapping; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.XMLEvent; + +import org.hibernate.validator.internal.xml.AbstractStaxBuilder; + +/** + * @author Marko Bekhta + */ +class ValidStaxBuilder extends AbstractStaxBuilder { + + private static final String VALID_QNAME_LOCAL_PART = "valid"; + private Boolean cascading; + + @Override + protected String getAcceptableQName() { + return VALID_QNAME_LOCAL_PART; + } + + @Override + protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) { + cascading = true; + } + + public boolean build() { + return cascading == null ? false : true; + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/xml/MappingXmlParserTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/xml/MappingXmlParserTest.java index 517980d41d..0ef2a724f0 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/xml/MappingXmlParserTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/xml/MappingXmlParserTest.java @@ -26,7 +26,7 @@ import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; -import org.hibernate.validator.internal.xml.MappingXmlParser; +import org.hibernate.validator.internal.xml.mapping.MappingXmlParser; import org.hibernate.validator.testutil.TestForIssue; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; From df9cf9fed2b81ebb4494cfb841f37b766439d22f Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 3 Apr 2018 18:49:34 +0200 Subject: [PATCH 005/393] HV-1577 Fix class loading issues --- .../util/privilegedactions/LoadClass.java | 41 +++++++++++++------ .../xml/mapping/ClassLoadingHelper.java | 8 +++- .../xml/mapping/MappingXmlParser.java | 23 ++++++++++- modules/src/script/setupModules.groovy | 9 ++++ 4 files changed, 65 insertions(+), 16 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/LoadClass.java b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/LoadClass.java index da33182ca3..2ea36ccf30 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/LoadClass.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/LoadClass.java @@ -26,6 +26,7 @@ * @author Hardy Ferentschik * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI * @author Gunnar Morling + * @author Guillaume Smet */ public final class LoadClass implements PrivilegedAction> { @@ -37,22 +38,32 @@ public final class LoadClass implements PrivilegedAction> { private final ClassLoader classLoader; + private final ClassLoader initialThreadContextClassLoader; + /** * when true, it will check the Thread Context ClassLoader when the class is not found in the provided one */ private final boolean fallbackOnTCCL; public static LoadClass action(String className, ClassLoader classLoader) { - return new LoadClass( className, classLoader, true ); + return action( className, classLoader, true ); } public static LoadClass action(String className, ClassLoader classLoader, boolean fallbackOnTCCL) { - return new LoadClass( className, classLoader, fallbackOnTCCL ); + return new LoadClass( className, classLoader, null, fallbackOnTCCL ); + } + + /** + * in some cases, the TCCL has been overridden so we need to pass it explicitly. + */ + public static LoadClass action(String className, ClassLoader classLoader, ClassLoader initialThreadContextClassLoader) { + return new LoadClass( className, classLoader, initialThreadContextClassLoader, true ); } - private LoadClass(String className, ClassLoader classLoader, boolean fallbackOnTCCL) { + private LoadClass(String className, ClassLoader classLoader, ClassLoader initialThreadContextClassLoader, boolean fallbackOnTCCL) { this.className = className; this.classLoader = classLoader; + this.initialThreadContextClassLoader = initialThreadContextClassLoader; this.fallbackOnTCCL = fallbackOnTCCL; } @@ -80,7 +91,9 @@ private Class loadClassInValidatorNameSpace() { exception = e; } if ( fallbackOnTCCL ) { - ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + ClassLoader contextClassLoader = initialThreadContextClassLoader != null + ? initialThreadContextClassLoader + : Thread.currentThread().getContextClassLoader(); if ( contextClassLoader != null ) { try { return Class.forName( className, false, contextClassLoader ); @@ -100,20 +113,22 @@ private Class loadClassInValidatorNameSpace() { private Class loadNonValidatorClass() { Exception exception = null; - try { - if ( classLoader != null ) { + if ( classLoader != null ) { + try { return Class.forName( className, false, classLoader ); } - } - catch (ClassNotFoundException e) { - exception = e; - } - catch (RuntimeException e) { - exception = e; + catch (ClassNotFoundException e) { + exception = e; + } + catch (RuntimeException e) { + exception = e; + } } if ( fallbackOnTCCL ) { try { - ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + ClassLoader contextClassLoader = initialThreadContextClassLoader != null + ? initialThreadContextClassLoader + : Thread.currentThread().getContextClassLoader(); if ( contextClassLoader != null ) { return Class.forName( className, false, contextClassLoader ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassLoadingHelper.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassLoadingHelper.java index b7ae1af373..959e3e65b5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassLoadingHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassLoadingHelper.java @@ -20,6 +20,7 @@ * types, qualified names or unqualified names (in which case a given default package will be assumed). * * @author Gunnar Morling + * @author Guillaume Smet */ class ClassLoadingHelper { @@ -47,8 +48,11 @@ class ClassLoadingHelper { private final ClassLoader externalClassLoader; - ClassLoadingHelper(ClassLoader externalClassLoader) { + private final ClassLoader threadContextClassLoader; + + ClassLoadingHelper(ClassLoader externalClassLoader, ClassLoader threadContextClassLoader) { this.externalClassLoader = externalClassLoader; + this.threadContextClassLoader = threadContextClassLoader; } Class loadClass(String className, String defaultPackage) { @@ -80,7 +84,7 @@ Class loadClass(String className, String defaultPackage) { } private Class loadClass(String className) { - return run( LoadClass.action( className, externalClassLoader ) ); + return run( LoadClass.action( className, externalClassLoader, threadContextClassLoader ) ); } private static boolean isArrayClassName(String className) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java index 9180582222..75cbb1bd59 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java @@ -12,6 +12,8 @@ import java.io.IOException; import java.io.InputStream; import java.lang.invoke.MethodHandles; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -32,6 +34,8 @@ import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader; +import org.hibernate.validator.internal.util.privilegedactions.SetContextClassLoader; import org.hibernate.validator.internal.xml.CloseIgnoringInputStream; import org.hibernate.validator.internal.xml.XmlParserHelper; import org.xml.sax.SAXException; @@ -79,7 +83,7 @@ public MappingXmlParser(ConstraintHelper constraintHelper, TypeResolutionHelper this.defaultSequences = newHashMap(); this.constrainedElements = newHashMap(); this.xmlParserHelper = new XmlParserHelper(); - this.classLoadingHelper = new ClassLoadingHelper( externalClassLoader ); + this.classLoadingHelper = new ClassLoadingHelper( externalClassLoader, run( GetClassLoader.fromContext() ) ); } /** @@ -89,7 +93,11 @@ public MappingXmlParser(ConstraintHelper constraintHelper, TypeResolutionHelper * @param mappingStreams The streams to parse. Must support the mark/reset contract. */ public final void parse(Set mappingStreams) { + ClassLoader previousTccl = run( GetClassLoader.fromContext() ); + try { + run( SetContextClassLoader.action( MappingXmlParser.class.getClassLoader() ) ); + Set alreadyProcessedConstraintDefinitions = newHashSet(); for ( InputStream in : mappingStreams ) { // the InputStreams passed in parameters support mark and reset @@ -128,6 +136,9 @@ public final void parse(Set mappingStreams) { catch (IOException | XMLStreamException | SAXException e) { throw LOG.getErrorParsingMappingFileException( e ); } + finally { + run( SetContextClassLoader.action( previousTccl ) ); + } } public final Set> getXmlConfiguredClasses() { @@ -160,4 +171,14 @@ private String getSchemaResourceName(String schemaVersion) { return schemaResource; } + + /** + * Runs the given privileged action, using a privileged block if required. + *

+ * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary + * privileged actions within HV's protection domain. + */ + private static T run(PrivilegedAction action) { + return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); + } } diff --git a/modules/src/script/setupModules.groovy b/modules/src/script/setupModules.groovy index f4763c3c88..ce849302dd 100644 --- a/modules/src/script/setupModules.groovy +++ b/modules/src/script/setupModules.groovy @@ -17,6 +17,10 @@ def appendDependency(File file, String dependencyToAppend, boolean optional) { file.write( file.text.replaceAll( /<\/dependencies>/, ' \n ' ) ) } +def removeDependency(File file, String dependencyToRemove) { + file.write( file.text.replaceAll( //, '' ) ) +} + // BV API bvModuleXml = new File( wildflyPatchedTargetDir, 'modules/system/layers/base/javax/validation/api/main/module.xml' ) def bvArtifactName = 'validation-api-' + project.properties['bv.api.version'] + '.jar'; @@ -34,6 +38,11 @@ println "[INFO] Using HV version " + hvArtifactName; processFileInplace( hvModuleXml ) { text -> text.replaceAll( /hibernate-validator.*jar/, hvArtifactName ) } + +removeDependency( hvModuleXml, "org.apache.xerces" ) +appendDependency( hvModuleXml, "javax.xml.stream.api", false ) +appendDependency( hvModuleXml, "javax.api", false ) + appendDependency( hvModuleXml, "javax.money.api", true ) appendDependency( hvModuleXml, "javafx.api", true ) From 70513144c9bfdeb6d9157ecab768db6dc13f2f80 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Thu, 29 Mar 2018 23:50:06 +0200 Subject: [PATCH 006/393] HV-1577 Fix invalid XML constraint declarations --- .../internal/engine/constraintvalidation/hv-1589-mapping.xml | 2 +- .../internal/engine/constraintvalidation/hv-662-mapping.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/engine/src/test/resources/org/hibernate/validator/test/internal/engine/constraintvalidation/hv-1589-mapping.xml b/engine/src/test/resources/org/hibernate/validator/test/internal/engine/constraintvalidation/hv-1589-mapping.xml index eb78ab7370..96016dd950 100644 --- a/engine/src/test/resources/org/hibernate/validator/test/internal/engine/constraintvalidation/hv-1589-mapping.xml +++ b/engine/src/test/resources/org/hibernate/validator/test/internal/engine/constraintvalidation/hv-1589-mapping.xml @@ -18,7 +18,7 @@ 5 - 10 + 10 diff --git a/engine/src/test/resources/org/hibernate/validator/test/internal/engine/constraintvalidation/hv-662-mapping.xml b/engine/src/test/resources/org/hibernate/validator/test/internal/engine/constraintvalidation/hv-662-mapping.xml index eb78ab7370..96016dd950 100644 --- a/engine/src/test/resources/org/hibernate/validator/test/internal/engine/constraintvalidation/hv-662-mapping.xml +++ b/engine/src/test/resources/org/hibernate/validator/test/internal/engine/constraintvalidation/hv-662-mapping.xml @@ -18,7 +18,7 @@ 5 - 10 + 10 From 0f64f72644a8a0db7779ab20c81c3a36bc2d27b1 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Fri, 30 Mar 2018 00:08:56 +0200 Subject: [PATCH 007/393] HV-1577 Removed JAXB related code - removed builders and supporting privileged actions - removed beans generation from xsd - added javax.xml.bind to forbidden APIs - remove schema normalization --- .../src/main/resources/forbidden-common.txt | 4 + distribution/pom.xml | 2 +- documentation/src/main/asciidoc/ch01.asciidoc | 3 - engine/pom.xml | 103 ------ .../privilegedactions/NewJaxbContext.java | 35 -- .../util/privilegedactions/Unmarshal.java | 40 -- .../xml/ConstrainedExecutableBuilder.java | 345 ------------------ .../internal/xml/ConstrainedFieldBuilder.java | 138 ------- .../xml/ConstrainedGetterBuilder.java | 146 -------- .../xml/ConstrainedParameterBuilder.java | 113 ------ .../internal/xml/ConstrainedTypeBuilder.java | 99 ----- ...tainerElementTypeConfigurationBuilder.java | 186 ---------- .../internal/xml/GroupConversionBuilder.java | 57 --- .../internal/xml/LocalNamespace.java | 31 -- .../internal/xml/MetaConstraintBuilder.java | 327 ----------------- ...paceNormalizingXMLEventReaderDelegate.java | 101 ----- .../internal/xml/XmlParserHelper.java | 27 +- .../xml/config/ValidationXmlParser.java | 2 +- engine/src/main/xjb/binding-customization.xjb | 30 -- pom.xml | 8 - tck-runner/src/test/resources/test.policy | 4 - 21 files changed, 9 insertions(+), 1792 deletions(-) delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/NewJaxbContext.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/Unmarshal.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedExecutableBuilder.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedFieldBuilder.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedGetterBuilder.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedParameterBuilder.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedTypeBuilder.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/ContainerElementTypeConfigurationBuilder.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/GroupConversionBuilder.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/LocalNamespace.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/MetaConstraintBuilder.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/xml/NamespaceNormalizingXMLEventReaderDelegate.java delete mode 100644 engine/src/main/xjb/binding-customization.xjb diff --git a/build-config/src/main/resources/forbidden-common.txt b/build-config/src/main/resources/forbidden-common.txt index 3f02a90e8f..47ae8513d0 100644 --- a/build-config/src/main/resources/forbidden-common.txt +++ b/build-config/src/main/resources/forbidden-common.txt @@ -26,3 +26,7 @@ org.assertj.core.api.Assertions#fail() java.lang.StringBuffer org.jboss.logging.processor.util.Objects + +################################################################################################################ +# JAXB shouldn't be used anymore as it is targeted to be removed from the JDK +javax.xml.bind.** diff --git a/distribution/pom.xml b/distribution/pom.xml index 09afdfb706..dcbb0a4d8d 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -207,7 +207,7 @@ [9,) - -html5 --add-modules=${maven-javadoc-plugin.jigsaw.modules} + -html5 diff --git a/documentation/src/main/asciidoc/ch01.asciidoc b/documentation/src/main/asciidoc/ch01.asciidoc index 9463a8e47a..2465cbc765 100644 --- a/documentation/src/main/asciidoc/ch01.asciidoc +++ b/documentation/src/main/asciidoc/ch01.asciidoc @@ -206,9 +206,6 @@ These are the module names as declared using the `Automatic-Module-Name` header: These module names are preliminary and may be changed when providing real module descriptors in a future release. -When using Bean Validation XML descriptors (_META-INF/validation.xml_ and/or constraint mapping files), the `java.xml.bind` module must be enabled. -Do so by appending `--add-modules java.xml.bind` to your _java_ invocation. - [WARNING] ==== When using Hibernate Validator with CDI, be careful to not enable the `java.xml.ws.annotation` module of the JDK. diff --git a/engine/pom.xml b/engine/pom.xml index 903f7878ed..fd6d26aa8b 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -273,39 +273,6 @@ - - pre-jdk9 - - 1.8 - - - - - org.codehaus.mojo - jaxb2-maven-plugin - - - - xjc - - - - - org.hibernate.validator.internal.xml.binding - true - - true - - 2.1 - - src/main/xsd/validation-configuration-2.0.xsd - src/main/xsd/validation-mapping-2.0.xsd - - - - - - jdk9 @@ -314,76 +281,6 @@ --illegal-access=deny - - - - org.apache.maven.plugins - maven-antrun-plugin - - - generate-sources - - - - - - - - run - - - - - - org.codehaus.mojo - exec-maven-plugin - - - generate schema types - generate-sources - - exec - - - - - xjc - - -enableIntrospection - -p - org.hibernate.validator.internal.xml.binding - -extension - -target - 2.1 - -d - target/generated-sources/jaxb - src/main/xsd/validation-configuration-2.0.xsd - src/main/xsd/validation-mapping-2.0.xsd - -b - src/main/xjb/binding-customization.xjb - - - - - org.codehaus.mojo - build-helper-maven-plugin - - - add-source - generate-sources - - add-source - - - - target/generated-sources/jaxb - - - - - - - sigtest diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/NewJaxbContext.java b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/NewJaxbContext.java deleted file mode 100644 index cb8f7e16da..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/NewJaxbContext.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.util.privilegedactions; - -import java.security.PrivilegedExceptionAction; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; - -/** - * Returns a new {@link JAXBContext} for the given class. - * - * @author Gunnar Morling - */ -public final class NewJaxbContext implements PrivilegedExceptionAction { - - private final Class clazz; - - public static NewJaxbContext action(Class clazz) { - return new NewJaxbContext( clazz ); - } - - private NewJaxbContext(Class clazz) { - this.clazz = clazz; - } - - @Override - public JAXBContext run() throws JAXBException { - return JAXBContext.newInstance( clazz ); - } -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/Unmarshal.java b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/Unmarshal.java deleted file mode 100644 index 73073081f3..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/Unmarshal.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.util.privilegedactions; - -import java.security.PrivilegedExceptionAction; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import javax.xml.stream.XMLEventReader; - -/** - * Unmarshals the given source. - * - * @author Gunnar Morling - */ -public final class Unmarshal implements PrivilegedExceptionAction> { - - private final Unmarshaller unmarshaller; - private final XMLEventReader xmlEventReader; - private final Class clazz; - - public static Unmarshal action(Unmarshaller unmarshaller, XMLEventReader xmlEventReader, Class clazz) { - return new Unmarshal( unmarshaller, xmlEventReader, clazz ); - } - - private Unmarshal(Unmarshaller unmarshaller, XMLEventReader xmlEventReader, Class clazz) { - this.unmarshaller = unmarshaller; - this.xmlEventReader = xmlEventReader; - this.clazz = clazz; - } - - @Override - public JAXBElement run() throws JAXBException { - return unmarshaller.unmarshal( xmlEventReader, clazz ); - } -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedExecutableBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedExecutableBuilder.java deleted file mode 100644 index 8bad5a9511..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedExecutableBuilder.java +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.xml; - -import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; -import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; - -import java.lang.invoke.MethodHandles; -import java.lang.reflect.Constructor; -import java.lang.reflect.Executable; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.validation.ValidationException; - -import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; -import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.MetaConstraint; -import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; -import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; -import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; -import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; -import org.hibernate.validator.internal.util.ExecutableHelper; -import org.hibernate.validator.internal.util.ReflectionHelper; -import org.hibernate.validator.internal.util.logging.Log; -import org.hibernate.validator.internal.util.logging.LoggerFactory; -import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredConstructor; -import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethod; -import org.hibernate.validator.internal.xml.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; -import org.hibernate.validator.internal.xml.binding.ConstraintType; -import org.hibernate.validator.internal.xml.binding.ConstructorType; -import org.hibernate.validator.internal.xml.binding.CrossParameterType; -import org.hibernate.validator.internal.xml.binding.MethodType; -import org.hibernate.validator.internal.xml.binding.ParameterType; -import org.hibernate.validator.internal.xml.binding.ReturnValueType; - -/** - * Builder for constrained methods and constructors. - * - * @author Hardy Ferentschik - * @author Guillaume Smet - */ -class ConstrainedExecutableBuilder { - - private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - - private final ClassLoadingHelper classLoadingHelper; - private final MetaConstraintBuilder metaConstraintBuilder; - private final GroupConversionBuilder groupConversionBuilder; - private final ConstrainedParameterBuilder constrainedParameterBuilder; - private final AnnotationProcessingOptionsImpl annotationProcessingOptions; - - ConstrainedExecutableBuilder(ClassLoadingHelper classLoadingHelper, MetaConstraintBuilder metaConstraintBuilder, - GroupConversionBuilder groupConversionBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions) { - this.classLoadingHelper = classLoadingHelper; - this.metaConstraintBuilder = metaConstraintBuilder; - this.groupConversionBuilder = groupConversionBuilder; - this.constrainedParameterBuilder = new ConstrainedParameterBuilder( - metaConstraintBuilder, - groupConversionBuilder, - annotationProcessingOptions - ); - this.annotationProcessingOptions = annotationProcessingOptions; - } - - Set buildMethodConstrainedExecutable(List methods, - Class beanClass, - String defaultPackage) { - Set constrainedExecutables = newHashSet(); - List alreadyProcessedMethods = newArrayList(); - for ( MethodType methodType : methods ) { - // parse the parameters - List> parameterTypes = createParameterTypes( - methodType.getParameter(), - beanClass, - defaultPackage - ); - - String methodName = methodType.getName(); - - final Method method = run( - GetDeclaredMethod.action( - beanClass, - methodName, - parameterTypes.toArray( new Class[parameterTypes.size()] ) - ) - ); - - if ( method == null ) { - throw LOG.getBeanDoesNotContainMethodException( - beanClass, - methodName, - parameterTypes.toArray( new Class[parameterTypes.size()] ) - ); - } - - if ( alreadyProcessedMethods.contains( method ) ) { - throw LOG.getMethodIsDefinedTwiceInMappingXmlForBeanException( method, beanClass ); - } - else { - alreadyProcessedMethods.add( method ); - } - - // ignore annotations - if ( methodType.getIgnoreAnnotations() != null ) { - annotationProcessingOptions.ignoreConstraintAnnotationsOnMember( - method, - methodType.getIgnoreAnnotations() - ); - } - - ConstrainedExecutable constrainedExecutable = parseExecutableType( - defaultPackage, - methodType.getParameter(), - methodType.getCrossParameter(), - methodType.getReturnValue(), - method - ); - - constrainedExecutables.add( constrainedExecutable ); - } - return constrainedExecutables; - } - - Set buildConstructorConstrainedExecutable(List constructors, - Class beanClass, - String defaultPackage) { - Set constrainedExecutables = newHashSet(); - List> alreadyProcessedConstructors = newArrayList(); - for ( ConstructorType constructorType : constructors ) { - // parse the parameters - List> constructorParameterTypes = createParameterTypes( - constructorType.getParameter(), - beanClass, - defaultPackage - ); - - final Constructor constructor = run( - GetDeclaredConstructor.action( - beanClass, - constructorParameterTypes.toArray( new Class[constructorParameterTypes.size()] ) - ) - ); - - if ( constructor == null ) { - throw LOG.getBeanDoesNotContainConstructorException( - beanClass, - constructorParameterTypes.toArray( new Class[constructorParameterTypes.size()] ) - ); - } - if ( alreadyProcessedConstructors.contains( constructor ) ) { - throw LOG.getConstructorIsDefinedTwiceInMappingXmlForBeanException( - constructor, - beanClass - ); - } - else { - alreadyProcessedConstructors.add( constructor ); - } - - // ignore annotations - if ( constructorType.getIgnoreAnnotations() != null ) { - annotationProcessingOptions.ignoreConstraintAnnotationsOnMember( - constructor, - constructorType.getIgnoreAnnotations() - ); - } - - ConstrainedExecutable constrainedExecutable = parseExecutableType( - defaultPackage, - constructorType.getParameter(), - constructorType.getCrossParameter(), - constructorType.getReturnValue(), - constructor - ); - constrainedExecutables.add( constrainedExecutable ); - } - return constrainedExecutables; - } - - private ConstrainedExecutable parseExecutableType(String defaultPackage, - List parameterTypeList, - CrossParameterType crossParameterType, - ReturnValueType returnValueType, - Executable executable) { - List parameterMetaData = constrainedParameterBuilder.buildConstrainedParameters( - parameterTypeList, - executable, - defaultPackage - ); - - Set> crossParameterConstraints = parseCrossParameterConstraints( - defaultPackage, - crossParameterType, - executable - ); - - // parse the return value - Set> returnValueConstraints = new HashSet<>(); - Set> returnValueTypeArgumentConstraints = new HashSet<>(); - CascadingMetaDataBuilder cascadingMetaDataBuilder = parseReturnValueType( - returnValueType, - executable, - returnValueConstraints, - returnValueTypeArgumentConstraints, - defaultPackage - ); - - return new ConstrainedExecutable( - ConfigurationSource.XML, - executable, - parameterMetaData, - crossParameterConstraints, - returnValueConstraints, - returnValueTypeArgumentConstraints, - cascadingMetaDataBuilder - ); - } - - private Set> parseCrossParameterConstraints(String defaultPackage, - CrossParameterType crossParameterType, - Executable executable) { - - Set> crossParameterConstraints = newHashSet(); - if ( crossParameterType == null ) { - return crossParameterConstraints; - } - - ConstraintLocation constraintLocation = ConstraintLocation.forCrossParameter( executable ); - - for ( ConstraintType constraintType : crossParameterType.getConstraint() ) { - MetaConstraint metaConstraint = metaConstraintBuilder.buildMetaConstraint( - constraintLocation, - constraintType, - ExecutableHelper.getElementType( executable ), - defaultPackage, - ConstraintDescriptorImpl.ConstraintType.CROSS_PARAMETER - ); - crossParameterConstraints.add( metaConstraint ); - } - - // ignore annotations - if ( crossParameterType.getIgnoreAnnotations() != null ) { - annotationProcessingOptions.ignoreConstraintAnnotationsForCrossParameterConstraint( - executable, - crossParameterType.getIgnoreAnnotations() - ); - } - - return crossParameterConstraints; - } - - private CascadingMetaDataBuilder parseReturnValueType(ReturnValueType returnValueType, - Executable executable, - Set> returnValueConstraints, - Set> returnValueTypeArgumentConstraints, - String defaultPackage) { - if ( returnValueType == null ) { - return CascadingMetaDataBuilder.nonCascading(); - } - - ConstraintLocation constraintLocation = ConstraintLocation.forReturnValue( executable ); - for ( ConstraintType constraint : returnValueType.getConstraint() ) { - MetaConstraint metaConstraint = metaConstraintBuilder.buildMetaConstraint( - constraintLocation, - constraint, - ExecutableHelper.getElementType( executable ), - defaultPackage, - ConstraintDescriptorImpl.ConstraintType.GENERIC - ); - returnValueConstraints.add( metaConstraint ); - } - - ContainerElementTypeConfigurationBuilder containerElementTypeConfigurationBuilder = new ContainerElementTypeConfigurationBuilder( - metaConstraintBuilder, groupConversionBuilder, constraintLocation, defaultPackage ); - ContainerElementTypeConfiguration containerElementTypeConfiguration = containerElementTypeConfigurationBuilder - .build( returnValueType.getContainerElementType(), ReflectionHelper.typeOf( executable ) ); - - returnValueTypeArgumentConstraints.addAll( containerElementTypeConfiguration.getMetaConstraints() ); - - // ignore annotations - if ( returnValueType.getIgnoreAnnotations() != null ) { - annotationProcessingOptions.ignoreConstraintAnnotationsForReturnValue( - executable, - returnValueType.getIgnoreAnnotations() - ); - } - - return getCascadingMetaDataForReturnValue( containerElementTypeConfiguration.getTypeParametersCascadingMetaData(), executable, returnValueType, - defaultPackage ); - } - - private List> createParameterTypes(List parameterList, - Class beanClass, - String defaultPackage) { - List> parameterTypes = newArrayList(); - for ( ParameterType parameterType : parameterList ) { - String type = null; - try { - type = parameterType.getType(); - Class parameterClass = classLoadingHelper.loadClass( type, defaultPackage ); - parameterTypes.add( parameterClass ); - } - catch (ValidationException e) { - throw LOG.getInvalidParameterTypeException( type, beanClass ); - } - } - - return parameterTypes; - } - - private CascadingMetaDataBuilder getCascadingMetaDataForReturnValue(Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaData, Executable executable, - ReturnValueType returnValueType, String defaultPackage) { - Type type = ReflectionHelper.typeOf( executable ); - boolean isCascaded = returnValueType.getValid() != null; - Map, Class> groupConversions = groupConversionBuilder.buildGroupConversionMap( - returnValueType.getConvertGroup(), - defaultPackage - ); - - return CascadingMetaDataBuilder.annotatedObject( type, isCascaded, containerElementTypesCascadingMetaData, groupConversions ); - } - - /** - * Runs the given privileged action, using a privileged block if required. - *

- * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary - * privileged actions within HV's protection domain. - */ - private static T run(PrivilegedAction action) { - return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); - } -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedFieldBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedFieldBuilder.java deleted file mode 100644 index f36ed6e054..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedFieldBuilder.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.xml; - -import java.lang.invoke.MethodHandles; -import java.lang.reflect.Field; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; -import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.MetaConstraint; -import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; -import org.hibernate.validator.internal.metadata.raw.ConstrainedField; -import org.hibernate.validator.internal.util.ReflectionHelper; -import org.hibernate.validator.internal.util.logging.Log; -import org.hibernate.validator.internal.util.logging.LoggerFactory; -import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredField; -import org.hibernate.validator.internal.xml.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; -import org.hibernate.validator.internal.xml.binding.ConstraintType; -import org.hibernate.validator.internal.xml.binding.FieldType; - -/** - * Builder for constraint fields. - * - * @author Hardy Ferentschik - * @author Guillaume Smet - */ -class ConstrainedFieldBuilder { - private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - - private final GroupConversionBuilder groupConversionBuilder; - private final MetaConstraintBuilder metaConstraintBuilder; - private final AnnotationProcessingOptionsImpl annotationProcessingOptions; - - ConstrainedFieldBuilder(MetaConstraintBuilder metaConstraintBuilder, GroupConversionBuilder groupConversionBuilder, - AnnotationProcessingOptionsImpl annotationProcessingOptions) { - this.metaConstraintBuilder = metaConstraintBuilder; - this.groupConversionBuilder = groupConversionBuilder; - this.annotationProcessingOptions = annotationProcessingOptions; - } - - Set buildConstrainedFields(List fields, - Class beanClass, - String defaultPackage) { - Set constrainedFields = new HashSet<>(); - List alreadyProcessedFieldNames = new ArrayList<>(); - for ( FieldType fieldType : fields ) { - Field field = findField( beanClass, fieldType.getName(), alreadyProcessedFieldNames ); - ConstraintLocation constraintLocation = ConstraintLocation.forField( field ); - Set> metaConstraints = new HashSet<>(); - - for ( ConstraintType constraint : fieldType.getConstraint() ) { - MetaConstraint metaConstraint = metaConstraintBuilder.buildMetaConstraint( - constraintLocation, - constraint, - java.lang.annotation.ElementType.FIELD, - defaultPackage, - null - ); - metaConstraints.add( metaConstraint ); - } - - ContainerElementTypeConfigurationBuilder containerElementTypeConfigurationBuilder = new ContainerElementTypeConfigurationBuilder( - metaConstraintBuilder, groupConversionBuilder, constraintLocation, defaultPackage ); - ContainerElementTypeConfiguration containerElementTypeConfiguration = containerElementTypeConfigurationBuilder - .build( fieldType.getContainerElementType(), ReflectionHelper.typeOf( field ) ); - - ConstrainedField constrainedField = new ConstrainedField( - ConfigurationSource.XML, - field, - metaConstraints, - containerElementTypeConfiguration.getMetaConstraints(), - getCascadingMetaDataForField( containerElementTypeConfiguration.getTypeParametersCascadingMetaData(), field, fieldType, defaultPackage ) - ); - constrainedFields.add( constrainedField ); - - // ignore annotations - if ( fieldType.getIgnoreAnnotations() != null ) { - annotationProcessingOptions.ignoreConstraintAnnotationsOnMember( - field, - fieldType.getIgnoreAnnotations() - ); - } - } - - return constrainedFields; - } - - private CascadingMetaDataBuilder getCascadingMetaDataForField(Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaData, Field field, - FieldType fieldType, String defaultPackage) { - Type type = ReflectionHelper.typeOf( field ); - boolean isCascaded = fieldType.getValid() != null; - Map, Class> groupConversions = groupConversionBuilder.buildGroupConversionMap( - fieldType.getConvertGroup(), - defaultPackage - ); - - return CascadingMetaDataBuilder.annotatedObject( type, isCascaded, containerElementTypesCascadingMetaData, groupConversions ); - } - - private static Field findField(Class beanClass, String fieldName, List alreadyProcessedFieldNames) { - if ( alreadyProcessedFieldNames.contains( fieldName ) ) { - throw LOG.getIsDefinedTwiceInMappingXmlForBeanException( fieldName, beanClass ); - } - else { - alreadyProcessedFieldNames.add( fieldName ); - } - - final Field field = run( GetDeclaredField.action( beanClass, fieldName ) ); - if ( field == null ) { - throw LOG.getBeanDoesNotContainTheFieldException( beanClass, fieldName ); - } - return field; - } - - /** - * Runs the given privileged action, using a privileged block if required. - *

- * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary - * privileged actions within HV's protection domain. - */ - private static T run(PrivilegedAction action) { - return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); - } -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedGetterBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedGetterBuilder.java deleted file mode 100644 index f78c94f4e2..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedGetterBuilder.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.xml; - -import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; -import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; - -import java.lang.invoke.MethodHandles; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; -import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.MetaConstraint; -import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; -import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; -import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; -import org.hibernate.validator.internal.util.ReflectionHelper; -import org.hibernate.validator.internal.util.logging.Log; -import org.hibernate.validator.internal.util.logging.LoggerFactory; -import org.hibernate.validator.internal.util.privilegedactions.GetMethodFromPropertyName; -import org.hibernate.validator.internal.xml.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; -import org.hibernate.validator.internal.xml.binding.ConstraintType; -import org.hibernate.validator.internal.xml.binding.GetterType; - -/** - * Builder for constraint getters. - * - * @author Hardy Ferentschik - * @author Guillaume Smet - */ -class ConstrainedGetterBuilder { - - private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - - private final GroupConversionBuilder groupConversionBuilder; - private final MetaConstraintBuilder metaConstraintBuilder; - private final AnnotationProcessingOptionsImpl annotationProcessingOptions; - - ConstrainedGetterBuilder(MetaConstraintBuilder metaConstraintBuilder, GroupConversionBuilder groupConversionBuilder, - AnnotationProcessingOptionsImpl annotationProcessingOptions) { - this.metaConstraintBuilder = metaConstraintBuilder; - this.groupConversionBuilder = groupConversionBuilder; - this.annotationProcessingOptions = annotationProcessingOptions; - } - - Set buildConstrainedGetters(List getterList, - Class beanClass, - String defaultPackage) { - Set constrainedExecutables = newHashSet(); - List alreadyProcessedGetterNames = newArrayList(); - for ( GetterType getterType : getterList ) { - String getterName = getterType.getName(); - Method getter = findGetter( beanClass, getterName, alreadyProcessedGetterNames ); - ConstraintLocation constraintLocation = ConstraintLocation.forGetter( getter ); - - Set> metaConstraints = newHashSet(); - for ( ConstraintType constraint : getterType.getConstraint() ) { - MetaConstraint metaConstraint = metaConstraintBuilder.buildMetaConstraint( - constraintLocation, - constraint, - java.lang.annotation.ElementType.METHOD, - defaultPackage, - null - ); - metaConstraints.add( metaConstraint ); - } - - ContainerElementTypeConfigurationBuilder containerElementTypeConfigurationBuilder = new ContainerElementTypeConfigurationBuilder( - metaConstraintBuilder, groupConversionBuilder, constraintLocation, defaultPackage ); - ContainerElementTypeConfiguration containerElementTypeConfiguration = containerElementTypeConfigurationBuilder - .build( getterType.getContainerElementType(), ReflectionHelper.typeOf( getter ) ); - - ConstrainedExecutable constrainedGetter = new ConstrainedExecutable( - ConfigurationSource.XML, - getter, - Collections.emptyList(), - Collections.>emptySet(), - metaConstraints, - containerElementTypeConfiguration.getMetaConstraints(), - getCascadingMetaDataForGetter( containerElementTypeConfiguration.getTypeParametersCascadingMetaData(), getter, getterType, defaultPackage ) - ); - constrainedExecutables.add( constrainedGetter ); - - // ignore annotations - if ( getterType.getIgnoreAnnotations() != null ) { - annotationProcessingOptions.ignoreConstraintAnnotationsOnMember( - getter, - getterType.getIgnoreAnnotations() - ); - } - } - - return constrainedExecutables; - } - - private CascadingMetaDataBuilder getCascadingMetaDataForGetter(Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaData, Method method, - GetterType getterType, String defaultPackage) { - Type type = ReflectionHelper.typeOf( method ); - boolean isCascaded = getterType.getValid() != null; - Map, Class> groupConversions = groupConversionBuilder.buildGroupConversionMap( - getterType.getConvertGroup(), - defaultPackage - ); - - return CascadingMetaDataBuilder.annotatedObject( type, isCascaded, containerElementTypesCascadingMetaData, groupConversions ); - } - - private static Method findGetter(Class beanClass, String getterName, List alreadyProcessedGetterNames) { - if ( alreadyProcessedGetterNames.contains( getterName ) ) { - throw LOG.getIsDefinedTwiceInMappingXmlForBeanException( getterName, beanClass ); - } - else { - alreadyProcessedGetterNames.add( getterName ); - } - - final Method method = run( GetMethodFromPropertyName.action( beanClass, getterName ) ); - if ( method == null ) { - throw LOG.getBeanDoesNotContainThePropertyException( beanClass, getterName ); - } - - return method; - } - - /** - * Runs the given privileged action, using a privileged block if required. - *

- * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary - * privileged actions within HV's protection domain. - */ - private static T run(PrivilegedAction action) { - return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); - } -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedParameterBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedParameterBuilder.java deleted file mode 100644 index 576d6de700..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedParameterBuilder.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.xml; - -import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; - -import java.lang.annotation.ElementType; -import java.lang.reflect.Executable; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; -import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.MetaConstraint; -import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; -import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; -import org.hibernate.validator.internal.util.ReflectionHelper; -import org.hibernate.validator.internal.xml.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; -import org.hibernate.validator.internal.xml.binding.ConstraintType; -import org.hibernate.validator.internal.xml.binding.ParameterType; - -/** - * Builder for constraint parameters. - * - * @author Hardy Ferentschik - * @author Guillaume Smet - */ -class ConstrainedParameterBuilder { - - private final GroupConversionBuilder groupConversionBuilder; - private final MetaConstraintBuilder metaConstraintBuilder; - private final AnnotationProcessingOptionsImpl annotationProcessingOptions; - - ConstrainedParameterBuilder(MetaConstraintBuilder metaConstraintBuilder, - GroupConversionBuilder groupConversionBuilder, - AnnotationProcessingOptionsImpl annotationProcessingOptions) { - this.metaConstraintBuilder = metaConstraintBuilder; - this.groupConversionBuilder = groupConversionBuilder; - this.annotationProcessingOptions = annotationProcessingOptions; - } - - List buildConstrainedParameters(List parameterList, - Executable executable, - String defaultPackage) { - List constrainedParameters = newArrayList(); - int i = 0; - for ( ParameterType parameterType : parameterList ) { - ConstraintLocation constraintLocation = ConstraintLocation.forParameter( executable, i ); - Type type = ReflectionHelper.typeOf( executable, i ); - - Set> metaConstraints = new HashSet<>(); - for ( ConstraintType constraint : parameterType.getConstraint() ) { - MetaConstraint metaConstraint = metaConstraintBuilder.buildMetaConstraint( - constraintLocation, - constraint, - ElementType.PARAMETER, - defaultPackage, - null - ); - metaConstraints.add( metaConstraint ); - } - - ContainerElementTypeConfigurationBuilder containerElementTypeConfigurationBuilder = new ContainerElementTypeConfigurationBuilder( - metaConstraintBuilder, groupConversionBuilder, constraintLocation, defaultPackage ); - ContainerElementTypeConfiguration containerElementTypeConfiguration = containerElementTypeConfigurationBuilder - .build( parameterType.getContainerElementType(), type ); - - // ignore annotations - if ( parameterType.getIgnoreAnnotations() != null ) { - annotationProcessingOptions.ignoreConstraintAnnotationsOnParameter( - executable, - i, - parameterType.getIgnoreAnnotations() - ); - } - - ConstrainedParameter constrainedParameter = new ConstrainedParameter( - ConfigurationSource.XML, - executable, - type, - i, - metaConstraints, - containerElementTypeConfiguration.getMetaConstraints(), - getCascadingMetaDataForParameter( containerElementTypeConfiguration.getTypeParametersCascadingMetaData(), type, parameterType, defaultPackage ) - ); - constrainedParameters.add( constrainedParameter ); - i++; - } - - return constrainedParameters; - } - - - private CascadingMetaDataBuilder getCascadingMetaDataForParameter(Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaData, Type type, - ParameterType parameterType, String defaultPackage) { - boolean isCascaded = parameterType.getValid() != null; - Map, Class> groupConversions = groupConversionBuilder.buildGroupConversionMap( - parameterType.getConvertGroup(), - defaultPackage - ); - - return CascadingMetaDataBuilder.annotatedObject( type, isCascaded, containerElementTypesCascadingMetaData, groupConversions ); - } -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedTypeBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedTypeBuilder.java deleted file mode 100644 index 4c54ae39ad..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/ConstrainedTypeBuilder.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.xml; - -import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; -import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.MetaConstraint; -import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; -import org.hibernate.validator.internal.metadata.raw.ConstrainedType; -import org.hibernate.validator.internal.xml.binding.ClassType; -import org.hibernate.validator.internal.xml.binding.ConstraintType; -import org.hibernate.validator.internal.xml.binding.GroupSequenceType; - -/** - * Builder for constraint types. - * - * @author Hardy Ferentschik - */ -class ConstrainedTypeBuilder { - - private final ClassLoadingHelper classLoadingHelper; - private final MetaConstraintBuilder metaConstraintBuilder; - private final AnnotationProcessingOptionsImpl annotationProcessingOptions; - private final Map, List>> defaultSequences; - - public ConstrainedTypeBuilder(ClassLoadingHelper classLoadingHelper, - MetaConstraintBuilder metaConstraintBuilder, - AnnotationProcessingOptionsImpl annotationProcessingOptions, - Map, List>> defaultSequences) { - this.classLoadingHelper = classLoadingHelper; - this.metaConstraintBuilder = metaConstraintBuilder; - this.annotationProcessingOptions = annotationProcessingOptions; - this.defaultSequences = defaultSequences; - } - - ConstrainedType buildConstrainedType(ClassType classType, Class beanClass, String defaultPackage) { - if ( classType == null ) { - return null; - } - - // group sequence - List> groupSequence = createGroupSequence( classType.getGroupSequence(), defaultPackage ); - if ( !groupSequence.isEmpty() ) { - defaultSequences.put( beanClass, groupSequence ); - } - - // constraints - ConstraintLocation constraintLocation = ConstraintLocation.forClass( beanClass ); - Set> metaConstraints = newHashSet(); - for ( ConstraintType constraint : classType.getConstraint() ) { - MetaConstraint metaConstraint = metaConstraintBuilder.buildMetaConstraint( - constraintLocation, - constraint, - java.lang.annotation.ElementType.TYPE, - defaultPackage, - null - ); - metaConstraints.add( metaConstraint ); - } - - // ignore annotation - if ( classType.getIgnoreAnnotations() != null ) { - annotationProcessingOptions.ignoreClassLevelConstraintAnnotations( - beanClass, - classType.getIgnoreAnnotations() - ); - } - - return new ConstrainedType( - ConfigurationSource.XML, - beanClass, - metaConstraints - ); - } - - private List> createGroupSequence(GroupSequenceType groupSequenceType, String defaultPackage) { - List> groupSequence = newArrayList(); - if ( groupSequenceType != null ) { - for ( String groupName : groupSequenceType.getValue() ) { - Class group = classLoadingHelper.loadClass( groupName, defaultPackage ); - groupSequence.add( group ); - } - } - return groupSequence; - } -} - - diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/ContainerElementTypeConfigurationBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/ContainerElementTypeConfigurationBuilder.java deleted file mode 100644 index 521fbfd3c7..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/ContainerElementTypeConfigurationBuilder.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.xml; - -import java.lang.invoke.MethodHandles; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.hibernate.validator.internal.engine.valueextraction.ArrayElement; -import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; -import org.hibernate.validator.internal.metadata.core.MetaConstraint; -import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.util.CollectionHelper; -import org.hibernate.validator.internal.util.ReflectionHelper; -import org.hibernate.validator.internal.util.TypeHelper; -import org.hibernate.validator.internal.util.logging.Log; -import org.hibernate.validator.internal.util.logging.LoggerFactory; -import org.hibernate.validator.internal.xml.binding.ConstraintType; -import org.hibernate.validator.internal.xml.binding.ContainerElementTypeType; - -/** - * Builds the cascading and type argument constraints configuration from the {@link ContainerElementType} elements. - * - * @author Guillaume Smet - */ -class ContainerElementTypeConfigurationBuilder { - - private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - - private final ConstraintLocation rootConstraintLocation; - - private final MetaConstraintBuilder metaConstraintBuilder; - - private final GroupConversionBuilder groupConversionBuilder; - - private final String defaultPackage; - - private final Set configuredPaths = new HashSet<>(); - - ContainerElementTypeConfigurationBuilder(MetaConstraintBuilder metaConstraintBuilder, GroupConversionBuilder groupConversionBuilder, - ConstraintLocation rootConstraintLocation, String defaultPackage) { - this.metaConstraintBuilder = metaConstraintBuilder; - this.groupConversionBuilder = groupConversionBuilder; - this.rootConstraintLocation = rootConstraintLocation; - this.defaultPackage = defaultPackage; - } - - ContainerElementTypeConfiguration build(List xmlContainerElementTypes, Type enclosingType) { - return add( ContainerElementTypePath.root(), xmlContainerElementTypes, rootConstraintLocation, enclosingType ); - } - - private ContainerElementTypeConfiguration add(ContainerElementTypePath parentConstraintElementTypePath, List xmlContainerElementTypes, - ConstraintLocation parentConstraintLocation, Type enclosingType) { - if ( xmlContainerElementTypes.isEmpty() ) { - return new ContainerElementTypeConfiguration( Collections.emptySet(), Collections.emptyMap() ); - } - - // HV-1428 Container element support is disabled for arrays - if ( TypeHelper.isArray( enclosingType ) ) { - throw LOG.getContainerElementConstraintsAndCascadedValidationNotSupportedOnArraysException( enclosingType ); - } - - if ( !( enclosingType instanceof ParameterizedType ) && !TypeHelper.isArray( enclosingType ) ) { - throw LOG.getTypeIsNotAParameterizedNorArrayTypeException( enclosingType ); - } - - Set> metaConstraints = new HashSet<>(); - Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaDataBuilder = - CollectionHelper.newHashMap( xmlContainerElementTypes.size() ); - - boolean isArray = TypeHelper.isArray( enclosingType ); - TypeVariable[] typeParameters = isArray ? new TypeVariable[0] : ReflectionHelper.getClassFromType( enclosingType ).getTypeParameters(); - - for ( ContainerElementTypeType xmlContainerElementType : xmlContainerElementTypes ) { - Integer typeArgumentIndex = getTypeArgumentIndex( xmlContainerElementType, typeParameters, isArray, enclosingType ); - - ContainerElementTypePath constraintElementTypePath = ContainerElementTypePath.of( parentConstraintElementTypePath, typeArgumentIndex ); - boolean configuredBefore = !configuredPaths.add( constraintElementTypePath ); - if ( configuredBefore ) { - throw LOG.getContainerElementTypeHasAlreadyBeenConfiguredViaXmlMappingConfigurationException( rootConstraintLocation, constraintElementTypePath ); - } - - TypeVariable typeParameter = getTypeParameter( typeParameters, typeArgumentIndex, isArray, enclosingType ); - Type containerElementType = getContainerElementType( enclosingType, typeArgumentIndex, isArray ); - ConstraintLocation containerElementTypeConstraintLocation = ConstraintLocation.forTypeArgument( parentConstraintLocation, typeParameter, - containerElementType ); - - for ( ConstraintType constraint : xmlContainerElementType.getConstraint() ) { - MetaConstraint metaConstraint = metaConstraintBuilder.buildMetaConstraint( - containerElementTypeConstraintLocation, - constraint, - java.lang.annotation.ElementType.TYPE_USE, - defaultPackage, - null - ); - metaConstraints.add( metaConstraint ); - } - - ContainerElementTypeConfiguration nestedContainerElementTypeConfiguration = add( constraintElementTypePath, xmlContainerElementType.getContainerElementType(), - containerElementTypeConstraintLocation, containerElementType ); - - metaConstraints.addAll( nestedContainerElementTypeConfiguration.getMetaConstraints() ); - - boolean isCascaded = xmlContainerElementType.getValid() != null; - - containerElementTypesCascadingMetaDataBuilder.put( typeParameter, new CascadingMetaDataBuilder( enclosingType, typeParameter, isCascaded, - nestedContainerElementTypeConfiguration.getTypeParametersCascadingMetaData(), - groupConversionBuilder.buildGroupConversionMap( xmlContainerElementType.getConvertGroup(), defaultPackage ) ) - ); - } - - return new ContainerElementTypeConfiguration( metaConstraints, containerElementTypesCascadingMetaDataBuilder ); - } - - private Integer getTypeArgumentIndex(ContainerElementTypeType xmlContainerElementType, TypeVariable[] typeParameters, boolean isArray, Type enclosingType) { - if ( isArray ) { - return null; - } - - Integer typeArgumentIndex = xmlContainerElementType.getTypeArgumentIndex(); - if ( typeArgumentIndex == null ) { - if ( typeParameters.length > 1 ) { - throw LOG.getNoTypeArgumentIndexIsGivenForTypeWithMultipleTypeArgumentsException( enclosingType ); - } - typeArgumentIndex = 0; - } - - return typeArgumentIndex; - } - - private TypeVariable getTypeParameter(TypeVariable[] typeParameters, Integer typeArgumentIndex, boolean isArray, Type enclosingType) { - TypeVariable typeParameter; - if ( !isArray ) { - if ( typeArgumentIndex > typeParameters.length - 1 ) { - throw LOG.getInvalidTypeArgumentIndexException( enclosingType, typeArgumentIndex ); - } - - typeParameter = typeParameters[typeArgumentIndex]; - } - else { - typeParameter = new ArrayElement( enclosingType ); - } - return typeParameter; - } - - private Type getContainerElementType(Type enclosingType, Integer typeArgumentIndex, boolean isArray) { - Type containerElementType; - if ( !isArray ) { - containerElementType = ( (ParameterizedType) enclosingType ).getActualTypeArguments()[typeArgumentIndex]; - } - else { - containerElementType = TypeHelper.getComponentType( enclosingType ); - } - return containerElementType; - } - - static class ContainerElementTypeConfiguration { - - private final Set> metaConstraints; - - private final Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaDataBuilder; - - private ContainerElementTypeConfiguration(Set> metaConstraints, Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaData) { - this.metaConstraints = metaConstraints; - this.containerElementTypesCascadingMetaDataBuilder = containerElementTypesCascadingMetaData; - } - - public Set> getMetaConstraints() { - return metaConstraints; - } - - public Map, CascadingMetaDataBuilder> getTypeParametersCascadingMetaData() { - return containerElementTypesCascadingMetaDataBuilder; - } - } -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/GroupConversionBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/GroupConversionBuilder.java deleted file mode 100644 index 6077edc763..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/GroupConversionBuilder.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.xml; - -import static org.hibernate.validator.internal.util.CollectionHelper.newHashMap; - -import java.lang.invoke.MethodHandles; -import java.util.List; -import java.util.Map; - -import javax.validation.groups.Default; - -import org.hibernate.validator.internal.util.CollectionHelper; -import org.hibernate.validator.internal.util.logging.Log; -import org.hibernate.validator.internal.util.logging.LoggerFactory; -import org.hibernate.validator.internal.xml.binding.GroupConversionType; - -/** - * Builder for group conversions. - * - * @author Hardy Ferentschik - */ -class GroupConversionBuilder { - - private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - - private final ClassLoadingHelper classLoadingHelper; - - GroupConversionBuilder(ClassLoadingHelper classLoadingHelper) { - this.classLoadingHelper = classLoadingHelper; - } - - Map, Class> buildGroupConversionMap(List groupConversionTypes, - String defaultPackage) { - Map, Class> groupConversionMap = newHashMap(); - for ( GroupConversionType groupConversionType : groupConversionTypes ) { - Class fromClass = groupConversionType.getFrom() == null ? - Default.class : - classLoadingHelper.loadClass( groupConversionType.getFrom(), defaultPackage ); - Class toClass = classLoadingHelper.loadClass( groupConversionType.getTo(), defaultPackage ); - - if ( groupConversionMap.containsKey( fromClass ) ) { - throw LOG.getMultipleGroupConversionsForSameSourceException( - fromClass, - CollectionHelper.>asSet( groupConversionMap.get( fromClass ), toClass ) ); - } - - groupConversionMap.put( fromClass, toClass ); - } - - return groupConversionMap; - } -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/LocalNamespace.java b/engine/src/main/java/org/hibernate/validator/internal/xml/LocalNamespace.java deleted file mode 100644 index ffca5e1f1e..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/LocalNamespace.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.xml; - -/** - * Bean Validation namespaces reference. - * - * @author Guillaume Smet - */ -public enum LocalNamespace { - VALIDATION_1_CONFIGURATION("http://jboss.org/xml/ns/javax/validation/configuration"), - VALIDATION_1_MAPPING("http://jboss.org/xml/ns/javax/validation/mapping"), - - VALIDATION_2_CONFIGURATION("http://xmlns.jcp.org/xml/ns/validation/configuration"), - VALIDATION_2_MAPPING("http://xmlns.jcp.org/xml/ns/validation/mapping"); - - private String namespaceURI; - - private LocalNamespace(String namespaceURI) { - this.namespaceURI = namespaceURI; - } - - public String getNamespaceURI() { - return namespaceURI; - } - -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/MetaConstraintBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/MetaConstraintBuilder.java deleted file mode 100644 index 7851214f3b..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/MetaConstraintBuilder.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.xml; - -import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; - -import java.io.Serializable; -import java.lang.annotation.Annotation; -import java.lang.invoke.MethodHandles; -import java.lang.reflect.Array; -import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Iterator; -import java.util.List; -import java.util.regex.Pattern; - -import javax.validation.Payload; -import javax.validation.ValidationException; -import javax.xml.bind.JAXBElement; - -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; -import org.hibernate.validator.internal.metadata.core.MetaConstraint; -import org.hibernate.validator.internal.metadata.core.MetaConstraints; -import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; -import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.util.TypeResolutionHelper; -import org.hibernate.validator.internal.util.annotation.AnnotationDescriptor; -import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; -import org.hibernate.validator.internal.util.logging.Log; -import org.hibernate.validator.internal.util.logging.LoggerFactory; -import org.hibernate.validator.internal.util.privilegedactions.GetMethod; -import org.hibernate.validator.internal.xml.binding.AnnotationType; -import org.hibernate.validator.internal.xml.binding.ConstraintType; -import org.hibernate.validator.internal.xml.binding.ElementType; -import org.hibernate.validator.internal.xml.binding.GroupsType; -import org.hibernate.validator.internal.xml.binding.PayloadType; - -/** - * Build meta constraint from XML - * - * @author Hardy Ferentschik - */ -class MetaConstraintBuilder { - - private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - - private static final Pattern IS_ONLY_WHITESPACE = Pattern.compile( "\\s*" ); - private static final Class[] EMPTY_CLASSES_ARRAY = new Class[0]; - - private final ClassLoadingHelper classLoadingHelper; - private final ConstraintHelper constraintHelper; - private final TypeResolutionHelper typeResolutionHelper; - private final ValueExtractorManager valueExtractorManager; - - MetaConstraintBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager) { - this.classLoadingHelper = classLoadingHelper; - this.constraintHelper = constraintHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; - } - - @SuppressWarnings("unchecked") - MetaConstraint buildMetaConstraint(ConstraintLocation constraintLocation, - ConstraintType constraint, - java.lang.annotation.ElementType type, - String defaultPackage, - ConstraintDescriptorImpl.ConstraintType constraintType) { - Class annotationClass; - try { - annotationClass = (Class) classLoadingHelper.loadClass( constraint.getAnnotation(), defaultPackage ); - } - catch (ValidationException e) { - throw LOG.getUnableToLoadConstraintAnnotationClassException( constraint.getAnnotation(), e ); - } - ConstraintAnnotationDescriptor.Builder annotationDescriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( annotationClass ); - - if ( constraint.getMessage() != null ) { - annotationDescriptorBuilder.setMessage( constraint.getMessage() ); - } - annotationDescriptorBuilder.setGroups( getGroups( constraint.getGroups(), defaultPackage ) ) - .setPayload( getPayload( constraint.getPayload(), defaultPackage ) ); - - for ( ElementType elementType : constraint.getElement() ) { - String name = elementType.getName(); - checkNameIsValid( name ); - Class returnType = getAnnotationParameterType( annotationClass, name ); - Object elementValue = getElementValue( elementType, returnType, defaultPackage ); - annotationDescriptorBuilder.setAttribute( name, elementValue ); - } - - ConstraintAnnotationDescriptor annotationDescriptor; - try { - annotationDescriptor = annotationDescriptorBuilder.build(); - } - catch (RuntimeException e) { - throw LOG.getUnableToCreateAnnotationForConfiguredConstraintException( e ); - } - - // we set initially ConstraintOrigin.DEFINED_LOCALLY for all xml configured constraints - // later we will make copies of this constraint descriptor when needed and adjust the ConstraintOrigin - ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl( - constraintHelper, constraintLocation.getMember(), annotationDescriptor, type, constraintType - ); - - return MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor, constraintLocation ); - } - - private Annotation buildAnnotation(AnnotationType annotationType, Class returnType, String defaultPackage) { - AnnotationDescriptor.Builder annotationDescriptorBuilder = new AnnotationDescriptor.Builder<>( returnType ); - for ( ElementType elementType : annotationType.getElement() ) { - String name = elementType.getName(); - Class parameterType = getAnnotationParameterType( returnType, name ); - Object elementValue = getElementValue( elementType, parameterType, defaultPackage ); - annotationDescriptorBuilder.setAttribute( name, elementValue ); - } - return annotationDescriptorBuilder.build().getAnnotation(); - } - - private static void checkNameIsValid(String name) { - if ( ConstraintHelper.MESSAGE.equals( name ) || ConstraintHelper.GROUPS.equals( name ) ) { - throw LOG.getReservedParameterNamesException( ConstraintHelper.MESSAGE, ConstraintHelper.GROUPS, ConstraintHelper.PAYLOAD ); - } - } - - private static Class getAnnotationParameterType(Class annotationClass, String name) { - Method m = run( GetMethod.action( annotationClass, name ) ); - if ( m == null ) { - throw LOG.getAnnotationDoesNotContainAParameterException( annotationClass, 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() == 0 ) { - if ( returnType == String.class ) { - return ""; - } - else { - throw LOG.getEmptyElementOnlySupportedWhenCharSequenceIsExpectedExpection(); - } - } - else if ( elementType.getContent().size() > 1 ) { - throw LOG.getAttemptToSpecifyAnArrayWhereSingleValueIsExpectedException(); - } - return getSingleValue( elementType.getContent().get( 0 ), returnType, defaultPackage ); - } - else { - List values = newArrayList(); - for ( Serializable s : elementType.getContent() ) { - values.add( getSingleValue( s, returnType.getComponentType(), defaultPackage ) ); - } - return values.toArray( (Object[]) Array.newInstance( returnType.getComponentType(), values.size() ) ); - } - } - - private static void removeEmptyContentElements(ElementType elementType) { - for ( Iterator contentIterator = elementType.getContent().iterator(); contentIterator.hasNext(); ) { - Serializable content = contentIterator.next(); - if ( content instanceof String && IS_ONLY_WHITESPACE.matcher( (String) content ).matches() ) { - contentIterator.remove(); - } - } - } - - private Object getSingleValue(Serializable serializable, Class returnType, String defaultPackage) { - - Object returnValue; - if ( serializable instanceof String ) { - String value = (String) serializable; - returnValue = convertStringToReturnType( returnType, value, defaultPackage ); - } - else if ( serializable instanceof JAXBElement && ( (JAXBElement) serializable ).getDeclaredType() - .equals( String.class ) ) { - JAXBElement elem = (JAXBElement) serializable; - String value = (String) elem.getValue(); - returnValue = convertStringToReturnType( returnType, value, defaultPackage ); - } - else if ( serializable instanceof JAXBElement && ( (JAXBElement) serializable ).getDeclaredType() - .equals( AnnotationType.class ) ) { - JAXBElement elem = (JAXBElement) serializable; - AnnotationType annotationType = (AnnotationType) elem.getValue(); - try { - @SuppressWarnings("unchecked") - Class annotationClass = (Class) returnType; - returnValue = buildAnnotation( annotationType, annotationClass, defaultPackage ); - } - catch (ClassCastException e) { - throw LOG.getUnexpectedParameterValueException( e ); - } - } - else { - throw LOG.getUnexpectedParameterValueException(); - } - return returnValue; - - } - - private Object convertStringToReturnType(Class returnType, String value, String defaultPackage) { - Object returnValue; - if ( returnType == byte.class ) { - try { - returnValue = Byte.parseByte( value ); - } - catch (NumberFormatException e) { - throw LOG.getInvalidNumberFormatException( "byte", e ); - } - } - else if ( returnType == short.class ) { - try { - returnValue = Short.parseShort( value ); - } - catch (NumberFormatException e) { - throw LOG.getInvalidNumberFormatException( "short", e ); - } - } - else if ( returnType == int.class ) { - try { - returnValue = Integer.parseInt( value ); - } - catch (NumberFormatException e) { - throw LOG.getInvalidNumberFormatException( "int", e ); - } - } - else if ( returnType == long.class ) { - try { - returnValue = Long.parseLong( value ); - } - catch (NumberFormatException e) { - throw LOG.getInvalidNumberFormatException( "long", e ); - } - } - else if ( returnType == float.class ) { - try { - returnValue = Float.parseFloat( value ); - } - catch (NumberFormatException e) { - throw LOG.getInvalidNumberFormatException( "float", e ); - } - } - else if ( returnType == double.class ) { - try { - returnValue = Double.parseDouble( value ); - } - catch (NumberFormatException e) { - throw LOG.getInvalidNumberFormatException( "double", e ); - } - } - else if ( returnType == boolean.class ) { - returnValue = Boolean.parseBoolean( value ); - } - else if ( returnType == char.class ) { - if ( value.length() != 1 ) { - throw LOG.getInvalidCharValueException( value ); - } - returnValue = value.charAt( 0 ); - } - else if ( returnType == String.class ) { - returnValue = value; - } - else if ( returnType == Class.class ) { - returnValue = classLoadingHelper.loadClass( value, defaultPackage ); - } - else { - try { - @SuppressWarnings("unchecked") - Class enumClass = (Class) returnType; - returnValue = Enum.valueOf( enumClass, value ); - } - catch (ClassCastException e) { - throw LOG.getInvalidReturnTypeException( returnType, e ); - } - } - return returnValue; - } - - private Class[] getGroups(GroupsType groupsType, String defaultPackage) { - if ( groupsType == null ) { - return EMPTY_CLASSES_ARRAY; - } - - List> groupList = newArrayList(); - for ( String groupClass : groupsType.getValue() ) { - groupList.add( classLoadingHelper.loadClass( groupClass, defaultPackage ) ); - } - return groupList.toArray( new Class[groupList.size()] ); - } - - @SuppressWarnings("unchecked") - private Class[] getPayload(PayloadType payloadType, String defaultPackage) { - if ( payloadType == null ) { - return EMPTY_CLASSES_ARRAY; - } - - List> payloadList = newArrayList(); - for ( String groupClass : payloadType.getValue() ) { - Class payload = classLoadingHelper.loadClass( groupClass, defaultPackage ); - if ( !Payload.class.isAssignableFrom( payload ) ) { - throw LOG.getWrongPayloadClassException( payload ); - } - else { - payloadList.add( (Class) payload ); - } - } - return payloadList.toArray( new Class[payloadList.size()] ); - } - - /** - * Runs the given privileged action, using a privileged block if required. - *

- * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary - * privileged actions within HV's protection domain. - */ - private static T run(PrivilegedAction action) { - return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); - } -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/NamespaceNormalizingXMLEventReaderDelegate.java b/engine/src/main/java/org/hibernate/validator/internal/xml/NamespaceNormalizingXMLEventReaderDelegate.java deleted file mode 100644 index 99215486e6..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/NamespaceNormalizingXMLEventReaderDelegate.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.xml; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import javax.xml.namespace.QName; -import javax.xml.stream.XMLEventFactory; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.EndElement; -import javax.xml.stream.events.Namespace; -import javax.xml.stream.events.StartElement; -import javax.xml.stream.events.XMLEvent; -import javax.xml.stream.util.EventReaderDelegate; - -/** - * An XML {@link EventReaderDelegate} designed to normalize the XML namespaces. - *

- * From BV 1.x to BV 2, we changed the namespaces and we need to normalize the namespaces to the ones of BV 2 so that - * the unmarshaller can do its job. - *

- * Note: it used to work in JDK 1.8 before the 102 release but the JDK is now stricter: - * https://bugs.openjdk.java.net/browse/JDK-8134111. - * - * @author Guillaume Smet - */ -public class NamespaceNormalizingXMLEventReaderDelegate extends EventReaderDelegate { - - private final XMLEventFactory eventFactory; - - private final Map namespaceMapping; - - public NamespaceNormalizingXMLEventReaderDelegate(XMLEventReader eventReader, XMLEventFactory eventFactory, Map namespaceMapping) { - super( eventReader ); - this.eventFactory = eventFactory; - this.namespaceMapping = namespaceMapping; - } - - @Override - public XMLEvent peek() throws XMLStreamException { - return normalizeXMLEvent( super.peek() ); - } - - @Override - public XMLEvent nextEvent() throws XMLStreamException { - return normalizeXMLEvent( super.nextEvent() ); - } - - private XMLEvent normalizeXMLEvent(XMLEvent xmlEvent) { - if ( xmlEvent.isStartElement() ) { - return normalizeNamespace( xmlEvent.asStartElement() ); - } - else if ( xmlEvent.isEndElement() ) { - return normalizeNamespace( xmlEvent.asEndElement() ); - } - else { - return xmlEvent; - } - } - - @SuppressWarnings("unchecked") - private StartElement normalizeNamespace(StartElement element) { - eventFactory.setLocation( element.getLocation() ); - return eventFactory.createStartElement( normalizeQName( element.getName() ), element.getAttributes(), normalizeNamespaces( element.getNamespaces() ) ); - } - - @SuppressWarnings("unchecked") - private EndElement normalizeNamespace(EndElement element) { - eventFactory.setLocation( element.getLocation() ); - return eventFactory.createEndElement( normalizeQName( element.getName() ), normalizeNamespaces( element.getNamespaces() ) ); - } - - private QName normalizeQName(QName qName) { - return new QName( normalizeNamespaceURI( qName.getNamespaceURI() ), qName.getLocalPart() ); - } - - private Iterator normalizeNamespaces(Iterator namespaces) { - List newNamespaces = new ArrayList<>(); - while ( namespaces.hasNext() ) { - newNamespaces.add( normalizeNamespace( namespaces.next() ) ); - } - return newNamespaces.iterator(); - } - - private Namespace normalizeNamespace(Namespace namespace) { - return eventFactory.createNamespace( namespace.getPrefix(), normalizeNamespaceURI( namespace.getNamespaceURI() ) ); - } - - private String normalizeNamespaceURI(String namespaceURI) { - return namespaceMapping.getOrDefault( namespaceURI, namespaceURI ); - } - -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/XmlParserHelper.java b/engine/src/main/java/org/hibernate/validator/internal/xml/XmlParserHelper.java index 6ba3ba1762..511da201f6 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/XmlParserHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/XmlParserHelper.java @@ -14,14 +14,10 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import javax.xml.namespace.QName; -import javax.xml.stream.XMLEventFactory; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; @@ -54,29 +50,16 @@ public class XmlParserHelper { */ private static final int NUMBER_OF_SCHEMAS = 4; private static final String DEFAULT_VERSION = "1.0"; - - private static final Map NAMESPACE_NORMALIZATION_MAPPING; + private static final QName VERSION_QNAME = new QName( "version" ); // xmlInputFactory used to be static in order to cache the factory, but that introduced a leakage of // class loader in WildFly. See HV-842 private final XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); - // xmlEventFactory should not be static either. - private final XMLEventFactory xmlEventFactory = XMLEventFactory.newInstance(); - private static final ConcurrentMap schemaCache = new ConcurrentHashMap( NUMBER_OF_SCHEMAS ); - static { - Map namespaceNormalizationMapping = new HashMap<>(); - namespaceNormalizationMapping.put( LocalNamespace.VALIDATION_1_CONFIGURATION.getNamespaceURI(), - LocalNamespace.VALIDATION_2_CONFIGURATION.getNamespaceURI() ); - namespaceNormalizationMapping.put( LocalNamespace.VALIDATION_1_MAPPING.getNamespaceURI(), - LocalNamespace.VALIDATION_2_MAPPING.getNamespaceURI() ); - NAMESPACE_NORMALIZATION_MAPPING = Collections.unmodifiableMap( namespaceNormalizationMapping ); - } - /** * Retrieves the schema version applying for the given XML input stream as * represented by the "version" attribute of the root element of the stream. @@ -105,11 +88,7 @@ public String getSchemaVersion(String resourceName, XMLEventReader xmlEventReade public synchronized XMLEventReader createXmlEventReader(String resourceName, InputStream xmlStream) { try { - return new NamespaceNormalizingXMLEventReaderDelegate( - xmlInputFactory.createXMLEventReader( xmlStream ), - xmlEventFactory, - NAMESPACE_NORMALIZATION_MAPPING - ); + return xmlInputFactory.createXMLEventReader( xmlStream ); } catch (Exception e) { throw LOG.getUnableToCreateXMLEventReader( resourceName, e ); @@ -121,7 +100,7 @@ private String getVersionValue(StartElement startElement) { return null; } - Attribute versionAttribute = startElement.getAttributeByName( new QName( "version" ) ); + Attribute versionAttribute = startElement.getAttributeByName( VERSION_QNAME ); return versionAttribute != null ? versionAttribute.getValue() : DEFAULT_VERSION; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationXmlParser.java b/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationXmlParser.java index 059ae6df1c..bdfb20f81d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationXmlParser.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationXmlParser.java @@ -32,7 +32,7 @@ import org.xml.sax.SAXException; /** - * Parser for validation.xml using JAXB. + * Parser for validation.xml. * * @author Hardy Ferentschik * @author Gunnar Morling diff --git a/engine/src/main/xjb/binding-customization.xjb b/engine/src/main/xjb/binding-customization.xjb deleted file mode 100644 index 8dc5132c86..0000000000 --- a/engine/src/main/xjb/binding-customization.xjb +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/pom.xml b/pom.xml index fdf19d6603..96fc787983 100644 --- a/pom.xml +++ b/pom.xml @@ -759,11 +759,6 @@ --> 1.5.0 - - org.codehaus.mojo - jaxb2-maven-plugin - 2.2 - org.asciidoctor asciidoctor-maven-plugin @@ -1169,9 +1164,6 @@ maven-compiler-plugin true - - -J--add-modules=java.xml.ws.annotation - diff --git a/tck-runner/src/test/resources/test.policy b/tck-runner/src/test/resources/test.policy index cf6722c55e..1b454f882e 100644 --- a/tck-runner/src/test/resources/test.policy +++ b/tck-runner/src/test/resources/test.policy @@ -30,8 +30,6 @@ grant codeBase "file:${localRepository}/org/hibernate/validator/hibernate-valida permission org.hibernate.validator.HibernateValidatorPermission "accessPrivateMembers"; - // JAXB - permission java.util.PropertyPermission "mapAnyUriToUri", "read"; }; // Used during aggregator builds also building "engine", e.g. mvn clean install -pl tck-runner -am @@ -43,8 +41,6 @@ grant codeBase "file:${basedir}/../engine/target/hibernate-validator-${project.v permission org.hibernate.validator.HibernateValidatorPermission "accessPrivateMembers"; - // JAXB - permission java.util.PropertyPermission "mapAnyUriToUri", "read"; }; grant codeBase "file:${localRepository}/com/fasterxml/classmate/-" { From 6b24ba825a54e0125cdf50db20f18c568f852ada Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Wed, 7 Mar 2018 00:04:02 +0100 Subject: [PATCH 008/393] HV-1450 Changed which executables are excepted by ExecutableMetaData.Builder - changed the logic on how executable builder determines if it should accept a constrained element. Used a most specific sub type from the hierarchy under inspection to resolve executables and check if they override each other somewhere in the hierarchy. - changed the order of metadata providers. Made annotation based as a first provider. This should build all possible builder delegates after the first iteration on metadata providers and data from other providers will be just merged in. --- .../metadata/BeanMetaDataManager.java | 15 ++-- .../aggregated/ExecutableMetaData.java | 12 ++- .../internal/util/ExecutableHelper.java | 88 +++++++++++++++++-- ...terConstraintsInParallelHierarchyTest.java | 71 +++++++++++++++ 4 files changed, 169 insertions(+), 17 deletions(-) create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/MethodParameterConstraintsInParallelHierarchyTest.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java index 5a5abbf095..4697088099 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java @@ -127,9 +127,6 @@ public BeanMetaDataManager(ConstraintHelper constraintHelper, this.parameterNameProvider = parameterNameProvider; this.validationOrderGenerator = validationOrderGenerator; - this.metaDataProviders = newArrayList(); - this.metaDataProviders.addAll( optionalMetaDataProviders ); - this.methodValidationConfiguration = methodValidationConfiguration; this.beanMetaDataCache = new ConcurrentReferenceHashMap<>( @@ -141,15 +138,19 @@ public BeanMetaDataManager(ConstraintHelper constraintHelper, EnumSet.of( IDENTITY_COMPARISONS ) ); - AnnotationProcessingOptions annotationProcessingOptions = getAnnotationProcessingOptionsFromNonDefaultProviders(); + AnnotationProcessingOptions annotationProcessingOptions = getAnnotationProcessingOptionsFromNonDefaultProviders( optionalMetaDataProviders ); AnnotationMetaDataProvider defaultProvider = new AnnotationMetaDataProvider( constraintHelper, typeResolutionHelper, valueExtractorManager, annotationProcessingOptions ); - + this.metaDataProviders = newArrayList(); + // default annotation based metadata provider should go first in the list of providers to prevent possible issues + // similar to HV-1450. This way after the first run we will have all possible constrained elements in the list and + // should only merge in additional constraint information from other providers. this.metaDataProviders.add( defaultProvider ); + this.metaDataProviders.addAll( optionalMetaDataProviders ); } @SuppressWarnings("unchecked") @@ -195,9 +196,9 @@ private BeanMetaDataImpl createBeanMetaData(Class clazz) { /** * @return returns the annotation ignores from the non annotation based meta data providers */ - private AnnotationProcessingOptions getAnnotationProcessingOptionsFromNonDefaultProviders() { + private AnnotationProcessingOptions getAnnotationProcessingOptionsFromNonDefaultProviders(List optionalMetaDataProviders) { AnnotationProcessingOptions options = new AnnotationProcessingOptionsImpl(); - for ( MetaDataProvider metaDataProvider : metaDataProviders ) { + for ( MetaDataProvider metaDataProvider : optionalMetaDataProviders ) { options.merge( metaDataProvider.getAnnotationProcessingOptions() ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java index 001ac4db3b..be3de00daa 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java @@ -310,9 +310,15 @@ public boolean accepts(ConstrainedElement constrainedElement) { //are the locations equal (created by different builders) or //does one of the executables override the other one? - return executable.equals( candidate ) || - overrides( executable, candidate ) || - overrides( candidate, executable ); + return resolveToSameMethodInHierarchy( executable, candidate ); + } + + private boolean resolveToSameMethodInHierarchy(Executable first, Executable other) { + if ( first instanceof Constructor || other instanceof Constructor ) { + return first.equals( other ); + } + + return executableHelper.resolveToSameMethodInHierarchy( getBeanClass(), (Method) first, (Method) other ); } private boolean overrides(Executable first, Executable other) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/ExecutableHelper.java b/engine/src/main/java/org/hibernate/validator/internal/util/ExecutableHelper.java index ce83775ef2..90111b5f19 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/ExecutableHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/ExecutableHelper.java @@ -17,6 +17,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.hibernate.validator.internal.util.classhierarchy.Filters; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.util.privilegedactions.GetResolvedMemberMethods; @@ -90,14 +91,83 @@ public boolean overrides(Method subTypeMethod, Method superTypeMethod) { return false; } - if ( !Modifier.isPublic( superTypeMethod.getModifiers() ) && !Modifier.isProtected( superTypeMethod.getModifiers() ) - && !superTypeMethod.getDeclaringClass().getPackage().equals( subTypeMethod.getDeclaringClass().getPackage() ) ) { + if ( !isOneMethodVisibleToAnother( subTypeMethod, superTypeMethod ) ) { return false; } return instanceMethodParametersResolveToSameTypes( subTypeMethod, superTypeMethod ); } + /** + * Checks if a pair of given methods ({@code left} and {@code right}) are resolved to the same + * method based on the {@code mainSubType} type. + * + * @param mainSubType a type at the bottom of class hierarchy to be used to lookup the methods. + * @param left one of the methods to check + * @param right another of the methods to check + * + * @return {@code true} if a pair of methods are equal {@code left == right}, or one of the methods + * override another one in the class hierarchy with {@code mainSubType} at the bottom, + * {@code false} otherwise. + */ + public boolean resolveToSameMethodInHierarchy(Class mainSubType, Method left, Method right) { + Contracts.assertValueNotNull( mainSubType, "mainSubType" ); + Contracts.assertValueNotNull( left, "left" ); + Contracts.assertValueNotNull( right, "right" ); + + if ( left.equals( right ) ) { + return true; + } + + if ( !left.getName().equals( right.getName() ) ) { + return false; + } + + // methods with same name in the same class should be different + if ( left.getDeclaringClass().equals( right.getDeclaringClass() ) ) { + return false; + } + + if ( left.getParameterTypes().length != right.getParameterTypes().length ) { + return false; + } + + // if at least one method from a pair is static - they are different methods + if ( Modifier.isStatic( right.getModifiers() ) || Modifier.isStatic( left.getModifiers() ) ) { + return false; + } + + // HV-861 Bridge method should be ignored. Classmates type/member resolution will take care of proper + // override detection without considering bridge methods + if ( left.isBridge() || right.isBridge() ) { + return false; + } + + // if one of the methods is private - methods are different + if ( Modifier.isPrivate( left.getModifiers() ) || Modifier.isPrivate( right.getModifiers() ) ) { + return false; + } + + if ( !isOneMethodVisibleToAnother( left, right ) || !isOneMethodVisibleToAnother( right, left ) ) { + return false; + } + + // We need to check if the passed mainSubType is not a Weld proxy. In case of proxy we need to get + // a class that was proxied otherwise we can use the class itself. This is due to the issue that + // call to Class#getGenericInterfaces() on a Weld proxy returns raw types instead of parametrized + // generics and methods will not be resolved correctly. + return instanceMethodParametersResolveToSameTypes( + Filters.excludeProxies().accepts( mainSubType ) ? mainSubType : mainSubType.getSuperclass(), + left, + right + ); + } + + private static boolean isOneMethodVisibleToAnother(Method left, Method right) { + return Modifier.isPublic( right.getModifiers() ) || Modifier.isProtected( right.getModifiers() ) + || right.getDeclaringClass().getPackage().equals( left.getDeclaringClass().getPackage() ); + } + public static String getSimpleName(Executable executable) { return executable instanceof Constructor ? executable.getDeclaringClass().getSimpleName() : executable.getName(); } @@ -140,14 +210,18 @@ public static ElementType getElementType(Executable executable) { * @return {@code true} if the parameters of the two methods resolve to the same types, {@code false otherwise}. */ private boolean instanceMethodParametersResolveToSameTypes(Method subTypeMethod, Method superTypeMethod) { - if ( subTypeMethod.getParameterTypes().length == 0 ) { + return instanceMethodParametersResolveToSameTypes( subTypeMethod.getDeclaringClass(), subTypeMethod, superTypeMethod ); + } + + private boolean instanceMethodParametersResolveToSameTypes(Class mainSubType, Method left, Method right) { + if ( left.getParameterTypes().length == 0 ) { return true; } - ResolvedType resolvedSubType = typeResolver.resolve( subTypeMethod.getDeclaringClass() ); + ResolvedType resolvedSubType = typeResolver.resolve( mainSubType ); MemberResolver memberResolver = new MemberResolver( typeResolver ); - memberResolver.setMethodFilter( new SimpleMethodFilter( subTypeMethod, superTypeMethod ) ); + memberResolver.setMethodFilter( new SimpleMethodFilter( left, right ) ); ResolvedTypeWithMembers typeWithMembers = memberResolver.resolve( resolvedSubType, null, @@ -181,9 +255,9 @@ private boolean instanceMethodParametersResolveToSameTypes(Method subTypeMethod, catch (ArrayIndexOutOfBoundsException e) { LOG.debug( "Error in ExecutableHelper#instanceMethodParametersResolveToSameTypes comparing " - + subTypeMethod + + left + " with " - + superTypeMethod + + right ); } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/MethodParameterConstraintsInParallelHierarchyTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/MethodParameterConstraintsInParallelHierarchyTest.java new file mode 100644 index 0000000000..aac2e4436e --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/MethodParameterConstraintsInParallelHierarchyTest.java @@ -0,0 +1,71 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.engine.methodvalidation; + +import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; + +import java.lang.reflect.Method; +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.testutil.TestForIssue; + +import org.testng.annotations.Test; + +/** + * @author Marko Bekhta + */ +public class MethodParameterConstraintsInParallelHierarchyTest { + + /** + * NOTE: prior to the changes where this test was added it would fail randomly. + */ + @Test + @TestForIssue(jiraKey = "HV-1450") + public void testDeepParallelHierarchyIsProcessedCorrectly() throws Exception { + + WebServiceImpl service = new WebServiceImpl(); + Method method = WebServiceImpl.class.getMethod( "getEntityVersion", Long.class ); + Object[] params = new Object[] { null }; + + Validator validator = Validation.byDefaultProvider().configure() + .buildValidatorFactory().getValidator(); + + Set> violations = + validator.forExecutables().validateParameters( service, method, params ); + + assertThat( violations ).containsOnlyViolations( violationOf( NotNull.class ) ); + } + + private class WebServiceImpl extends AbstractWebService implements ExtendedWebService { + + } + + private abstract class AbstractWebService implements WebService { + + @Override + public int getEntityVersion(Long id) { + return id.intValue(); + } + } + + private interface ExtendedWebService extends WebService { + + @Override + int getEntityVersion(Long id); + } + + private interface WebService { + + int getEntityVersion(@NotNull Long id); + } +} From 8f08f09abd5a54d27b272d8f3e68f3afadeee266 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 7 Mar 2018 14:26:08 +0100 Subject: [PATCH 009/393] HV-1450 Some minor editorialization --- .../metadata/BeanMetaDataManager.java | 29 ++++++++++++------- .../aggregated/ExecutableMetaData.java | 6 ++-- .../internal/util/ExecutableHelper.java | 12 ++++---- ...terConstraintsInParallelHierarchyTest.java | 13 +++++---- 4 files changed, 34 insertions(+), 26 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java index 4697088099..197a3232c4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java @@ -11,6 +11,7 @@ import static org.hibernate.validator.internal.util.ConcurrentReferenceHashMap.ReferenceType.SOFT; import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES; +import java.util.ArrayList; import java.util.EnumSet; import java.util.List; @@ -28,12 +29,14 @@ import org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; +import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.ConcurrentReferenceHashMap; import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper; +import org.hibernate.validator.internal.util.stereotypes.Immutable; /** * This manager is in charge of providing all constraint related meta data @@ -74,6 +77,7 @@ public class BeanMetaDataManager { * Additional metadata providers used for meta data retrieval if * the XML and/or programmatic configuration is used. */ + @Immutable private final List metaDataProviders; /** @@ -140,17 +144,20 @@ public BeanMetaDataManager(ConstraintHelper constraintHelper, AnnotationProcessingOptions annotationProcessingOptions = getAnnotationProcessingOptionsFromNonDefaultProviders( optionalMetaDataProviders ); AnnotationMetaDataProvider defaultProvider = new AnnotationMetaDataProvider( - constraintHelper, - typeResolutionHelper, - valueExtractorManager, - annotationProcessingOptions - ); - this.metaDataProviders = newArrayList(); - // default annotation based metadata provider should go first in the list of providers to prevent possible issues - // similar to HV-1450. This way after the first run we will have all possible constrained elements in the list and - // should only merge in additional constraint information from other providers. - this.metaDataProviders.add( defaultProvider ); - this.metaDataProviders.addAll( optionalMetaDataProviders ); + constraintHelper, + typeResolutionHelper, + valueExtractorManager, + annotationProcessingOptions + ); + List tmpMetaDataProviders = new ArrayList<>( optionalMetaDataProviders.size() + 1 ); + // We add the annotation based metadata provider at the first position so that the entire metadata model is assembled + // first. + // The other optional metadata providers will then contribute their additional metadata to the preexisting model. + // This helps to mitigate issues like HV-1450. + tmpMetaDataProviders.add( defaultProvider ); + tmpMetaDataProviders.addAll( optionalMetaDataProviders ); + + this.metaDataProviders = CollectionHelper.toImmutableList( tmpMetaDataProviders ); } @SuppressWarnings("unchecked") diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java index be3de00daa..46d1aa7050 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java @@ -310,15 +310,15 @@ public boolean accepts(ConstrainedElement constrainedElement) { //are the locations equal (created by different builders) or //does one of the executables override the other one? - return resolveToSameMethodInHierarchy( executable, candidate ); + return isResolvedToSameMethodInHierarchy( executable, candidate ); } - private boolean resolveToSameMethodInHierarchy(Executable first, Executable other) { + private boolean isResolvedToSameMethodInHierarchy(Executable first, Executable other) { if ( first instanceof Constructor || other instanceof Constructor ) { return first.equals( other ); } - return executableHelper.resolveToSameMethodInHierarchy( getBeanClass(), (Method) first, (Method) other ); + return executableHelper.isResolvedToSameMethodInHierarchy( getBeanClass(), (Method) first, (Method) other ); } private boolean overrides(Executable first, Executable other) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/ExecutableHelper.java b/engine/src/main/java/org/hibernate/validator/internal/util/ExecutableHelper.java index 90111b5f19..0ae6378a5a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/ExecutableHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/ExecutableHelper.java @@ -91,7 +91,7 @@ public boolean overrides(Method subTypeMethod, Method superTypeMethod) { return false; } - if ( !isOneMethodVisibleToAnother( subTypeMethod, superTypeMethod ) ) { + if ( !isMethodVisibleTo( superTypeMethod, subTypeMethod ) ) { return false; } @@ -110,7 +110,7 @@ public boolean overrides(Method subTypeMethod, Method superTypeMethod) { * override another one in the class hierarchy with {@code mainSubType} at the bottom, * {@code false} otherwise. */ - public boolean resolveToSameMethodInHierarchy(Class mainSubType, Method left, Method right) { + public boolean isResolvedToSameMethodInHierarchy(Class mainSubType, Method left, Method right) { Contracts.assertValueNotNull( mainSubType, "mainSubType" ); Contracts.assertValueNotNull( left, "left" ); Contracts.assertValueNotNull( right, "right" ); @@ -148,7 +148,7 @@ public boolean resolveToSameMethodInHierarchy(Class mainSubType, Method left, return false; } - if ( !isOneMethodVisibleToAnother( left, right ) || !isOneMethodVisibleToAnother( right, left ) ) { + if ( !isMethodVisibleTo( right, left ) || !isMethodVisibleTo( left, right ) ) { return false; } @@ -163,9 +163,9 @@ public boolean resolveToSameMethodInHierarchy(Class mainSubType, Method left, ); } - private static boolean isOneMethodVisibleToAnother(Method left, Method right) { - return Modifier.isPublic( right.getModifiers() ) || Modifier.isProtected( right.getModifiers() ) - || right.getDeclaringClass().getPackage().equals( left.getDeclaringClass().getPackage() ); + private static boolean isMethodVisibleTo(Method visibleMethod, Method otherMethod) { + return Modifier.isPublic( visibleMethod.getModifiers() ) || Modifier.isProtected( visibleMethod.getModifiers() ) + || visibleMethod.getDeclaringClass().getPackage().equals( otherMethod.getDeclaringClass().getPackage() ); } public static String getSimpleName(Executable executable) { diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/MethodParameterConstraintsInParallelHierarchyTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/MethodParameterConstraintsInParallelHierarchyTest.java index aac2e4436e..408a91c19e 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/MethodParameterConstraintsInParallelHierarchyTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/MethodParameterConstraintsInParallelHierarchyTest.java @@ -27,7 +27,7 @@ public class MethodParameterConstraintsInParallelHierarchyTest { /** - * NOTE: prior to the changes where this test was added it would fail randomly. + * NOTE: prior to the changes made for HV-1450, this test was failing randomly. */ @Test @TestForIssue(jiraKey = "HV-1450") @@ -37,13 +37,14 @@ public void testDeepParallelHierarchyIsProcessedCorrectly() throws Exception { Method method = WebServiceImpl.class.getMethod( "getEntityVersion", Long.class ); Object[] params = new Object[] { null }; - Validator validator = Validation.byDefaultProvider().configure() - .buildValidatorFactory().getValidator(); + for ( int i = 0; i < 100; i++ ) { + Validator validator = Validation.byDefaultProvider().configure() + .buildValidatorFactory().getValidator(); - Set> violations = - validator.forExecutables().validateParameters( service, method, params ); + Set> violations = validator.forExecutables().validateParameters( service, method, params ); - assertThat( violations ).containsOnlyViolations( violationOf( NotNull.class ) ); + assertThat( violations ).containsOnlyViolations( violationOf( NotNull.class ) ); + } } private class WebServiceImpl extends AbstractWebService implements ExtendedWebService { From 7e8043111358163072ca3f70c369d11acabad1d2 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Sat, 7 Apr 2018 18:05:29 +0300 Subject: [PATCH 010/393] HV-1599 Changed when the violation is created in ConstraintTree - delayed creating of violation when validating constraint in ConstraintTree - added a benchmark to SimpleValidation with composing constraint validation --- .../internal/engine/ValidationContext.java | 21 ++-- .../ComposingConstraintTree.java | 91 ++++++++------- .../constraintvalidation/ConstraintTree.java | 38 ++++--- .../SimpleConstraintTree.java | 16 +-- .../SimpleComposingConstraintValidation.java | 104 ++++++++++++++++++ 5 files changed, 184 insertions(+), 86 deletions(-) create mode 100644 performance/src/main/java/org/hibernate/validator/performance/simple/SimpleComposingConstraintValidation.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java index 640217e794..bde191ef06 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java @@ -18,7 +18,6 @@ import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; import javax.validation.ClockProvider; import javax.validation.ConstraintValidatorFactory; @@ -33,7 +32,6 @@ import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; import org.hibernate.validator.internal.engine.ValidatorFactoryImpl.ValidatorFactoryScopedContext; -import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext; import org.hibernate.validator.internal.engine.path.PathImpl; @@ -272,14 +270,6 @@ public HibernateConstraintValidatorInitializationContext getConstraintValidatorI return constraintValidatorInitializationContext; } - public Set> createConstraintViolations(ValueContext localContext, - ConstraintValidatorContextImpl constraintValidatorContext) { - - return constraintValidatorContext.getConstraintViolationCreationContexts().stream() - .map( c -> createConstraintViolation( localContext, c, constraintValidatorContext.getConstraintDescriptor() ) ) - .collect( Collectors.toSet() ); - } - public ConstraintValidatorFactory getConstraintValidatorFactory() { return constraintValidatorFactory; } @@ -308,16 +298,19 @@ public void markCurrentBeanAsProcessed(ValueContext valueContext) { markCurrentBeanAsProcessedForCurrentPath( valueContext.getCurrentBean(), valueContext.getPropertyPath() ); } - public void addConstraintFailures(Set> failingConstraintViolations) { - this.failingConstraintViolations.addAll( failingConstraintViolations ); + public void addConstraintFailure(ConstraintViolation failingConstraintViolation) { + this.failingConstraintViolations.add( failingConstraintViolation ); } public Set> getFailingConstraints() { return failingConstraintViolations; } - - public ConstraintViolation createConstraintViolation(ValueContext localContext, ConstraintViolationCreationContext constraintViolationCreationContext, ConstraintDescriptor descriptor) { + public ConstraintViolation createConstraintViolation( + ValueContext localContext, + ConstraintViolationCreationContext constraintViolationCreationContext, + ConstraintDescriptor descriptor + ) { String messageTemplate = constraintViolationCreationContext.getMessage(); String interpolatedMessage = interpolate( messageTemplate, diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java index 4d72ef1c10..46d97114b4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java @@ -9,18 +9,17 @@ import static org.hibernate.validator.constraints.CompositionType.ALL_FALSE; import static org.hibernate.validator.constraints.CompositionType.AND; import static org.hibernate.validator.constraints.CompositionType.OR; -import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandles; import java.lang.reflect.Type; -import java.util.Collections; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; -import java.util.Set; +import java.util.Optional; import java.util.stream.Collectors; import javax.validation.ConstraintValidator; -import javax.validation.ConstraintViolation; import org.hibernate.validator.constraints.CompositionType; import org.hibernate.validator.internal.engine.ValidationContext; @@ -67,15 +66,15 @@ private ConstraintTree createConstraintTree(Constraint @Override protected void validateConstraints(ValidationContext validationContext, ValueContext valueContext, - Set> constraintViolations) { + Collection violatedConstraintValidatorContexts) { CompositionResult compositionResult = validateComposingConstraints( - validationContext, valueContext, constraintViolations + validationContext, valueContext, violatedConstraintValidatorContexts ); - Set> localViolations; + Optional violatedLocalConstraintValidatorContext; // After all children are validated the actual ConstraintValidator of the constraint itself is executed - if ( mainConstraintNeedsEvaluation( validationContext, constraintViolations ) ) { + if ( mainConstraintNeedsEvaluation( validationContext, violatedConstraintValidatorContexts ) ) { if ( LOG.isTraceEnabled() ) { LOG.tracef( @@ -98,8 +97,7 @@ protected void validateConstraints(ValidationContext validationContext, ); // validate - localViolations = validateSingleConstraint( - validationContext, + violatedLocalConstraintValidatorContext = validateSingleConstraint( valueContext, constraintValidatorContext, validator @@ -107,7 +105,7 @@ protected void validateConstraints(ValidationContext validationContext, // We re-evaluate the boolean composition by taking into consideration also the violations // from the local constraintValidator - if ( localViolations.isEmpty() ) { + if ( !violatedLocalConstraintValidatorContext.isPresent() ) { compositionResult.setAtLeastOneTrue( true ); } else { @@ -115,24 +113,24 @@ protected void validateConstraints(ValidationContext validationContext, } } else { - localViolations = Collections.emptySet(); + violatedLocalConstraintValidatorContext = Optional.empty(); } - if ( !passesCompositionTypeRequirement( constraintViolations, compositionResult ) ) { + if ( !passesCompositionTypeRequirement( violatedConstraintValidatorContexts, compositionResult ) ) { prepareFinalConstraintViolations( - validationContext, valueContext, constraintViolations, localViolations + validationContext, valueContext, violatedConstraintValidatorContexts, violatedLocalConstraintValidatorContext ); } } - private boolean mainConstraintNeedsEvaluation(ValidationContext executionContext, - Set> constraintViolations) { + private boolean mainConstraintNeedsEvaluation(ValidationContext validationContext, + Collection violatedConstraintValidatorContexts) { // we are dealing with a composing constraint with no validator for the main constraint if ( !descriptor.getComposingConstraints().isEmpty() && descriptor.getMatchingConstraintValidatorDescriptors().isEmpty() ) { return false; } - if ( constraintViolations.isEmpty() ) { + if ( violatedConstraintValidatorContexts.isEmpty() ) { return true; } @@ -142,7 +140,7 @@ private boolean mainConstraintNeedsEvaluation(ValidationContext execution } // explicit fail fast mode - if ( executionContext.isFailFastModeEnabled() ) { + if ( validationContext.isFailFastModeEnabled() ) { return false; } @@ -153,33 +151,32 @@ private boolean mainConstraintNeedsEvaluation(ValidationContext execution * Before the final constraint violations can be reported back we need to check whether we have a composing * constraint whose result should be reported as single violation. * - * @param executionContext meta data about top level validation + * @param validationContext meta data about top level validation * @param valueContext meta data for currently validated value - * @param constraintViolations used to accumulate constraint violations - * @param localViolations set of constraint violations of top level constraint + * @param violatedConstraintValidatorContexts used to accumulate constraint validator contexts that cause constraint violations + * @param localConstraintValidatorContext an optional of constraint violations of top level constraint + * */ - private void prepareFinalConstraintViolations(ValidationContext executionContext, + private void prepareFinalConstraintViolations(ValidationContext validationContext, ValueContext valueContext, - Set> constraintViolations, - Set> localViolations) { + Collection violatedConstraintValidatorContexts, + Optional localConstraintValidatorContext) { if ( reportAsSingleViolation() ) { // We clear the current violations list anyway - constraintViolations.clear(); + violatedConstraintValidatorContexts.clear(); // But then we need to distinguish whether the local ConstraintValidator has reported // violations or not (or if there is no local ConstraintValidator at all). // If not we create a violation // using the error message in the annotation declaration at top level. - if ( localViolations.isEmpty() ) { - final String message = getDescriptor().getMessageTemplate(); - ConstraintViolationCreationContext constraintViolationCreationContext = new ConstraintViolationCreationContext( - message, - valueContext.getPropertyPath() - ); - ConstraintViolation violation = executionContext.createConstraintViolation( - valueContext, constraintViolationCreationContext, descriptor - ); - constraintViolations.add( violation ); + if ( !localConstraintValidatorContext.isPresent() ) { + violatedConstraintValidatorContexts.add( new ConstraintValidatorContextImpl( + validationContext.getParameterNames(), + validationContext.getClockProvider(), + valueContext.getPropertyPath(), + descriptor, + validationContext.getConstraintValidatorPayload() + ) ); } } @@ -191,28 +188,30 @@ private void prepareFinalConstraintViolations(ValidationContext execution // as checked in test CustomErrorMessage.java // If no violations have been reported from the local ConstraintValidator, or no such validator exists, // then we just add an empty list. - constraintViolations.addAll( localViolations ); + if ( localConstraintValidatorContext.isPresent() ) { + violatedConstraintValidatorContexts.add( localConstraintValidatorContext.get() ); + } } /** * Validates all composing constraints recursively. * - * @param executionContext Meta data about top level validation + * @param validationContext Meta data about top level validation * @param valueContext Meta data for currently validated value - * @param constraintViolations Used to accumulate constraint violations + * @param violatedConstraintValidatorContexts Used to accumulate constraint validator contexts that cause constraint violations * * @return Returns an instance of {@code CompositionResult} relevant for boolean composition of constraints */ - private CompositionResult validateComposingConstraints(ValidationContext executionContext, + private CompositionResult validateComposingConstraints(ValidationContext validationContext, ValueContext valueContext, - Set> constraintViolations) { + Collection violatedConstraintValidatorContexts) { CompositionResult compositionResult = new CompositionResult( true, false ); for ( ConstraintTree tree : children ) { - Set> tmpViolations = newHashSet( 5 ); - tree.validateConstraints( executionContext, valueContext, tmpViolations ); - constraintViolations.addAll( tmpViolations ); + List tmpConstraintValidatorContexts = new ArrayList<>( 5 ); + tree.validateConstraints( validationContext, valueContext, tmpConstraintValidatorContexts ); + violatedConstraintValidatorContexts.addAll( tmpConstraintValidatorContexts ); - if ( tmpViolations.isEmpty() ) { + if ( tmpConstraintValidatorContexts.isEmpty() ) { compositionResult.setAtLeastOneTrue( true ); // no need to further validate constraints, because at least one validation passed if ( descriptor.getCompositionType() == OR ) { @@ -222,7 +221,7 @@ private CompositionResult validateComposingConstraints(ValidationContext else { compositionResult.setAllTrue( false ); if ( descriptor.getCompositionType() == AND - && ( executionContext.isFailFastModeEnabled() || descriptor.isReportAsSingleViolation() ) ) { + && ( validationContext.isFailFastModeEnabled() || descriptor.isReportAsSingleViolation() ) ) { break; } } @@ -230,7 +229,7 @@ private CompositionResult validateComposingConstraints(ValidationContext return compositionResult; } - private boolean passesCompositionTypeRequirement(Set constraintViolations, CompositionResult compositionResult) { + private boolean passesCompositionTypeRequirement(Collection constraintViolations, CompositionResult compositionResult) { CompositionType compositionType = getDescriptor().getCompositionType(); boolean passedValidation = false; switch ( compositionType ) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java index 3a5e8a08b0..d9130ac1f3 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java @@ -7,17 +7,17 @@ package org.hibernate.validator.internal.engine.constraintvalidation; import static org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.DUMMY_CONSTRAINT_VALIDATOR; -import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandles; import java.lang.reflect.Type; -import java.util.Collections; -import java.util.Set; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Optional; import javax.validation.ConstraintDeclarationException; import javax.validation.ConstraintValidator; -import javax.validation.ConstraintViolation; import javax.validation.ValidationException; import org.hibernate.validator.internal.engine.ValidationContext; @@ -68,17 +68,23 @@ public static ConstraintTree of(ConstraintDescriptorIm } } - public final boolean validateConstraints(ValidationContext executionContext, ValueContext valueContext) { - Set> constraintViolations = newHashSet( 5 ); - validateConstraints( executionContext, valueContext, constraintViolations ); - if ( !constraintViolations.isEmpty() ) { - executionContext.addConstraintFailures( constraintViolations ); + public final boolean validateConstraints(ValidationContext validationContext, ValueContext valueContext) { + List violatedConstraintValidatorContexts = new ArrayList( 5 ); + validateConstraints( validationContext, valueContext, violatedConstraintValidatorContexts ); + if ( !violatedConstraintValidatorContexts.isEmpty() ) { + for ( ConstraintValidatorContextImpl constraintValidatorContext : violatedConstraintValidatorContexts ) { + for ( ConstraintViolationCreationContext constraintViolationCreationContext : constraintValidatorContext.getConstraintViolationCreationContexts() ) { + validationContext.addConstraintFailure( + validationContext.createConstraintViolation( valueContext, constraintViolationCreationContext, ( (ConstraintValidatorContextImpl) constraintValidatorContext ).getConstraintDescriptor() ) + ); + } + } return false; } return true; } - protected abstract void validateConstraints(ValidationContext executionContext, ValueContext valueContext, Set> constraintViolations); + protected abstract void validateConstraints(ValidationContext executionContext, ValueContext valueContext, Collection violatedConstraintValidatorContexts); public final ConstraintDescriptorImpl getDescriptor() { return descriptor; @@ -160,7 +166,11 @@ private ValidationException getExceptionForNullValidator(Type validatedValueType } } - protected final Set> validateSingleConstraint(ValidationContext executionContext, + /** + * @return an {@link Optional#empty()} if there is no violation or a corresponding {@link ConstraintValidatorContextImpl} + * otherwise. + */ + protected final Optional validateSingleConstraint( ValueContext valueContext, ConstraintValidatorContextImpl constraintValidatorContext, ConstraintValidator validator) { @@ -179,11 +189,9 @@ protected final Set> validateSingleConstraint(Vali if ( !isValid ) { //We do not add these violations yet, since we don't know how they are //going to influence the final boolean evaluation - return executionContext.createConstraintViolations( - valueContext, constraintValidatorContext - ); + return Optional.of( constraintValidatorContext ); } - return Collections.emptySet(); + return Optional.empty(); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java index 586c398708..05b17b85cd 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java @@ -9,10 +9,9 @@ import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandles; import java.lang.reflect.Type; -import java.util.Set; +import java.util.Collection; import javax.validation.ConstraintValidator; -import javax.validation.ConstraintViolation; import org.hibernate.validator.internal.engine.ValidationContext; import org.hibernate.validator.internal.engine.ValueContext; @@ -41,7 +40,7 @@ public SimpleConstraintTree(ConstraintDescriptorImpl descriptor, Type validat @Override protected void validateConstraints(ValidationContext validationContext, ValueContext valueContext, - Set> constraintViolations) { + Collection violatedConstraintValidatorContexts) { if ( LOG.isTraceEnabled() ) { LOG.tracef( @@ -64,13 +63,8 @@ protected void validateConstraints(ValidationContext validationContext, ); // validate - constraintViolations.addAll( - validateSingleConstraint( - validationContext, - valueContext, - constraintValidatorContext, - validator - ) - ); + if ( validateSingleConstraint( valueContext, constraintValidatorContext, validator ).isPresent() ) { + violatedConstraintValidatorContexts.add( constraintValidatorContext ); + } } } diff --git a/performance/src/main/java/org/hibernate/validator/performance/simple/SimpleComposingConstraintValidation.java b/performance/src/main/java/org/hibernate/validator/performance/simple/SimpleComposingConstraintValidation.java new file mode 100644 index 0000000000..46c21ce1bc --- /dev/null +++ b/performance/src/main/java/org/hibernate/validator/performance/simple/SimpleComposingConstraintValidation.java @@ -0,0 +1,104 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.performance.simple; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import javax.validation.Constraint; +import javax.validation.ConstraintViolation; +import javax.validation.Payload; +import javax.validation.ReportAsSingleViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Threads; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +/** + * @author Marko Bekhta + */ +public class SimpleComposingConstraintValidation { + + @State(Scope.Benchmark) + public static class ValidationState { + + public volatile Validator validator; + + { + ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + validator = factory.getValidator(); + } + + } + + @Benchmark + @BenchmarkMode(Mode.Throughput) + @OutputTimeUnit(TimeUnit.MILLISECONDS) + @Fork(value = 1) + @Threads(50) + @Warmup(iterations = 10) + @Measurement(iterations = 20) + public void testSimpleComposingConstraintValidation(ValidationState state, Blackhole bh) { + Foo foo = new Foo( "" ); + Set> violations = state.validator.validate( foo ); + bh.consume( violations ); + } + + public static class Foo { + + @ComposingConstraint + private final String foo; + + public Foo(String foo) { + this.foo = foo; + } + } + + @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) + @Retention(RUNTIME) + @Documented + @Constraint(validatedBy = { }) + @ReportAsSingleViolation + @NotNull + @Size(min = 1) + @NotBlank + @NotEmpty + @interface ComposingConstraint { + + String message() default "message"; + + Class[] groups() default { }; + + Class[] payload() default { }; + } +} From 731d506c99a23d41614b8100f99e9d16643e99f0 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 9 Apr 2018 17:03:16 +0200 Subject: [PATCH 011/393] HV-1577 Update the README after the migration to Stax --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index ec1fe6f9a1..c7e7ce62ef 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ There are more build options available as well. For more information refer to [C To build Hibernate Validator with JDK 9, export the following environment variable: - export MAVEN_OPTS="--add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-modules=java.xml.bind" + export MAVEN_OPTS="--add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED Then the build can be started like this: @@ -89,7 +89,6 @@ Here are the reasons why we added the various build options: * add-opens java.security: required by wildfly-maven-plugin:execute-commands (for the WildFly integration tests and the TCK runner running in container mode) * add-opens java.lang: required by JRuby for Asciidoc processing - * add-modules java.xml.bind: required by the forbiddenapis Maven plugin ## Continuous Integration From 6baa71a1e41060879687acf8e0746e66f97f1428 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 2 May 2018 10:47:16 +0200 Subject: [PATCH 012/393] HV-1577 Fix a quote that has been mistakenly dropped in the previous commit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c7e7ce62ef..b3ce5be777 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ There are more build options available as well. For more information refer to [C To build Hibernate Validator with JDK 9, export the following environment variable: - export MAVEN_OPTS="--add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED + export MAVEN_OPTS="--add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED" Then the build can be started like this: From 11fdcac92996a2f75f338e2315298d4efe85fbf5 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 2 May 2018 10:49:51 +0200 Subject: [PATCH 013/393] Update previous stable to 6.0.9.Final --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 96fc787983..f4fe27a04c 100644 --- a/pom.xml +++ b/pom.xml @@ -116,7 +116,7 @@ 2.0.2.Final - 6.0.4.Final + 6.0.9.Final 2.8 3.0.1-b09 From 37ac728092ba7f85c54d315a8e49654a85e8817c Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 30 Apr 2018 16:46:56 +0200 Subject: [PATCH 014/393] HV-1605 Update Surefire to 2.21.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f4fe27a04c..631d537a42 100644 --- a/pom.xml +++ b/pom.xml @@ -203,7 +203,7 @@ http://docs.jboss.org/hibernate/beanvalidation/spec/2.0/api http://javamoney.github.io/apidocs - 2.20.1 + 2.21.0 From 961e94d0e065eb60253fc86120532cdf94d0765a Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 30 Apr 2018 14:56:30 +0200 Subject: [PATCH 015/393] HV-1604 Fix instantiation of the JPATraversableResolver Also raise the log message to WARN as it's important to be warned if there is an issue instantiating it. --- .../resolver/JPATraversableResolver.java | 4 +- .../engine/resolver/TraversableResolvers.java | 5 +- .../validator/internal/util/logging/Log.java | 4 ++ .../JpaTraversableResolverTest.java | 6 +- .../wildfly/jpa/JPATraversableResolverIT.java | 56 +++++++++++++++++++ 5 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 integration/src/test/java/org/hibernate/validator/integration/wildfly/jpa/JPATraversableResolverIT.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/resolver/JPATraversableResolver.java b/engine/src/main/java/org/hibernate/validator/internal/engine/resolver/JPATraversableResolver.java index b1d401ea9a..c4ed299cab 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/resolver/JPATraversableResolver.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/resolver/JPATraversableResolver.java @@ -21,11 +21,13 @@ * query the reachability of a property. * This resolver will be automatically enabled if JPA 2 is on the classpath and the default {@code TraversableResolver} is * used. + *

+ * This class needs to be public as it's instantiated via a privileged action that is not in this package. * * @author Hardy Ferentschik * @author Emmanuel Bernard */ -class JPATraversableResolver implements TraversableResolver { +public class JPATraversableResolver implements TraversableResolver { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/resolver/TraversableResolvers.java b/engine/src/main/java/org/hibernate/validator/internal/engine/resolver/TraversableResolvers.java index f1392120bd..e7c513b884 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/resolver/TraversableResolvers.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/resolver/TraversableResolvers.java @@ -106,10 +106,7 @@ public static TraversableResolver getDefault() { return run( NewInstance.action( jpaAwareResolverClass, "" ) ); } catch (ValidationException e) { - LOG.debugf( - "Unable to load or instantiate JPA aware resolver %s. All properties will per default be traversable.", - JPA_AWARE_TRAVERSABLE_RESOLVER_CLASS_NAME - ); + LOG.logUnableToLoadOrInstantiateJPAAwareResolver( JPA_AWARE_TRAVERSABLE_RESOLVER_CLASS_NAME ); return getTraverseAllTraversableResolver(); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 5978c2b603..f7c68a891e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -845,4 +845,8 @@ ValidationException getUnableToAccessMethodException(Lookup lookup, @FormatWith( @Message(id = 241, value = "Encountered unsupported element %1$s while parsing the XML configuration.") ValidationException logUnknownElementInXmlConfiguration(String tag); + + @LogMessage(level = WARN) + @Message(id = 242, value = "Unable to load or instantiate JPA aware resolver %1$s. All properties will per default be traversable.") + void logUnableToLoadOrInstantiateJPAAwareResolver(String traversableResolverClassName); } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/traversableresolver/JpaTraversableResolverTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/traversableresolver/JpaTraversableResolverTest.java index 200d5836e3..12871b2080 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/traversableresolver/JpaTraversableResolverTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/traversableresolver/JpaTraversableResolverTest.java @@ -14,7 +14,7 @@ import javax.validation.ConstraintViolation; import javax.validation.Validator; -import org.hibernate.validator.internal.engine.resolver.TraversableResolvers; +import org.hibernate.validator.internal.engine.resolver.JPATraversableResolver; import org.hibernate.validator.testutil.TestForIssue; import org.hibernate.validator.testutils.ValidatorUtil; import org.testng.annotations.BeforeTest; @@ -32,7 +32,7 @@ public class JpaTraversableResolverTest { @BeforeTest public void setUp() { Configuration configuration = ValidatorUtil.getConfiguration(); - configuration.traversableResolver( TraversableResolvers.getDefault() ); + configuration.traversableResolver( new JPATraversableResolver() ); validator = configuration.buildValidatorFactory().getValidator(); } @@ -55,5 +55,3 @@ public void testWithoutBooks() { assertTrue( results.isEmpty() ); } } - - diff --git a/integration/src/test/java/org/hibernate/validator/integration/wildfly/jpa/JPATraversableResolverIT.java b/integration/src/test/java/org/hibernate/validator/integration/wildfly/jpa/JPATraversableResolverIT.java new file mode 100644 index 0000000000..a07d7ee8df --- /dev/null +++ b/integration/src/test/java/org/hibernate/validator/integration/wildfly/jpa/JPATraversableResolverIT.java @@ -0,0 +1,56 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.integration.wildfly.jpa; + +import static org.assertj.core.api.Assertions.assertThat; + +import javax.validation.TraversableResolver; + +import org.hibernate.validator.integration.AbstractArquillianIT; +import org.hibernate.validator.internal.engine.resolver.JPATraversableResolver; +import org.hibernate.validator.internal.engine.resolver.TraversableResolvers; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.asset.Asset; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.descriptor.api.Descriptors; +import org.jboss.shrinkwrap.descriptor.api.persistence20.PersistenceDescriptor; +import org.testng.annotations.Test; + +/** + * Tests that the default {@link TraversableResolver} for a JPA environment is {@code JPATraversableResolver}. + * + * @author Guillaume Smet + */ +public class JPATraversableResolverIT extends AbstractArquillianIT { + + private static final String WAR_FILE_NAME = JPATraversableResolverIT.class.getSimpleName() + ".war"; + + @Deployment + public static Archive createTestArchive() { + return buildTestArchive( WAR_FILE_NAME ) + .addAsResource( persistenceXml(), "META-INF/persistence.xml" ) + .addAsWebInfResource( EmptyAsset.INSTANCE, "beans.xml" ); + } + + private static Asset persistenceXml() { + String persistenceXml = Descriptors.create( PersistenceDescriptor.class ) + .version( "2.0" ) + .createPersistenceUnit() + .name( "default" ) + .jtaDataSource( "java:jboss/datasources/ExampleDS" ) + .up() + .exportAsString(); + return new StringAsset( persistenceXml ); + } + + @Test + public void testDefaultTraversableResolverInJPAEnvironmentIsJPATraversableResolver() throws Exception { + assertThat( TraversableResolvers.getDefault() ).isInstanceOf( JPATraversableResolver.class ); + } +} From 7b7e6799760b9df7f6a93a19ccbfcac92629ce8b Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 3 May 2018 16:02:22 +0200 Subject: [PATCH 016/393] HV-1607 Make the build work with JDK 10 We need prevent the OSGi integration tests from running on JDK 10 for now as pax-exam does not support JDK 10. It will be fixed in the not yet released pax-exam 4.12. --- pom.xml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 631d537a42..445531e3dd 100644 --- a/pom.xml +++ b/pom.xml @@ -92,7 +92,6 @@ annotation-processor integration performance - osgi @@ -573,7 +572,7 @@ de.thetaphi forbiddenapis - 2.4.1 + 2.5 false @@ -1130,7 +1129,16 @@ - jdk9 + jdk9- + + (,9] + + + osgi + + + + jdk9+ [9,) From 72072e0e4e12ac4cc35bdb4f1bb4f3cc848a2941 Mon Sep 17 00:00:00 2001 From: Maurice Betzel Date: Fri, 4 May 2018 09:47:44 +0200 Subject: [PATCH 017/393] HV-1612 Add Dutch translation for the validation messages --- .../ValidationMessages_nl.properties | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties new file mode 100644 index 0000000000..023695d2bf --- /dev/null +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties @@ -0,0 +1,45 @@ +javax.validation.constraints.AssertFalse.message = moet onwaar zijn +javax.validation.constraints.AssertTrue.message = moet waar zijn sein +javax.validation.constraints.DecimalMax.message = moet kleiner dan ${strict == false ? 'of gelijk aan ' : ''}{value} zijn +javax.validation.constraints.DecimalMin.message = moet groter dan ${inclusive == true ? 'of gelijk aan ' : ''}{value} zijn +javax.validation.constraints.Digits.message = numerieke waarde ligt buiten het toegestane bereik (<{integer} cijfers>,<{fraction} cijfers> verwacht) +javax.validation.constraints.Email.message = het e-mailadres is ongeldig +javax.validation.constraints.Future.message = moet in de toekomst zijn +javax.validation.constraints.FutureOrPresent.message = moet in het heden of in de toekomst zijn +javax.validation.constraints.Max.message = moet kleiner of gelijk aan {value} zijn +javax.validation.constraints.Min.message = moet groter of gelijk aan {value} zijn +javax.validation.constraints.Negative.message = moet kleiner dan 0 zijn +javax.validation.constraints.NegativeOrZero.message = moet kleiner dan of gelijk aan 0 zijn +javax.validation.constraints.NotBlank.message = mag niet onbeschreven zijn +javax.validation.constraints.NotEmpty.message = mag niet leeg zijn +javax.validation.constraints.NotNull.message = mag niet null zijn +javax.validation.constraints.Null.message = moet null zijn +javax.validation.constraints.Past.message = moet in het verleden zijn +javax.validation.constraints.PastOrPresent.message = moet in het heden of in het verleden zijn +javax.validation.constraints.Pattern.message = moet overeenkomen met "{regexp}" +javax.validation.constraints.Positive.message = moet gtoter dan 0 sein +javax.validation.constraints.PositiveOrZero.message = moet groter of gelijk zijn aan 0 +javax.validation.constraints.Size.message = moet tussen {min} en {max} liggen + +org.hibernate.validator.constraints.CreditCardNumber.message = Creditcard nummer ongeldig +org.hibernate.validator.constraints.Currency.message = ongeldige valuta (toegestane waarden: {value}) +org.hibernate.validator.constraints.EAN.message = ongeldige barcode +org.hibernate.validator.constraints.Email.message = geen geldig e-mailadres +org.hibernate.validator.constraints.ISBN.message = ongeldig ISBN +org.hibernate.validator.constraints.Length.message = moet tussen {min} en {max} tekens lang zijn +org.hibernate.validator.constraints.CodePointLength.message = moet tussen {min} en {max} tekens lang zijn +org.hibernate.validator.constraints.LuhnCheck.message = Het controlecijfer voor ${validatedValue} is ongeldig, Luhn Modulo 10 checksum mislukt +org.hibernate.validator.constraints.Mod10Check.message = Het controlecijfer voor ${validatedValue} is ongeldig, Modulo 10 checksum mislukt +org.hibernate.validator.constraints.Mod11Check.message = Het controlecijfer voor ${validatedValue} is ongeldig, Modulo 11 checksum mislukt +org.hibernate.validator.constraints.ModCheck.message = Het controlecijfer voor ${validatedValue} is ongeldig, ${modType} checksum mislukt +org.hibernate.validator.constraints.NotBlank.message = mag niet onbeschreven zijn +org.hibernate.validator.constraints.NotEmpty.message = mag niet leeg zijn +org.hibernate.validator.constraints.ParametersScriptAssert.message = Scriptexpressie "{script}" is ongeldig +org.hibernate.validator.constraints.Range.message = moet tussen {min} en {max} zijn +org.hibernate.validator.constraints.SafeHtml.message = Kan onveilige HTML-inhoud bevatten +org.hibernate.validator.constraints.ScriptAssert.message = Scriptexpressie "{script}" is ongeldig +org.hibernate.validator.constraints.UniqueElements.message = Mag geen duplicaten bevatten +org.hibernate.validator.constraints.URL.message = moet een geldige URL zijn + +org.hibernate.validator.constraints.time.DurationMax.message = moet korter${inclusive == true ? ' of gelijk' : ' dan'}${days == 0 ? '' : days == 1 ? ' 1 dag' : ' ' += days += ' dagen'}${hours == 0 ? '' : hours == 1 ? ' 1 uur' : ' ' += hours += ' uren'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minuut' : ' ' += minutes += ' Minuten'}${seconds == 0 ? '' : seconds == 1 ? ' 1 seconde' : ' ' += seconds += ' seconden'}${millis == 0 ? '' : millis == 1 ? ' 1 milliseconde' : ' ' += millis += ' milliseconden'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanoseconde' : ' ' += nanos += ' nanoseconden'} sein +org.hibernate.validator.constraints.time.DurationMin.message = moet langer${inclusive == true ? ' of gelijk' : ' dan'}${days == 0 ? '' : days == 1 ? ' 1 dag' : ' ' += days += ' dagen'}${hours == 0 ? '' : hours == 1 ? ' 1 uur' : ' ' += hours += ' uren'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minuut' : ' ' += minutes += ' minuten'}${seconds == 0 ? '' : seconds == 1 ? ' 1 seconde' : ' ' += seconds += ' seconden'}${millis == 0 ? '' : millis == 1 ? ' 1 milliseconde' : ' ' += millis += ' milliseconden'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanoseconde' : ' ' += nanos += ' nanoseconden'} sein From 9f40990aa7054e0e420a41b4d7620b4a609914d2 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Wed, 2 May 2018 18:45:08 +0200 Subject: [PATCH 018/393] HV-1609 Change how we filter which beans to process in CDI extension As @WithAnnotations does not check the interfaces and superclasses and we cannot rely on usage of @Inherited either, filtering is performed "manually" by walking through the class hierarchy and checking all possible places for annotations that would enable the validation. --- .../validator/cdi/ValidationExtension.java | 26 +- .../cdi/internal/ValidateableBeanFilter.java | 161 ++++++++++ .../internal/ValidateableBeanFilterTest.java | 276 ++++++++++++++++++ 3 files changed, 452 insertions(+), 11 deletions(-) create mode 100644 cdi/src/main/java/org/hibernate/validator/cdi/internal/ValidateableBeanFilter.java create mode 100644 cdi/src/test/java/org/hibernate/validator/test/cdi/internal/ValidateableBeanFilterTest.java diff --git a/cdi/src/main/java/org/hibernate/validator/cdi/ValidationExtension.java b/cdi/src/main/java/org/hibernate/validator/cdi/ValidationExtension.java index 45c5ef63f6..cc092fe17b 100644 --- a/cdi/src/main/java/org/hibernate/validator/cdi/ValidationExtension.java +++ b/cdi/src/main/java/org/hibernate/validator/cdi/ValidationExtension.java @@ -18,6 +18,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Set; +import java.util.function.Predicate; import javax.enterprise.event.Observes; import javax.enterprise.inject.Default; @@ -32,12 +33,9 @@ import javax.enterprise.inject.spi.Extension; import javax.enterprise.inject.spi.ProcessAnnotatedType; import javax.enterprise.inject.spi.ProcessBean; -import javax.enterprise.inject.spi.WithAnnotations; import javax.enterprise.util.AnnotationLiteral; import javax.validation.BootstrapConfiguration; import javax.validation.Configuration; -import javax.validation.Constraint; -import javax.validation.Valid; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; @@ -47,6 +45,7 @@ import javax.validation.metadata.PropertyDescriptor; import org.hibernate.validator.cdi.internal.InheritedMethodsHelper; +import org.hibernate.validator.cdi.internal.ValidateableBeanFilter; import org.hibernate.validator.cdi.internal.ValidationProviderHelper; import org.hibernate.validator.cdi.internal.ValidatorBean; import org.hibernate.validator.cdi.internal.ValidatorFactoryBean; @@ -83,6 +82,7 @@ public class ValidationExtension implements Extension { EnumSet.of( ExecutableType.CONSTRUCTORS, ExecutableType.NON_GETTER_METHODS, ExecutableType.GETTER_METHODS ); private static final EnumSet DEFAULT_EXECUTABLE_TYPES = EnumSet.of( ExecutableType.CONSTRUCTORS, ExecutableType.NON_GETTER_METHODS ); + private static final Predicate> VALIDATEABLE_BEAN_FILTER = new ValidateableBeanFilter(); @SuppressWarnings("serial") private final Annotation defaultQualifier = new AnnotationLiteral() { @@ -219,19 +219,23 @@ else if ( bean.getTypes().contains( Validator.class ) || bean instanceof Validat * @param processAnnotatedTypeEvent event fired for each annotated type * @param the annotated type */ - public void processAnnotatedType(@Observes @WithAnnotations({ - Constraint.class, - Valid.class, - ValidateOnExecution.class - }) ProcessAnnotatedType processAnnotatedTypeEvent) { + public void processAnnotatedType(@Observes ProcessAnnotatedType processAnnotatedTypeEvent) { + // NOTE: we cannot use @WithAnnotations for filtering purposes here. + // This annotation does not consider implemented interfaces and super classes for annotations. + // Hence beans with no Hibernate Validator/Bean Validation annotations (@Valid, @Constraint, + // @ValidateOnExecution) on them, that implement interfaces that have such annotations + // will not be pushed to this method if @WithAnnotations is used. + // To prevent filling memory with useless metadata and redundant work in HV we have a custom + // VALIDATEABLE_BEAN_FILTER that checks for annotation presence in the way that we need. Contracts.assertNotNull( processAnnotatedTypeEvent, "The ProcessAnnotatedType event cannot be null" ); - // validation globally disabled - if ( !isExecutableValidationEnabled ) { + AnnotatedType type = processAnnotatedTypeEvent.getAnnotatedType(); + + // validation globally disabled or annotated type has none of needed annotations: + if ( !isExecutableValidationEnabled || !VALIDATEABLE_BEAN_FILTER.test( type.getJavaClass() ) ) { return; } - AnnotatedType type = processAnnotatedTypeEvent.getAnnotatedType(); Set> constrainedCallables = determineConstrainedCallables( type ); if ( !constrainedCallables.isEmpty() ) { diff --git a/cdi/src/main/java/org/hibernate/validator/cdi/internal/ValidateableBeanFilter.java b/cdi/src/main/java/org/hibernate/validator/cdi/internal/ValidateableBeanFilter.java new file mode 100644 index 0000000000..4c9f7a5547 --- /dev/null +++ b/cdi/src/main/java/org/hibernate/validator/cdi/internal/ValidateableBeanFilter.java @@ -0,0 +1,161 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.cdi.internal; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedParameterizedType; +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.function.Predicate; + +import javax.enterprise.inject.spi.WithAnnotations; +import javax.validation.Constraint; +import javax.validation.Valid; +import javax.validation.executable.ValidateOnExecution; + +import org.hibernate.validator.internal.util.CollectionHelper; +import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper; + +/** + * A filter that checks if the passed class has any of these annotations: + *

+ *

+ * on a type level, or on any member, or any parameter of any member. Super classes and all implemented interfaces are + * considered while looking for these annotations. + *

+ * The annotation may be applied as a meta-annotation on any annotation considered. + *

+ * This filter is required as {@link WithAnnotations} does not look for annotations into the class hierarchy. + * + * @author Marko Bekhta + */ +public class ValidateableBeanFilter implements Predicate> { + + private static final Set> MATCHING_ANNOTATIONS = Collections.unmodifiableSet( + CollectionHelper.asSet( Valid.class, Constraint.class, ValidateOnExecution.class ) + ); + + @Override + public boolean test(Class type) { + for ( Class clazz : ClassHierarchyHelper.getHierarchy( type ) ) { + if ( hasMatchingAnnotation( clazz ) ) { + return true; + } + } + + return false; + } + + private boolean hasMatchingAnnotation(Class clazz) { + Set processedAnnotations = new HashSet<>(); + // 1. Is present on a type level: + if ( containsMatchingAnnotation( clazz.getDeclaredAnnotations(), processedAnnotations ) ) { + return true; + } + + // 2. Or on a field level + for ( Field field : clazz.getDeclaredFields() ) { + if ( hasMatchingAnnotation( field.getAnnotatedType(), processedAnnotations ) ) { + return true; + } + if ( containsMatchingAnnotation( field.getDeclaredAnnotations(), processedAnnotations ) ) { + return true; + } + } + // 3. Or on any executable + // 3.1 Constructors + for ( Constructor constructor : clazz.getDeclaredConstructors() ) { + if ( hasMatchingAnnotation( constructor, processedAnnotations ) ) { + return true; + } + } + + // 3.2 Methods + for ( Method method : clazz.getDeclaredMethods() ) { + if ( hasMatchingAnnotation( method, processedAnnotations ) ) { + return true; + } + } + return false; + } + + private boolean containsMatchingAnnotation(Annotation[] annotations, Set processedAnnotations) { + for ( Annotation annotation : annotations ) { + if ( isMatchingAnnotation( annotation, processedAnnotations ) ) { + return true; + } + } + return false; + } + + private boolean hasMatchingAnnotation(AnnotatedType annotatedType, Set processedAnnotations) { + if ( containsMatchingAnnotation( annotatedType.getDeclaredAnnotations(), processedAnnotations ) ) { + return true; + } + if ( annotatedType instanceof AnnotatedParameterizedType ) { + for ( AnnotatedType type : ( (AnnotatedParameterizedType) annotatedType ).getAnnotatedActualTypeArguments() ) { + if ( hasMatchingAnnotation( type, processedAnnotations ) ) { + return true; + } + } + } + return false; + } + + private boolean hasMatchingAnnotation(Executable executable, Set processedAnnotations) { + // Check the executable itself first + if ( containsMatchingAnnotation( executable.getDeclaredAnnotations(), processedAnnotations ) ) { + return true; + } + // Check its return value + if ( hasMatchingAnnotation( executable.getAnnotatedReturnType(), processedAnnotations ) ) { + return true; + } + // Then check its parameters + for ( AnnotatedType annotatedParameterType : executable.getAnnotatedParameterTypes() ) { + if ( hasMatchingAnnotation( annotatedParameterType, processedAnnotations ) ) { + return true; + } + } + // NOTE: this check looks to be redundant BUT without it, test on BeanWithCustomConstraintOnParameter + // will fail as executable.getAnnotatedParameterTypes() on BeanWithCustomConstraintOnParameter#doDefault() + // will not contain matching annotations + for ( Annotation[] annotations : executable.getParameterAnnotations() ) { + if ( containsMatchingAnnotation( annotations, processedAnnotations ) ) { + return true; + } + } + return false; + } + + private boolean isMatchingAnnotation(Annotation annotationToCheck, Set processedAnnotations) { + // Need to have this to prevent infinite loops, for example on annotations like @Target + if ( !processedAnnotations.add( annotationToCheck ) ) { + return false; + } + Class annotationType = annotationToCheck.annotationType(); + if ( MATCHING_ANNOTATIONS.contains( annotationType ) ) { + return true; + } + for ( Annotation annotation : annotationType.getDeclaredAnnotations() ) { + if ( isMatchingAnnotation( annotation, processedAnnotations ) ) { + return true; + } + } + return false; + } +} diff --git a/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/ValidateableBeanFilterTest.java b/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/ValidateableBeanFilterTest.java new file mode 100644 index 0000000000..8d72aba85c --- /dev/null +++ b/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/ValidateableBeanFilterTest.java @@ -0,0 +1,276 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.cdi.internal; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import java.io.Serializable; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Predicate; + +import javax.validation.Constraint; +import javax.validation.Payload; +import javax.validation.Valid; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; +import javax.validation.executable.ExecutableType; +import javax.validation.executable.ValidateOnExecution; + +import org.hibernate.validator.cdi.internal.ValidateableBeanFilter; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * @author Marko Bekhta + */ +public class ValidateableBeanFilterTest { + + private Predicate> predicate; + + @BeforeMethod + public void setUp() { + this.predicate = new ValidateableBeanFilter(); + } + + @Test + public void test() { + // Cases where no required annotations are present: + // 1. Object doesn't have any required annotations + assertFalse( predicate.test( Object.class ) ); + // 2. Simple class with no annotations + assertFalse( predicate.test( SimpleClassWithNoAnnotations.class ) ); + // 3. Class that implements a lot of interfaces but there's no required annotations on it + assertFalse( predicate.test( ImplementsALotOfInterfacesButNoneAreAnnotated.class ) ); + + // Cases where annotation could be found somewhere: + // 1. A constraint annotation on an interface + assertTrue( predicate.test( InterfaceWithConstraintAnnotation.class ) ); + // 2. Class that doesn't have any own annotations but implements an interface with one + assertTrue( predicate.test( NoAnnotationsOfItsOwnButImplementsAnnotatedInterface.class ) ); + // 3. Class with deeper hierarchy and its own annotation + assertTrue( predicate.test( ExtendsCleanClassButHasOwnAnnotation.class ) ); + + // 4. Interface with @Valid and class that implements it + assertTrue( predicate.test( ImplementsInterfaceWithValidAnnotation.class ) ); + assertTrue( predicate.test( InterfaceWithValidAnnotation.class ) ); + + // 5. Interface with constraint and class that implements it + assertTrue( predicate.test( InterfaceWithConstraintAnnotation.class ) ); + assertTrue( predicate.test( ImplementsInterfaceWithConstraintAnnotation.class ) ); + + // 6. Interface with @ValidateOnExecution and class that implements it + assertTrue( predicate.test( ImplementsInterfaceWithValidateOnExecutionAnnotation.class ) ); + assertTrue( predicate.test( InterfaceWithValidateOnExecutionAnnotation.class ) ); + + // 7. Class with annotated field + assertTrue( predicate.test( AnnotatedField.class ) ); + + // 8. Class with annotated constructor + assertTrue( predicate.test( AnnotatedConstructor.class ) ); + + // 9. Annotated type arguments + assertTrue( predicate.test( TypeArgumentField.class ) ); + assertTrue( predicate.test( TypeArgumentReturnValue.class ) ); + assertTrue( predicate.test( TypeArgumentMethodParameter.class ) ); + assertTrue( predicate.test( TypeArgumentConstructorParameter.class ) ); + assertTrue( predicate.test( NestedTypeArgumentField.class ) ); + assertTrue( predicate.test( DeepNestedAnnotatedMethodParameter.class ) ); + + // 10. Custom user constraint: + assertTrue( predicate.test( BeanWithCustomConstraintOnParameter.class ) ); + assertTrue( predicate.test( BeanWithCustomConstraintOnField.class ) ); + assertTrue( predicate.test( BeanWithCustomConstraintOnReturnValue.class ) ); + } + + @SuppressWarnings("unused") + private static class AnnotatedMethodParameter { + void doSomething(@NotNull String string) { + } + } + + private static class DeepNestedAnnotatedMethodParameter { + @SuppressWarnings("unused") + void doSomething(List>>>> strings) { + } + } + + private static class TypeArgumentField { + @SuppressWarnings("unused") + private List<@NotNull String> strings; + } + + private static class NestedTypeArgumentField { + @SuppressWarnings("unused") + private List> strings; + } + + private static class TypeArgumentReturnValue { + @SuppressWarnings("unused") + List<@NotNull String> strings() { + return null; + } + } + + private static class TypeArgumentMethodParameter { + @SuppressWarnings("unused") + void strings(List<@NotNull String> strings) { + } + } + + private static class TypeArgumentConstructorParameter { + @SuppressWarnings("unused") + TypeArgumentConstructorParameter(List<@NotNull String> strings) { + } + } + + private static class AnnotatedConstructor { + @Valid + public AnnotatedConstructor() { + } + } + + private static class AnnotatedField { + @Min(10) + private int num; + } + + private static class SimpleClassWithNoAnnotations { + + @SuppressWarnings("unused") + public void doNothing() { + } + } + + private static class NoAnnotationsOfItsOwnButImplementsAnnotatedInterface extends SimpleClassWithNoAnnotations implements InterfaceWithConstraintAnnotation { + + @Override + public int bar() { + return 0; + } + + @SuppressWarnings("unused") + public void doSomething(int foo) { + } + } + + interface InterfaceWithConstraintAnnotation { + + @Min(10) + int bar(); + } + + private static class ImplementsInterfaceWithConstraintAnnotation implements InterfaceWithConstraintAnnotation { + + @Override + public int bar() { + return 0; + } + } + + interface InterfaceWithValidAnnotation { + + @Valid + SimpleClassWithNoAnnotations bar(); + } + + private static class ImplementsInterfaceWithValidAnnotation implements InterfaceWithValidAnnotation { + + @Override + public SimpleClassWithNoAnnotations bar() { + return null; + } + } + + @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS) + interface InterfaceWithValidateOnExecutionAnnotation { + + int bar(); + } + + private static class ImplementsInterfaceWithValidateOnExecutionAnnotation implements InterfaceWithValidateOnExecutionAnnotation { + @Override + public int bar() { + return 0; + } + } + + private static class ImplementsALotOfInterfacesButNoneAreAnnotated implements Serializable, Predicate, Comparable { + + @Override + public int compareTo(ImplementsALotOfInterfacesButNoneAreAnnotated o) { + return 0; + } + + @Override + public boolean test(Integer integer) { + return false; + } + } + + private static class ExtendsCleanClassButHasOwnAnnotation extends ImplementsALotOfInterfacesButNoneAreAnnotated { + + @ValidateOnExecution + public int bar() { + return 0; + } + } + + /** + * This class and {@link ValidNumber} is taken from Felix tests, where the issue was initially + * discovered. + */ + public static class BeanWithCustomConstraintOnParameter { + + public void doDefault(@ValidNumber String number) { + } + } + + public static class BeanWithCustomConstraintOnField { + private @ValidNumber String number; + } + + + public static class BeanWithCustomConstraintOnReturnValue { + @ValidNumber + String number() { + return null; + } + } + + @Documented + @Target({ ANNOTATION_TYPE, METHOD, FIELD, CONSTRUCTOR, PARAMETER }) + @Retention(RUNTIME) + @Constraint(validatedBy = {}) + @Size(min = 3, message = "Must be 3 at least") + @Pattern(regexp = "[0-9]*") + @NotNull(message = "Cannot be null") + public @interface ValidNumber { + + String message() default "invalid number"; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String value() default ""; + } +} From 18638bbbe0923969685db6d0aea7dce5f3b9ac65 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 2 May 2018 11:06:24 +0200 Subject: [PATCH 019/393] HV-1606 Update TCK to 2.0.3.Final --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 445531e3dd..a33cea01d4 100644 --- a/pom.xml +++ b/pom.xml @@ -112,7 +112,7 @@ true 2.0.1.Final - 2.0.2.Final + 2.0.3.Final 6.0.9.Final From 2d1ff8cc0b605b0bd13cb747e7f7fba72cbc140a Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 20 Mar 2018 17:34:59 +0100 Subject: [PATCH 020/393] HV-1592 Fix a constraint pointing to an incorrect validator --- .../crossparameter/DodgyConstraint.java | 13 +++++----- .../DodgyConstraintValidator.java | 24 +++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/crossparameter/DodgyConstraintValidator.java diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/crossparameter/DodgyConstraint.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/crossparameter/DodgyConstraint.java index 837a37d379..c23db0079e 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/crossparameter/DodgyConstraint.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/crossparameter/DodgyConstraint.java @@ -6,24 +6,25 @@ */ package org.hibernate.validator.test.internal.engine.methodvalidation.crossparameter; +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; + import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; + import javax.validation.Constraint; import javax.validation.Payload; -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; - /** * @author Hardy Ferentschik */ @Target({ TYPE, FIELD, METHOD, ANNOTATION_TYPE }) @Retention(RetentionPolicy.RUNTIME) -@Constraint(validatedBy = { CrossParameterValidator1.class }) +@Constraint(validatedBy = { DodgyConstraintValidator.class }) @Documented public @interface DodgyConstraint { String message() default "{ConsistentDateParameters.message}"; diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/crossparameter/DodgyConstraintValidator.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/crossparameter/DodgyConstraintValidator.java new file mode 100644 index 0000000000..a1d3cb4edd --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/crossparameter/DodgyConstraintValidator.java @@ -0,0 +1,24 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.engine.methodvalidation.crossparameter; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import javax.validation.constraintvalidation.SupportedValidationTarget; +import javax.validation.constraintvalidation.ValidationTarget; + +/** + * @author Hardy Ferentschik + */ +@SupportedValidationTarget( value = ValidationTarget.PARAMETERS) +public class DodgyConstraintValidator implements ConstraintValidator { + + @Override + public boolean isValid(Object[] value, ConstraintValidatorContext context) { + return false; + } +} From 1f34de5c63fba4219e708b5dc2dc20cfe9a01aee Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 20 Mar 2018 17:35:27 +0100 Subject: [PATCH 021/393] HV-1592 Validate that the validator is defined with the right constraint --- .../ConstraintDefinitionContextImpl.java | 2 +- .../ClassBasedValidatorDescriptor.java | 22 +++++++--- .../ConstraintValidatorDescriptor.java | 5 ++- .../metadata/core/ConstraintHelper.java | 19 +++++---- .../validator/internal/util/TypeHelper.java | 28 +++++++++---- .../validator/internal/util/logging/Log.java | 6 +++ .../ConstraintDefinitionStaxBuilder.java | 2 +- .../ConstraintDefinitionTypeMismatchTest.java | 41 +++++++++++++++++++ .../TypeMismatchConstraint.java | 31 ++++++++++++++ .../test/internal/util/TypeHelperTest.java | 2 +- 10 files changed, 130 insertions(+), 28 deletions(-) create mode 100644 engine/src/test/java/org/hibernate/validator/test/constraintvalidator/ConstraintDefinitionTypeMismatchTest.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/constraintvalidator/TypeMismatchConstraint.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintDefinitionContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintDefinitionContextImpl.java index 6478ac3611..b49a0b8213 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintDefinitionContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintDefinitionContextImpl.java @@ -47,7 +47,7 @@ public ConstraintDefinitionContext includeExistingValidators(boolean includeE @Override public ConstraintDefinitionContext validatedBy(Class> validator) { - validatorDescriptors.add( ConstraintValidatorDescriptor.forClass( validator ) ); + validatorDescriptors.add( ConstraintValidatorDescriptor.forClass( validator, this.annotationType ) ); return this; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ClassBasedValidatorDescriptor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ClassBasedValidatorDescriptor.java index ab1bc49ece..fd5f8c96ce 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ClassBasedValidatorDescriptor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ClassBasedValidatorDescriptor.java @@ -25,28 +25,38 @@ * Represents an implementation of {@link ConstraintValidator}. * * @author Gunnar Morling + * @author Guillaume Smet */ class ClassBasedValidatorDescriptor implements ConstraintValidatorDescriptor { - private static final long serialVersionUID = -8207687559460098548L; private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); private final Class> validatorClass; private final Type validatedType; private final EnumSet validationTargets; - public ClassBasedValidatorDescriptor(Class> validatorClass) { + private ClassBasedValidatorDescriptor(Class> validatorClass) { this.validatorClass = validatorClass; - this.validatedType = TypeHelper.extractType( validatorClass ); + this.validatedType = TypeHelper.extractValidatedType( validatorClass ); this.validationTargets = determineValidationTargets( validatorClass ); } + public static ClassBasedValidatorDescriptor of(Class> validatorClass, + Class registeredConstraintAnnotationType) { + Type definedConstraintAnnotationType = TypeHelper.extractConstraintType( validatorClass ); + if ( !registeredConstraintAnnotationType.equals( definedConstraintAnnotationType ) ) { + throw LOG.getConstraintValidatorDefinitionConstraintMismatchException( validatorClass, registeredConstraintAnnotationType, + definedConstraintAnnotationType ); + } + + return new ClassBasedValidatorDescriptor( validatorClass ); + } + private static EnumSet determineValidationTargets(Class> validatorClass) { SupportedValidationTarget supportedTargetAnnotation = validatorClass.getAnnotation( - SupportedValidationTarget.class - ); + SupportedValidationTarget.class ); - //by default constraints target the annotated element + // by default constraints target the annotated element if ( supportedTargetAnnotation == null ) { return EnumSet.of( ValidationTarget.ANNOTATED_ELEMENT ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorDescriptor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorDescriptor.java index 7132ad1c9a..cb4da5b2ec 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorDescriptor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorDescriptor.java @@ -44,8 +44,9 @@ public interface ConstraintValidatorDescriptor { */ ConstraintValidator newInstance(ConstraintValidatorFactory constraintValidatorFactory); - static ConstraintValidatorDescriptor forClass(Class> validatorClass) { - return new ClassBasedValidatorDescriptor<>( validatorClass ); + static ConstraintValidatorDescriptor forClass(Class> validatorClass, + Class constraintAnnotationType) { + return ClassBasedValidatorDescriptor.of( validatorClass, constraintAnnotationType ); } static ConstraintValidatorDescriptor forLambda(Class annotationType, Type validatedType, ValidationCallable lambda) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java index 9d0ca63446..1e24b5e3da 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java @@ -679,21 +679,24 @@ public ConstraintHelper() { this.builtinConstraints = Collections.unmodifiableMap( tmpConstraints ); } - private static void putConstraint(Map, List>> validators, Class constraintType, Class> validatorType) { - validators.put( constraintType, Collections.singletonList( ConstraintValidatorDescriptor.forClass( validatorType ) ) ); + private static void putConstraint(Map, List>> validators, + Class constraintType, Class> validatorType) { + validators.put( constraintType, Collections.singletonList( ConstraintValidatorDescriptor.forClass( validatorType, constraintType ) ) ); } - private static void putConstraints(Map, List>> validators, Class constraintType, Class> validatorType1, Class> validatorType2) { + private static void putConstraints(Map, List>> validators, + Class constraintType, Class> validatorType1, Class> validatorType2) { List> descriptors = Stream.of( validatorType1, validatorType2 ) - .map( ConstraintValidatorDescriptor::forClass ) + .map( vt -> ConstraintValidatorDescriptor.forClass( vt, constraintType ) ) .collect( Collectors.toList() ); validators.put( constraintType, CollectionHelper.toImmutableList( descriptors ) ); } - private static void putConstraints(Map, List>> validators, Class constraintType, List>> validatorDescriptors) { + private static void putConstraints(Map, List>> validators, + Class constraintType, List>> validatorDescriptors) { List> descriptors = validatorDescriptors.stream() - .map( ConstraintValidatorDescriptor::forClass ) + .map( vt -> ConstraintValidatorDescriptor.forClass( vt, constraintType ) ) .collect( Collectors.toList() ); validators.put( constraintType, CollectionHelper.toImmutableList( descriptors ) ); @@ -995,8 +998,8 @@ private List> getDefault .validatedBy(); return Stream.of( validatedBy ) - .map( c -> ConstraintValidatorDescriptor.forClass( c ) ) - .collect( Collectors.collectingAndThen( Collectors.toList(), CollectionHelper::toImmutableList ) ); + .map( c -> ConstraintValidatorDescriptor.forClass( c, annotationType ) ) + .collect( Collectors.collectingAndThen( Collectors.toList(), CollectionHelper::toImmutableList ) ); } private static boolean isClassPresent(String className) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/TypeHelper.java b/engine/src/main/java/org/hibernate/validator/internal/util/TypeHelper.java index 680100121c..a657a582e6 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/TypeHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/TypeHelper.java @@ -31,6 +31,7 @@ import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -52,6 +53,7 @@ public final class TypeHelper { private static final Map, Set>> SUBTYPES_BY_PRIMITIVE; + private static final int CONSTRAINT_TYPE_INDEX = 0; private static final int VALIDATOR_TYPE_INDEX = 1; private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); @@ -324,24 +326,32 @@ public static Map> return validatorsTypes; } - public static Type extractType(Class> validator) { - Map resolvedTypes = newHashMap(); + public static Type extractValidatedType(Class> validator) { + return extractConstraintValidatorTypeArgumentType( validator, VALIDATOR_TYPE_INDEX ); + } + + public static Type extractConstraintType(Class> validator) { + return extractConstraintValidatorTypeArgumentType( validator, CONSTRAINT_TYPE_INDEX ); + } + + public static Type extractConstraintValidatorTypeArgumentType(Class> validator, int typeArgumentIndex) { + Map resolvedTypes = new HashMap<>(); Type constraintValidatorType = resolveTypes( resolvedTypes, validator ); //we now have all bind from a type to its resolution at one level - Type validatorType = ( (ParameterizedType) constraintValidatorType ).getActualTypeArguments()[VALIDATOR_TYPE_INDEX]; - if ( validatorType == null ) { + Type type = ( (ParameterizedType) constraintValidatorType ).getActualTypeArguments()[typeArgumentIndex]; + if ( type == null ) { throw LOG.getNullIsAnInvalidTypeForAConstraintValidatorException(); } - else if ( validatorType instanceof GenericArrayType ) { - validatorType = TypeHelper.getArrayType( TypeHelper.getComponentType( validatorType ) ); + else if ( type instanceof GenericArrayType ) { + type = TypeHelper.getArrayType( TypeHelper.getComponentType( type ) ); } - while ( resolvedTypes.containsKey( validatorType ) ) { - validatorType = resolvedTypes.get( validatorType ); + while ( resolvedTypes.containsKey( type ) ) { + type = resolvedTypes.get( type ); } //FIXME raise an exception if validatorType is not a class - return validatorType; + return type; } public static boolean isUnboundWildcard(Type type) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index f7c68a891e..d0cba30970 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -849,4 +849,10 @@ ValidationException getUnableToAccessMethodException(Lookup lookup, @FormatWith( @LogMessage(level = WARN) @Message(id = 242, value = "Unable to load or instantiate JPA aware resolver %1$s. All properties will per default be traversable.") void logUnableToLoadOrInstantiateJPAAwareResolver(String traversableResolverClassName); + + @Message(id = 243, value = "Constraint %2$s references constraint validator type %1$s, but this validator is defined for constraint type %3$s.") + ConstraintDefinitionException getConstraintValidatorDefinitionConstraintMismatchException( + @FormatWith(ClassObjectFormatter.class) Class> constraintValidatorImplementationType, + @FormatWith(ClassObjectFormatter.class) Class registeredConstraintAnnotationType, + @FormatWith(TypeFormatter.class) Type declaredConstraintAnnotationType); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintDefinitionStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintDefinitionStaxBuilder.java index 69e7af4f55..a600d370be 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintDefinitionStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintDefinitionStaxBuilder.java @@ -140,7 +140,7 @@ List> build(Class ann .map( value -> classLoadingHelper.loadClass( value, defaultPackage ) ) .peek( this::checkValidatorAssignability ) .map( clazz -> (Class>) clazz ) - .map( ConstraintValidatorDescriptor::forClass ) + .map( validatorClass -> ConstraintValidatorDescriptor.forClass( validatorClass, annotation ) ) .collect( Collectors.toList() ); } diff --git a/engine/src/test/java/org/hibernate/validator/test/constraintvalidator/ConstraintDefinitionTypeMismatchTest.java b/engine/src/test/java/org/hibernate/validator/test/constraintvalidator/ConstraintDefinitionTypeMismatchTest.java new file mode 100644 index 0000000000..56ea9c5d48 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/constraintvalidator/ConstraintDefinitionTypeMismatchTest.java @@ -0,0 +1,41 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.constraintvalidator; + +import static org.hibernate.validator.testutils.ValidatorUtil.getValidator; + +import javax.validation.ConstraintDefinitionException; +import javax.validation.Validator; + +import org.hibernate.validator.testutil.TestForIssue; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * @author Guillaume Smet + */ +@TestForIssue(jiraKey = "HV-1592") +public class ConstraintDefinitionTypeMismatchTest { + + private Validator validator; + + @BeforeMethod + public void setUp() { + validator = getValidator(); + } + + @Test(expectedExceptions = ConstraintDefinitionException.class, expectedExceptionsMessageRegExp = "^HV000243:.*") + public void constraint_validator_constraint_type_mismatch_causes_exception() { + validator.validate( new TypeMismatchBean() ); + } + + public class TypeMismatchBean { + + @TypeMismatchConstraint + private String property; + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/constraintvalidator/TypeMismatchConstraint.java b/engine/src/test/java/org/hibernate/validator/test/constraintvalidator/TypeMismatchConstraint.java new file mode 100644 index 0000000000..98237a2b14 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/constraintvalidator/TypeMismatchConstraint.java @@ -0,0 +1,31 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.constraintvalidator; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + + +@Documented +@Constraint(validatedBy = MustNotMatchValidator.class) +@Target({ METHOD, FIELD }) +@Retention(RUNTIME) +public @interface TypeMismatchConstraint { + String message() default "{org.hibernate.validator.test.constraintvalidator.TypeMismatchConstraint.message}"; + + Class[] groups() default { }; + + Class[] payload() default { }; +} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/util/TypeHelperTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/util/TypeHelperTest.java index a37d99ef0b..efe128ad6a 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/util/TypeHelperTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/util/TypeHelperTest.java @@ -858,7 +858,7 @@ public void isArrayWithParameterizedType() { @Test public void testTypeDiscovery() { List> validatorDescriptors = new ArrayList<>(); - validatorDescriptors.add( ConstraintValidatorDescriptor.forClass( PositiveConstraintValidator.class ) ); + validatorDescriptors.add( ConstraintValidatorDescriptor.forClass( PositiveConstraintValidator.class, Positive.class ) ); Map> validatorsTypes = TypeHelper .getValidatorTypes( Positive.class, validatorDescriptors ); From 8a20b4f7d3f0aa7c02a2596d7920a30c01e973c3 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 22 Mar 2018 17:18:42 +0100 Subject: [PATCH 022/393] HV-1598 Fix the behavior of XML default-validated-executable-types If NONE is present, it should be removed from the Set, rather than considering the Set as empty. --- .../config/BootstrapConfigurationImpl.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/config/BootstrapConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/xml/config/BootstrapConfigurationImpl.java index cf348967c7..f29c16f3b5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/config/BootstrapConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/config/BootstrapConfigurationImpl.java @@ -16,6 +16,7 @@ import javax.validation.BootstrapConfiguration; import javax.validation.executable.ExecutableType; +import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.stereotypes.Immutable; /** @@ -109,15 +110,23 @@ private Set prepareValidatedExecutableTypes(EnumSet preparedValidatedExecutableTypes = EnumSet.copyOf( validatedExecutableTypes ); + preparedValidatedExecutableTypes.remove( ExecutableType.NONE ); + return CollectionHelper.toImmutableSet( preparedValidatedExecutableTypes ); + } } + + return CollectionHelper.toImmutableSet( validatedExecutableTypes ); } @Override From 1dd038f48830854ca4d2c98fb7a8b1ef2d911cfe Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 4 May 2018 13:15:31 +0200 Subject: [PATCH 023/393] HV-1611 Be consistent in the case of the validation messages --- .../validator/ValidationMessages.properties | 14 +++---- .../ValidationMessages_hu.properties | 2 +- .../ValidationMessages_nl.properties | 18 ++++----- .../ValidationMessages_pt_BR.properties | 38 +++++++++---------- .../ValidationMessages_ru.properties | 8 ++-- .../ValidationMessages_sk.properties | 8 ++-- ...ProgrammaticConstraintDefinitionsTest.java | 8 ++-- 7 files changed, 48 insertions(+), 48 deletions(-) diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages.properties index c9d3ac8536..2cb1354faa 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages.properties @@ -28,10 +28,10 @@ org.hibernate.validator.constraints.Email.message = not a well org.hibernate.validator.constraints.ISBN.message = invalid ISBN org.hibernate.validator.constraints.Length.message = length must be between {min} and {max} org.hibernate.validator.constraints.CodePointLength.message = length must be between {min} and {max} -org.hibernate.validator.constraints.LuhnCheck.message = The check digit for ${validatedValue} is invalid, Luhn Modulo 10 checksum failed -org.hibernate.validator.constraints.Mod10Check.message = The check digit for ${validatedValue} is invalid, Modulo 10 checksum failed -org.hibernate.validator.constraints.Mod11Check.message = The check digit for ${validatedValue} is invalid, Modulo 11 checksum failed -org.hibernate.validator.constraints.ModCheck.message = The check digit for ${validatedValue} is invalid, ${modType} checksum failed +org.hibernate.validator.constraints.LuhnCheck.message = the check digit for ${validatedValue} is invalid, Luhn Modulo 10 checksum failed +org.hibernate.validator.constraints.Mod10Check.message = the check digit for ${validatedValue} is invalid, Modulo 10 checksum failed +org.hibernate.validator.constraints.Mod11Check.message = the check digit for ${validatedValue} is invalid, Modulo 11 checksum failed +org.hibernate.validator.constraints.ModCheck.message = the check digit for ${validatedValue} is invalid, ${modType} checksum failed org.hibernate.validator.constraints.NotBlank.message = may not be empty org.hibernate.validator.constraints.NotEmpty.message = may not be empty org.hibernate.validator.constraints.ParametersScriptAssert.message = script expression "{script}" didn't evaluate to true @@ -45,9 +45,9 @@ org.hibernate.validator.constraints.br.CNPJ.message = invalid Br org.hibernate.validator.constraints.br.CPF.message = invalid Brazilian individual taxpayer registry number (CPF) org.hibernate.validator.constraints.br.TituloEleitoral.message = invalid Brazilian Voter ID card number -org.hibernate.validator.constraints.pl.REGON.message = Invalid Polish Taxpayer Identification Number (REGON) -org.hibernate.validator.constraints.pl.NIP.message = Invalid VAT Identification Number (NIP) -org.hibernate.validator.constraints.pl.PESEL.message = Invalid Polish National Identification Number (PESEL) +org.hibernate.validator.constraints.pl.REGON.message = invalid Polish Taxpayer Identification Number (REGON) +org.hibernate.validator.constraints.pl.NIP.message = invalid VAT Identification Number (NIP) +org.hibernate.validator.constraints.pl.PESEL.message = invalid Polish National Identification Number (PESEL) org.hibernate.validator.constraints.time.DurationMax.message = must be shorter than${inclusive == true ? ' or equal to' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} org.hibernate.validator.constraints.time.DurationMin.message = must be longer than${inclusive == true ? ' or equal to' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_hu.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_hu.properties index 022339af3b..05fa1151f3 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_hu.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_hu.properties @@ -22,6 +22,6 @@ org.hibernate.validator.constraints.CodePointLength.message = a hossznak {min} org.hibernate.validator.constraints.NotBlank.message = nem lehet \u00FCres org.hibernate.validator.constraints.NotEmpty.message = nem lehet \u00FCres org.hibernate.validator.constraints.Range.message = az \u00E9rt\u00E9knek {min} \u00E9s {max} k\u00F6z\u00F6tt kell lennie -org.hibernate.validator.constraints.SafeHtml.message = Lehet, hogy nem biztons\u00E1gos html tartalom +org.hibernate.validator.constraints.SafeHtml.message = lehet, hogy nem biztons\u00E1gos html tartalom org.hibernate.validator.constraints.ScriptAssert.message = script kifejez\u00E9s "{script}" nem \u00E9rt\u00E9kel\u0151d\u00F6tt ki igazz\u00E1 org.hibernate.validator.constraints.URL.message = \u00E9rv\u00E9nyes URL-nek kell lennie diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties index 023695d2bf..e2da1b36a1 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties @@ -21,24 +21,24 @@ javax.validation.constraints.Positive.message = moet gtoter dan 0 sein javax.validation.constraints.PositiveOrZero.message = moet groter of gelijk zijn aan 0 javax.validation.constraints.Size.message = moet tussen {min} en {max} liggen -org.hibernate.validator.constraints.CreditCardNumber.message = Creditcard nummer ongeldig +org.hibernate.validator.constraints.CreditCardNumber.message = creditcard nummer ongeldig org.hibernate.validator.constraints.Currency.message = ongeldige valuta (toegestane waarden: {value}) org.hibernate.validator.constraints.EAN.message = ongeldige barcode org.hibernate.validator.constraints.Email.message = geen geldig e-mailadres org.hibernate.validator.constraints.ISBN.message = ongeldig ISBN org.hibernate.validator.constraints.Length.message = moet tussen {min} en {max} tekens lang zijn org.hibernate.validator.constraints.CodePointLength.message = moet tussen {min} en {max} tekens lang zijn -org.hibernate.validator.constraints.LuhnCheck.message = Het controlecijfer voor ${validatedValue} is ongeldig, Luhn Modulo 10 checksum mislukt -org.hibernate.validator.constraints.Mod10Check.message = Het controlecijfer voor ${validatedValue} is ongeldig, Modulo 10 checksum mislukt -org.hibernate.validator.constraints.Mod11Check.message = Het controlecijfer voor ${validatedValue} is ongeldig, Modulo 11 checksum mislukt -org.hibernate.validator.constraints.ModCheck.message = Het controlecijfer voor ${validatedValue} is ongeldig, ${modType} checksum mislukt +org.hibernate.validator.constraints.LuhnCheck.message = het controlecijfer voor ${validatedValue} is ongeldig, Luhn Modulo 10 checksum mislukt +org.hibernate.validator.constraints.Mod10Check.message = het controlecijfer voor ${validatedValue} is ongeldig, Modulo 10 checksum mislukt +org.hibernate.validator.constraints.Mod11Check.message = het controlecijfer voor ${validatedValue} is ongeldig, Modulo 11 checksum mislukt +org.hibernate.validator.constraints.ModCheck.message = het controlecijfer voor ${validatedValue} is ongeldig, ${modType} checksum mislukt org.hibernate.validator.constraints.NotBlank.message = mag niet onbeschreven zijn org.hibernate.validator.constraints.NotEmpty.message = mag niet leeg zijn -org.hibernate.validator.constraints.ParametersScriptAssert.message = Scriptexpressie "{script}" is ongeldig +org.hibernate.validator.constraints.ParametersScriptAssert.message = scriptexpressie "{script}" is ongeldig org.hibernate.validator.constraints.Range.message = moet tussen {min} en {max} zijn -org.hibernate.validator.constraints.SafeHtml.message = Kan onveilige HTML-inhoud bevatten -org.hibernate.validator.constraints.ScriptAssert.message = Scriptexpressie "{script}" is ongeldig -org.hibernate.validator.constraints.UniqueElements.message = Mag geen duplicaten bevatten +org.hibernate.validator.constraints.SafeHtml.message = kan onveilige HTML-inhoud bevatten +org.hibernate.validator.constraints.ScriptAssert.message = scriptexpressie "{script}" is ongeldig +org.hibernate.validator.constraints.UniqueElements.message = mag geen duplicaten bevatten org.hibernate.validator.constraints.URL.message = moet een geldige URL zijn org.hibernate.validator.constraints.time.DurationMax.message = moet korter${inclusive == true ? ' of gelijk' : ' dan'}${days == 0 ? '' : days == 1 ? ' 1 dag' : ' ' += days += ' dagen'}${hours == 0 ? '' : hours == 1 ? ' 1 uur' : ' ' += hours += ' uren'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minuut' : ' ' += minutes += ' Minuten'}${seconds == 0 ? '' : seconds == 1 ? ' 1 seconde' : ' ' += seconds += ' seconden'}${millis == 0 ? '' : millis == 1 ? ' 1 milliseconde' : ' ' += millis += ' milliseconden'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanoseconde' : ' ' += nanos += ' nanoseconden'} sein diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties index 0d6c0a89c7..14861f48f2 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties @@ -3,15 +3,15 @@ javax.validation.constraints.AssertTrue.message = deve ser verdadeiro javax.validation.constraints.DecimalMax.message = deve ser menor ou igual a {value} javax.validation.constraints.DecimalMin.message = deve ser maior ou igual a {value} javax.validation.constraints.Digits.message = valor num\u00E9rico fora do limite (<{integer} d\u00EDgitos>.<{fraction} d\u00EDgitos> esperado) -javax.validation.constraints.Email.message = N\u00E3o \u00E9 um endere\u00E7o de e-mail +javax.validation.constraints.Email.message = n\u00E3o \u00E9 um endere\u00E7o de e-mail javax.validation.constraints.Future.message = deve estar no futuro javax.validation.constraints.FutureOrPresent.message = deve de ser uma data em presente ou em futuro javax.validation.constraints.Max.message = deve ser menor ou igual a {value} javax.validation.constraints.Min.message = deve ser maior ou igual a {value} javax.validation.constraints.Negative.message = deve ser menor que 0 javax.validation.constraints.NegativeOrZero.message = deve ser menor ou igual a 0 -javax.validation.constraints.NotBlank.message = N\u00E3o pode estar em branco -javax.validation.constraints.NotEmpty.message = N\u00E3o pode estar vazio +javax.validation.constraints.NotBlank.message = n\u00E3o pode estar em branco +javax.validation.constraints.NotEmpty.message = n\u00E3o pode estar vazio javax.validation.constraints.NotNull.message = n\u00E3o pode ser nulo javax.validation.constraints.Null.message = deve ser nulo javax.validation.constraints.Past.message = deve estar no passado @@ -21,22 +21,22 @@ javax.validation.constraints.Positive.message = deve ser maior que 0 javax.validation.constraints.PositiveOrZero.message = deve ser maior ou igual a 0 javax.validation.constraints.Size.message = tamanho deve estar entre {min} e {max} -org.hibernate.validator.constraints.CreditCardNumber.message = N\u00FAmero de Cart\u00E3o de Cr\u00E9dito inv\u00E1lido -org.hibernate.validator.constraints.Email.message = N\u00E3o \u00E9 um endere\u00E7o de e-mail -org.hibernate.validator.constraints.EAN.message = C\u00F3digo de barras {type} inv\u00E1lido -org.hibernate.validator.constraints.Length.message = Tamanho deve estar entre {min} e {max} -org.hibernate.validator.constraints.CodePointLength.message = Tamanho deve estar entre {min} e {max} -org.hibernate.validator.constraints.LuhnCheck.message = Digito verificador para ${validatedValue} \u00E9 inv\u00E1lido, verifica\u00E7\u00E3o M\u00F3dulo 10 de Luhn falhou -org.hibernate.validator.constraints.Mod10Check.message = Digito verificador para ${validatedValue} \u00E9 inv\u00E1lido, verifica\u00E7\u00E3o M\u00F3dulo 10 falhou -org.hibernate.validator.constraints.Mod11Check.message = Digito verificador para ${validatedValue} \u00E9 inv\u00E1lido, verifica\u00E7\u00E3o M\u00F3dulo 10 falhou -org.hibernate.validator.constraints.ModCheck.message = Digito verificador para ${validatedValue} \u00E9 inv\u00E1lido, verifica\u00E7\u00E3o ${modType} falhou -org.hibernate.validator.constraints.NotBlank.message = N\u00E3o pode estar em branco -org.hibernate.validator.constraints.NotEmpty.message = N\u00E3o pode estar vazio -org.hibernate.validator.constraints.ParametersScriptAssert.message = O script "{script}" n\u00E3o retornou verdadeiro -org.hibernate.validator.constraints.Range.message = O valor precisa estar entre {min} e {max} -org.hibernate.validator.constraints.SafeHtml.message = Pode ter conte\u00FAdo inseguro no html -org.hibernate.validator.constraints.ScriptAssert.message = Express\u00E3o de script "{script}" n\u00E3o retornou verdadeiro -org.hibernate.validator.constraints.URL.message = Deve ser uma URL v\u00E1lida +org.hibernate.validator.constraints.CreditCardNumber.message = n\u00FAmero de cart\u00E3o de cr\u00E9dito inv\u00E1lido +org.hibernate.validator.constraints.Email.message = n\u00E3o \u00E9 um endere\u00E7o de e-mail +org.hibernate.validator.constraints.EAN.message = c\u00F3digo de barras {type} inv\u00E1lido +org.hibernate.validator.constraints.Length.message = tamanho deve estar entre {min} e {max} +org.hibernate.validator.constraints.CodePointLength.message = tamanho deve estar entre {min} e {max} +org.hibernate.validator.constraints.LuhnCheck.message = digito verificador para ${validatedValue} \u00E9 inv\u00E1lido, verifica\u00E7\u00E3o M\u00F3dulo 10 de Luhn falhou +org.hibernate.validator.constraints.Mod10Check.message = digito verificador para ${validatedValue} \u00E9 inv\u00E1lido, verifica\u00E7\u00E3o M\u00F3dulo 10 falhou +org.hibernate.validator.constraints.Mod11Check.message = digito verificador para ${validatedValue} \u00E9 inv\u00E1lido, verifica\u00E7\u00E3o M\u00F3dulo 10 falhou +org.hibernate.validator.constraints.ModCheck.message = digito verificador para ${validatedValue} \u00E9 inv\u00E1lido, verifica\u00E7\u00E3o ${modType} falhou +org.hibernate.validator.constraints.NotBlank.message = n\u00E3o pode estar em branco +org.hibernate.validator.constraints.NotEmpty.message = n\u00E3o pode estar vazio +org.hibernate.validator.constraints.ParametersScriptAssert.message = o script "{script}" n\u00E3o retornou verdadeiro +org.hibernate.validator.constraints.Range.message = o valor precisa estar entre {min} e {max} +org.hibernate.validator.constraints.SafeHtml.message = pode ter conte\u00FAdo inseguro no html +org.hibernate.validator.constraints.ScriptAssert.message = express\u00E3o de script "{script}" n\u00E3o retornou verdadeiro +org.hibernate.validator.constraints.URL.message = deve ser uma URL v\u00E1lida org.hibernate.validator.constraints.br.CNPJ.message = CNPJ inv\u00E1lido org.hibernate.validator.constraints.br.CPF.message = CPF inv\u00E1lido org.hibernate.validator.constraints.br.TituloEleitoral.message = T\u00EDtulo Eleitoral inv\u00E1lido diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ru.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ru.properties index 2886acb9d3..56a4877b75 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ru.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ru.properties @@ -19,10 +19,10 @@ org.hibernate.validator.constraints.EAN.message = \u043D\u04 org.hibernate.validator.constraints.Email.message = email \u043E\u043F\u0440\u0435\u0434\u0435\u043B\u0435\u043D \u0432 \u043D\u0435\u0432\u0435\u0440\u043D\u043E\u043C \u0444\u043E\u0440\u043C\u0430\u0442\u0435 org.hibernate.validator.constraints.Length.message = \u0434\u043B\u0438\u043D\u0430 \u0434\u043E\u043B\u0436\u043D\u0430 \u0431\u044B\u0442\u044C \u043C\u0435\u0436\u0434\u0443 {min} \u0438 {max} org.hibernate.validator.constraints.CodePointLength.message = \u0434\u043B\u0438\u043D\u0430 \u0434\u043E\u043B\u0436\u043D\u0430 \u0431\u044B\u0442\u044C \u043C\u0435\u0436\u0434\u0443 {min} \u0438 {max} -org.hibernate.validator.constraints.LuhnCheck.message = \u041A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u0430\u044F \u0446\u0438\u0444\u0440\u0430 \u0434\u043B\u044F ${validatedValue} \u043D\u0435\u0432\u0435\u0440\u043D\u0430, \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043F\u043E \u0430\u043B\u0433\u043E\u0440\u0438\u0442\u043C\u0443 \u041B\u0443\u043D\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430 \u0441 \u043E\u0448\u0438\u0431\u043A\u043E\u0439 -org.hibernate.validator.constraints.Mod10Check.message = \u041A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u0430\u044F \u0446\u0438\u0444\u0440\u0430 \u0434\u043B\u044F ${validatedValue} \u043D\u0435\u0432\u0435\u0440\u043D\u0430, \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043F\u043E \u0430\u043B\u0433\u043E\u0440\u0438\u0442\u043C\u0443 Mod10 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430 \u0441 \u043E\u0448\u0438\u0431\u043A\u043E\u0439 -org.hibernate.validator.constraints.Mod11Check.message = \u041A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u0430\u044F \u0446\u0438\u0444\u0440\u0430 \u0434\u043B\u044F ${validatedValue} \u043D\u0435\u0432\u0435\u0440\u043D\u0430, \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043F\u043E \u0430\u043B\u0433\u043E\u0440\u0438\u0442\u043C\u0443 Mod11 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430 \u0441 \u043E\u0448\u0438\u0431\u043A\u043E\u0439 -org.hibernate.validator.constraints.ModCheck.message = \u041A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u0430\u044F \u0446\u0438\u0444\u0440\u0430 \u0434\u043B\u044F ${validatedValue} \u043D\u0435\u0432\u0435\u0440\u043D\u0430, \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043F\u043E ${modType} \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430 \u0441 \u043E\u0448\u0438\u0431\u043A\u043E\u0439 +org.hibernate.validator.constraints.LuhnCheck.message = \u043A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u0430\u044F \u0446\u0438\u0444\u0440\u0430 \u0434\u043B\u044F ${validatedValue} \u043D\u0435\u0432\u0435\u0440\u043D\u0430, \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043F\u043E \u0430\u043B\u0433\u043E\u0440\u0438\u0442\u043C\u0443 \u041B\u0443\u043D\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430 \u0441 \u043E\u0448\u0438\u0431\u043A\u043E\u0439 +org.hibernate.validator.constraints.Mod10Check.message = \u043A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u0430\u044F \u0446\u0438\u0444\u0440\u0430 \u0434\u043B\u044F ${validatedValue} \u043D\u0435\u0432\u0435\u0440\u043D\u0430, \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043F\u043E \u0430\u043B\u0433\u043E\u0440\u0438\u0442\u043C\u0443 Mod10 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430 \u0441 \u043E\u0448\u0438\u0431\u043A\u043E\u0439 +org.hibernate.validator.constraints.Mod11Check.message = \u043A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u0430\u044F \u0446\u0438\u0444\u0440\u0430 \u0434\u043B\u044F ${validatedValue} \u043D\u0435\u0432\u0435\u0440\u043D\u0430, \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043F\u043E \u0430\u043B\u0433\u043E\u0440\u0438\u0442\u043C\u0443 Mod11 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430 \u0441 \u043E\u0448\u0438\u0431\u043A\u043E\u0439 +org.hibernate.validator.constraints.ModCheck.message = \u043A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u0430\u044F \u0446\u0438\u0444\u0440\u0430 \u0434\u043B\u044F ${validatedValue} \u043D\u0435\u0432\u0435\u0440\u043D\u0430, \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043F\u043E ${modType} \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430 \u0441 \u043E\u0448\u0438\u0431\u043A\u043E\u0439 org.hibernate.validator.constraints.NotBlank.message = \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0443\u0441\u0442\u043E org.hibernate.validator.constraints.NotEmpty.message = \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0443\u0441\u0442\u043E org.hibernate.validator.constraints.ParametersScriptAssert.message = \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u0435 "{script}" \u043D\u0435 \u044F\u0432\u043B\u044F\u0435\u0442\u0441\u044F \u0438\u0441\u0442\u0438\u043D\u043D\u044B\u043C diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_sk.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_sk.properties index 24dc9234ea..1268340cd9 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_sk.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_sk.properties @@ -20,10 +20,10 @@ org.hibernate.validator.constraints.EAN.message = nespr\u00e org.hibernate.validator.constraints.Email.message = nespr\u00e1vny form\u00e1t emailovej adresy org.hibernate.validator.constraints.Length.message = d\u013a\u017eka mus\u00ed by\u0165 medzi {min} a {max} org.hibernate.validator.constraints.CodePointLength.message = d\u013a\u017eka mus\u00ed by\u0165 medzi {min} a {max} -org.hibernate.validator.constraints.LuhnCheck.message = Kontroln\u00e1 \u010d\u00edslica pre ${validatedValue} nie je spr\u00e1vna, kontroln\u00fd s\u00fa\u010det Luhn Modulo 10 zlyhal -org.hibernate.validator.constraints.Mod10Check.message = Kontroln\u00e1 \u010d\u00edslica pre ${validatedValue} nie je spr\u00e1vna, kontroln\u00fd s\u00fa\u010det Modulo 10 zlyhal -org.hibernate.validator.constraints.Mod11Check.message = Kontroln\u00e1 \u010d\u00edslica pre ${validatedValue} nie je spr\u00e1vna, kontroln\u00fd s\u00fa\u010det Modulo 11 zlyhal -org.hibernate.validator.constraints.ModCheck.message = Kontroln\u00e1 \u010d\u00edslica pre ${validatedValue} nie je spr\u00e1vna, kontroln\u00fd s\u00fa\u010det ${modType} zlyhal +org.hibernate.validator.constraints.LuhnCheck.message = kontroln\u00e1 \u010d\u00edslica pre ${validatedValue} nie je spr\u00e1vna, kontroln\u00fd s\u00fa\u010det Luhn Modulo 10 zlyhal +org.hibernate.validator.constraints.Mod10Check.message = kontroln\u00e1 \u010d\u00edslica pre ${validatedValue} nie je spr\u00e1vna, kontroln\u00fd s\u00fa\u010det Modulo 10 zlyhal +org.hibernate.validator.constraints.Mod11Check.message = kontroln\u00e1 \u010d\u00edslica pre ${validatedValue} nie je spr\u00e1vna, kontroln\u00fd s\u00fa\u010det Modulo 11 zlyhal +org.hibernate.validator.constraints.ModCheck.message = kontroln\u00e1 \u010d\u00edslica pre ${validatedValue} nie je spr\u00e1vna, kontroln\u00fd s\u00fa\u010det ${modType} zlyhal org.hibernate.validator.constraints.NotBlank.message = nem\u00f4\u017ee by\u0165 pr\u00e1zdne org.hibernate.validator.constraints.NotEmpty.message = nem\u00f4\u017ee by\u0165 pr\u00e1zdne org.hibernate.validator.constraints.ParametersScriptAssert.message = skriptovac\u00ed v\u00fdraz "{script}" nebol vyhodnoten\u00fd na \u00e1no diff --git a/engine/src/test/java/org/hibernate/validator/test/cfg/ProgrammaticConstraintDefinitionsTest.java b/engine/src/test/java/org/hibernate/validator/test/cfg/ProgrammaticConstraintDefinitionsTest.java index 7c56d67a25..d45c5b1579 100644 --- a/engine/src/test/java/org/hibernate/validator/test/cfg/ProgrammaticConstraintDefinitionsTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/cfg/ProgrammaticConstraintDefinitionsTest.java @@ -61,10 +61,10 @@ public void countrySpecificProgrammaticDefinition() { "invalid Brazilian corporate taxpayer registry number (CNPJ)" ); - doProgrammaticTest( REGON.class, new REGONDef(), "49905531368510", "49905531368512", "Invalid Polish Taxpayer Identification Number (REGON)" ); - doProgrammaticTest( REGON.class, new REGONDef(), "858336997", "691657185", "Invalid Polish Taxpayer Identification Number (REGON)" ); - doProgrammaticTest( PESEL.class, new PESELDef(), "12252918020", "44051401358", "Invalid Polish National Identification Number (PESEL)" ); - doProgrammaticTest( NIP.class, new NIPDef(), "1786052059", "2596048505", "Invalid VAT Identification Number (NIP)" ); + doProgrammaticTest( REGON.class, new REGONDef(), "49905531368510", "49905531368512", "invalid Polish Taxpayer Identification Number (REGON)" ); + doProgrammaticTest( REGON.class, new REGONDef(), "858336997", "691657185", "invalid Polish Taxpayer Identification Number (REGON)" ); + doProgrammaticTest( PESEL.class, new PESELDef(), "12252918020", "44051401358", "invalid Polish National Identification Number (PESEL)" ); + doProgrammaticTest( NIP.class, new NIPDef(), "1786052059", "2596048505", "invalid VAT Identification Number (NIP)" ); } From c5fdd1919703d0eea4996778c19ac577dae4ebab Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Tue, 24 Apr 2018 15:47:13 +0200 Subject: [PATCH 024/393] HV-1526 Move creation of ConstraintValidatorContextImpl into ValidationContext - As we want to encapsulate the ValidationContext specifics and for example not expose the getParameterNames() method, ConstraintValidatorContextImpl can be created inside the context and returned from it. - This also allows to remove unnecessarily exposed getters of clock provider and constraint validator payload --- .../internal/engine/ValidationContext.java | 20 +++++++++++-------- .../ComposingConstraintTree.java | 20 +++++++------------ .../SimpleConstraintTree.java | 8 ++------ 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java index bde191ef06..919f0014c7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java @@ -32,6 +32,7 @@ import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; import org.hibernate.validator.internal.engine.ValidatorFactoryImpl.ValidatorFactoryScopedContext; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext; import org.hibernate.validator.internal.engine.path.PathImpl; @@ -39,6 +40,7 @@ import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.facets.Validatable; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.logging.Log; @@ -258,14 +260,6 @@ public List getParameterNames() { return validatorScopedContext.getParameterNameProvider().getParameterNames( executable ); } - public ClockProvider getClockProvider() { - return validatorScopedContext.getClockProvider(); - } - - public Object getConstraintValidatorPayload() { - return validatorScopedContext.getConstraintValidatorPayload(); - } - public HibernateConstraintValidatorInitializationContext getConstraintValidatorInitializationContext() { return constraintValidatorInitializationContext; } @@ -402,6 +396,16 @@ public void setValidatedProperty(String validatedProperty) { this.validatedProperty = validatedProperty; } + public ConstraintValidatorContextImpl createConstraintValidatorContextFor(ConstraintDescriptorImpl constraintDescriptor, PathImpl path) { + return new ConstraintValidatorContextImpl( + getParameterNames(), + validatorScopedContext.getClockProvider(), + path, + constraintDescriptor, + validatorScopedContext.getConstraintValidatorPayload() + ); + } + @Override public String toString() { final StringBuilder sb = new StringBuilder(); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java index 46d97114b4..4c705771a4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java @@ -88,12 +88,8 @@ protected void validateConstraints(ValidationContext validationContext, ConstraintValidator validator = getInitializedConstraintValidator( validationContext, valueContext ); // create a constraint validator context - ConstraintValidatorContextImpl constraintValidatorContext = new ConstraintValidatorContextImpl( - validationContext.getParameterNames(), - validationContext.getClockProvider(), - valueContext.getPropertyPath(), - descriptor, - validationContext.getConstraintValidatorPayload() + ConstraintValidatorContextImpl constraintValidatorContext = validationContext.createConstraintValidatorContextFor( + descriptor, valueContext.getPropertyPath() ); // validate @@ -170,13 +166,11 @@ private void prepareFinalConstraintViolations(ValidationContext validatio // If not we create a violation // using the error message in the annotation declaration at top level. if ( !localConstraintValidatorContext.isPresent() ) { - violatedConstraintValidatorContexts.add( new ConstraintValidatorContextImpl( - validationContext.getParameterNames(), - validationContext.getClockProvider(), - valueContext.getPropertyPath(), - descriptor, - validationContext.getConstraintValidatorPayload() - ) ); + violatedConstraintValidatorContexts.add( + validationContext.createConstraintValidatorContextFor( + descriptor, valueContext.getPropertyPath() + ) + ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java index 05b17b85cd..dbf11412ac 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java @@ -54,12 +54,8 @@ protected void validateConstraints(ValidationContext validationContext, ConstraintValidator validator = getInitializedConstraintValidator( validationContext, valueContext ); // create a constraint validator context - ConstraintValidatorContextImpl constraintValidatorContext = new ConstraintValidatorContextImpl( - validationContext.getParameterNames(), - validationContext.getClockProvider(), - valueContext.getPropertyPath(), - descriptor, - validationContext.getConstraintValidatorPayload() + ConstraintValidatorContextImpl constraintValidatorContext = validationContext.createConstraintValidatorContextFor( + descriptor, valueContext.getPropertyPath() ); // validate From 6d56faaaeb2d8da427655f039b5ea567390e9129 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Tue, 24 Apr 2018 17:31:12 +0200 Subject: [PATCH 025/393] HV-1526 Make a distinction between cross-parameter and other ConstraintValidatorContext implementations Thus we don't have the method parameter names in the ConstraintValidatorContext if it does not make sense, e.g. for class-level or field validation. --- ...ssParameterConstraintValidatorContext.java | 28 +++++++ .../hv/ParameterScriptAssertValidator.java | 20 +++-- .../internal/engine/ValidationContext.java | 15 +++- .../constraintvalidation/ConstraintTree.java | 2 +- .../ConstraintValidatorContextImpl.java | 50 +++++------- ...rameterConstraintValidatorContextImpl.java | 76 +++++++++++++++++++ .../ConstraintValidatorContextImplTest.java | 2 +- .../validator/testutils/ValidatorUtil.java | 2 +- 8 files changed, 151 insertions(+), 44 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/constraintvalidation/HibernateCrossParameterConstraintValidatorContext.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/CrossParameterConstraintValidatorContextImpl.java diff --git a/engine/src/main/java/org/hibernate/validator/constraintvalidation/HibernateCrossParameterConstraintValidatorContext.java b/engine/src/main/java/org/hibernate/validator/constraintvalidation/HibernateCrossParameterConstraintValidatorContext.java new file mode 100644 index 0000000000..b7ad51c76b --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/constraintvalidation/HibernateCrossParameterConstraintValidatorContext.java @@ -0,0 +1,28 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.constraintvalidation; + +import java.util.List; + +import javax.validation.ConstraintValidatorContext; + +import org.hibernate.validator.Incubating; + +/** + * A custom {@link ConstraintValidatorContext} which provides additional functionality for cross parameter validation contexts. + * + * @author Marko Bekhta + * @since 6.1.0 + */ +@Incubating +public interface HibernateCrossParameterConstraintValidatorContext extends HibernateConstraintValidatorContext { + + /** + * @return the list of the parameter names of the validated method. + */ + List getMethodParameterNames(); +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/ParameterScriptAssertValidator.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/ParameterScriptAssertValidator.java index 8bcf798283..8cfcf4dab7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/ParameterScriptAssertValidator.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/ParameterScriptAssertValidator.java @@ -9,6 +9,7 @@ import static org.hibernate.validator.internal.util.CollectionHelper.newHashMap; import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -18,9 +19,8 @@ import javax.validation.metadata.ConstraintDescriptor; import org.hibernate.validator.constraints.ParameterScriptAssert; -import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorContext; import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; -import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl; +import org.hibernate.validator.constraintvalidation.HibernateCrossParameterConstraintValidatorContext; import org.hibernate.validator.internal.util.Contracts; /** @@ -42,14 +42,18 @@ public void initialize(ConstraintDescriptor constraintDes @Override public boolean isValid(Object[] arguments, ConstraintValidatorContext constraintValidatorContext) { - if ( constraintValidatorContext instanceof HibernateConstraintValidatorContext ) { - constraintValidatorContext.unwrap( HibernateConstraintValidatorContext.class ).addMessageParameter( "script", escapedScript ); - } + Map bindings; + if ( constraintValidatorContext instanceof HibernateCrossParameterConstraintValidatorContext ) { + HibernateCrossParameterConstraintValidatorContext crossParameterConstraintValidatorContext = constraintValidatorContext + .unwrap( HibernateCrossParameterConstraintValidatorContext.class ); - List parameterNames = ( (ConstraintValidatorContextImpl) constraintValidatorContext ) - .getMethodParameterNames(); + crossParameterConstraintValidatorContext.addMessageParameter( "script", escapedScript ); - Map bindings = getBindings( arguments, parameterNames ); + bindings = getBindings( arguments, crossParameterConstraintValidatorContext.getMethodParameterNames() ); + } + else { + bindings = Collections.emptyMap(); + } return scriptAssertContext.evaluateScriptAssertExpression( bindings ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java index 919f0014c7..1ff5e8a650 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java @@ -35,12 +35,14 @@ import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext; +import org.hibernate.validator.internal.engine.constraintvalidation.CrossParameterConstraintValidatorContextImpl; import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; +import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; import org.hibernate.validator.internal.metadata.facets.Validatable; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.logging.Log; @@ -252,7 +254,7 @@ public ConstraintValidatorManager getConstraintValidatorManager() { * @return The current executable's parameter names,if this context was * created for parameter validation, {@code null} otherwise. */ - public List getParameterNames() { + private List getParameterNames() { if ( !ValidationOperation.PARAMETER_VALIDATION.equals( validationOperation ) ) { return null; } @@ -397,8 +399,17 @@ public void setValidatedProperty(String validatedProperty) { } public ConstraintValidatorContextImpl createConstraintValidatorContextFor(ConstraintDescriptorImpl constraintDescriptor, PathImpl path) { + if ( ConstraintType.CROSS_PARAMETER.equals( constraintDescriptor.getConstraintType() ) ) { + return new CrossParameterConstraintValidatorContextImpl( + getParameterNames(), + validatorScopedContext.getClockProvider(), + path, + constraintDescriptor, + validatorScopedContext.getConstraintValidatorPayload() + ); + } + return new ConstraintValidatorContextImpl( - getParameterNames(), validatorScopedContext.getClockProvider(), path, constraintDescriptor, diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java index d9130ac1f3..241cb5db8b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java @@ -75,7 +75,7 @@ public final boolean validateConstraints(ValidationContext validationCont for ( ConstraintValidatorContextImpl constraintValidatorContext : violatedConstraintValidatorContexts ) { for ( ConstraintViolationCreationContext constraintViolationCreationContext : constraintValidatorContext.getConstraintViolationCreationContexts() ) { validationContext.addConstraintFailure( - validationContext.createConstraintViolation( valueContext, constraintViolationCreationContext, ( (ConstraintValidatorContextImpl) constraintValidatorContext ).getConstraintDescriptor() ) + validationContext.createConstraintViolation( valueContext, constraintViolationCreationContext, constraintValidatorContext.getConstraintDescriptor() ) ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java index ff5c9c14d8..a62390f551 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java @@ -45,7 +45,6 @@ public class ConstraintValidatorContextImpl implements HibernateConstraintValida private Map messageParameters; private Map expressionVariables; - private final List methodParameterNames; private final ClockProvider clockProvider; private final PathImpl basePath; private final ConstraintDescriptor constraintDescriptor; @@ -54,9 +53,11 @@ public class ConstraintValidatorContextImpl implements HibernateConstraintValida private Object dynamicPayload; private final Object constraintValidatorPayload; - public ConstraintValidatorContextImpl(List methodParameterNames, ClockProvider clockProvider, - PathImpl propertyPath, ConstraintDescriptor constraintDescriptor, Object constraintValidatorPayload) { - this.methodParameterNames = methodParameterNames; + public ConstraintValidatorContextImpl( + ClockProvider clockProvider, + PathImpl propertyPath, + ConstraintDescriptor constraintDescriptor, + Object constraintValidatorPayload) { this.clockProvider = clockProvider; this.basePath = propertyPath; this.constraintDescriptor = constraintDescriptor; @@ -74,11 +75,10 @@ public final String getDefaultConstraintMessageTemplate() { } @Override - public final ConstraintViolationBuilder buildConstraintViolationWithTemplate(String messageTemplate) { + public ConstraintViolationBuilder buildConstraintViolationWithTemplate(String messageTemplate) { return new ConstraintViolationBuilderImpl( - methodParameterNames, messageTemplate, - PathImpl.createCopy( basePath ) + getCopyOfBasePath() ); } @@ -161,6 +161,10 @@ public final List getConstraintViolationCrea return CollectionHelper.toImmutableList( returnedConstraintViolationCreationContexts ); } + protected final PathImpl getCopyOfBasePath() { + return PathImpl.createCopy( basePath ); + } + private ConstraintViolationCreationContext getDefaultConstraintViolationCreationContext() { return new ConstraintViolationCreationContext( getDefaultConstraintMessageTemplate(), @@ -171,10 +175,6 @@ private ConstraintViolationCreationContext getDefaultConstraintViolationCreation ); } - public List getMethodParameterNames() { - return methodParameterNames; - } - private abstract class NodeBuilderBase { protected final String messageTemplate; @@ -202,13 +202,10 @@ public ConstraintValidatorContext addConstraintViolation() { } } - private class ConstraintViolationBuilderImpl extends NodeBuilderBase implements ConstraintViolationBuilder { - - private final List methodParameterNames; + protected class ConstraintViolationBuilderImpl extends NodeBuilderBase implements ConstraintViolationBuilder { - private ConstraintViolationBuilderImpl(List methodParameterNames, String template, PathImpl path) { + protected ConstraintViolationBuilderImpl(String template, PathImpl path) { super( template, path ); - this.methodParameterNames = methodParameterNames; } @Override @@ -233,14 +230,7 @@ public LeafNodeBuilderCustomizableContext addBeanNode() { @Override public NodeBuilderDefinedContext addParameterNode(int index) { - if ( propertyPath.getLeafNode().getKind() != ElementKind.CROSS_PARAMETER ) { - throw LOG.getParameterNodeAddedForNonCrossParameterConstraintException( propertyPath ); - } - - dropLeafNodeIfRequired(); - propertyPath.addParameterNode( methodParameterNames.get( index ), index ); - - return new NodeBuilder( messageTemplate, propertyPath ); + throw LOG.getParameterNodeAddedForNonCrossParameterConstraintException( propertyPath ); } @Override @@ -251,22 +241,20 @@ public ContainerElementNodeBuilderCustomizableContext addContainerElementNode(St } /** - * In case nodes are added from within a class-level or cross-parameter - * constraint, the node representing the constraint element will be - * dropped. inIterable(), getKey() etc. + * In case nodes are added from within a class-level constraint, the node representing + * the constraint element will be dropped. inIterable(), getKey() etc. */ private void dropLeafNodeIfRequired() { - if ( propertyPath.getLeafNode().getKind() == ElementKind.BEAN || propertyPath.getLeafNode() - .getKind() == ElementKind.CROSS_PARAMETER ) { + if ( propertyPath.getLeafNode().getKind() == ElementKind.BEAN ) { propertyPath = propertyPath.getPathWithoutLeafNode(); } } } - private class NodeBuilder extends NodeBuilderBase + protected class NodeBuilder extends NodeBuilderBase implements NodeBuilderDefinedContext, LeafNodeBuilderDefinedContext, ContainerElementNodeBuilderDefinedContext { - private NodeBuilder(String template, PathImpl path) { + protected NodeBuilder(String template, PathImpl path) { super( template, path ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/CrossParameterConstraintValidatorContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/CrossParameterConstraintValidatorContextImpl.java new file mode 100644 index 0000000000..fe84ec24b2 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/CrossParameterConstraintValidatorContextImpl.java @@ -0,0 +1,76 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.constraintvalidation; + +import java.util.List; + +import javax.validation.ClockProvider; +import javax.validation.ElementKind; +import javax.validation.metadata.ConstraintDescriptor; + +import org.hibernate.validator.constraintvalidation.HibernateCrossParameterConstraintValidatorContext; +import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.util.Contracts; + +/** + * @author Marko Bekhta + */ +public class CrossParameterConstraintValidatorContextImpl extends ConstraintValidatorContextImpl implements HibernateCrossParameterConstraintValidatorContext { + + private final List methodParameterNames; + + public CrossParameterConstraintValidatorContextImpl(List methodParameterNames, ClockProvider clockProvider, PathImpl propertyPath, ConstraintDescriptor constraintDescriptor, Object constraintValidatorPayload) { + super( clockProvider, propertyPath, constraintDescriptor, constraintValidatorPayload ); + Contracts.assertTrue( propertyPath.getLeafNode().getKind() == ElementKind.CROSS_PARAMETER, "Context can only be used for corss parameter validation" ); + this.methodParameterNames = methodParameterNames; + } + + @Override + public final ConstraintViolationBuilder buildConstraintViolationWithTemplate(String messageTemplate) { + return new CrossParameterConstraintViolationBuilderImpl( + methodParameterNames, + messageTemplate, + getCopyOfBasePath() + ); + } + + @Override + public List getMethodParameterNames() { + return methodParameterNames; + } + + @Override + public T unwrap(Class type) { + //allow unwrapping into public super types + if ( type.isAssignableFrom( HibernateCrossParameterConstraintValidatorContext.class ) ) { + return type.cast( this ); + } + return super.unwrap( type ); + } + + private class CrossParameterConstraintViolationBuilderImpl extends ConstraintViolationBuilderImpl { + + private final List methodParameterNames; + + private CrossParameterConstraintViolationBuilderImpl(List methodParameterNames, String template, PathImpl path) { + super( template, path ); + this.methodParameterNames = methodParameterNames; + } + + @Override + public NodeBuilderDefinedContext addParameterNode(int index) { + dropLeafNode(); + propertyPath.addParameterNode( methodParameterNames.get( index ), index ); + + return new NodeBuilder( messageTemplate, propertyPath ); + } + + private void dropLeafNode() { + propertyPath = propertyPath.getPathWithoutLeafNode(); + } + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextImplTest.java b/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextImplTest.java index 74031960a0..436536db8f 100644 --- a/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextImplTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextImplTest.java @@ -226,7 +226,7 @@ private ConstraintValidatorContextImpl createEmptyConstraintValidatorContextImpl PathImpl path = PathImpl.createRootPath(); path.addBeanNode(); - ConstraintValidatorContextImpl context = new ConstraintValidatorContextImpl( null, null, path, null, null ); + ConstraintValidatorContextImpl context = new ConstraintValidatorContextImpl( null, path, null, null ); context.disableDefaultConstraintViolation(); return context; } diff --git a/engine/src/test/java/org/hibernate/validator/testutils/ValidatorUtil.java b/engine/src/test/java/org/hibernate/validator/testutils/ValidatorUtil.java index 529e28ae75..061272b05f 100644 --- a/engine/src/test/java/org/hibernate/validator/testutils/ValidatorUtil.java +++ b/engine/src/test/java/org/hibernate/validator/testutils/ValidatorUtil.java @@ -235,6 +235,6 @@ public static T getValidatingProxy(I implementor, Validator exe } public static HibernateConstraintValidatorContext getConstraintValidatorContext() { - return new ConstraintValidatorContextImpl( null, DefaultClockProvider.INSTANCE, null, null, null ); + return new ConstraintValidatorContextImpl( DefaultClockProvider.INSTANCE, null, null, null ); } } From c00419569367f5363704ec62d0b61ec6585cca64 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Tue, 24 Apr 2018 22:06:27 +0200 Subject: [PATCH 026/393] HV-1526 Combine creation and addition of constraint violations in ValidationContext As now we don't create violations unless we need them, these operations can be combined. Another benefit is that ValidationContext exposes less public methods. --- .../internal/engine/ValidationContext.java | 18 +++++++++--------- .../constraintvalidation/ConstraintTree.java | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java index 1ff5e8a650..ebce881fbe 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java @@ -294,15 +294,11 @@ public void markCurrentBeanAsProcessed(ValueContext valueContext) { markCurrentBeanAsProcessedForCurrentPath( valueContext.getCurrentBean(), valueContext.getPropertyPath() ); } - public void addConstraintFailure(ConstraintViolation failingConstraintViolation) { - this.failingConstraintViolations.add( failingConstraintViolation ); - } - public Set> getFailingConstraints() { return failingConstraintViolations; } - public ConstraintViolation createConstraintViolation( + public void addConstraintFailure( ValueContext localContext, ConstraintViolationCreationContext constraintViolationCreationContext, ConstraintDescriptor descriptor @@ -318,10 +314,10 @@ public ConstraintViolation createConstraintViolation( // at this point we make a copy of the path to avoid side effects Path path = PathImpl.createCopy( constraintViolationCreationContext.getPath() ); Object dynamicPayload = constraintViolationCreationContext.getDynamicPayload(); - + ConstraintViolation violation; switch ( validationOperation ) { case PARAMETER_VALIDATION: - return ConstraintViolationImpl.forParameterValidation( + violation = ConstraintViolationImpl.forParameterValidation( messageTemplate, constraintViolationCreationContext.getMessageParameters(), constraintViolationCreationContext.getExpressionVariables(), @@ -336,8 +332,9 @@ public ConstraintViolation createConstraintViolation( executableParameters, dynamicPayload ); + break; case RETURN_VALUE_VALIDATION: - return ConstraintViolationImpl.forReturnValueValidation( + violation = ConstraintViolationImpl.forReturnValueValidation( messageTemplate, constraintViolationCreationContext.getMessageParameters(), constraintViolationCreationContext.getExpressionVariables(), @@ -352,8 +349,9 @@ public ConstraintViolation createConstraintViolation( executableReturnValue, dynamicPayload ); + break; default: - return ConstraintViolationImpl.forBeanValidation( + violation = ConstraintViolationImpl.forBeanValidation( messageTemplate, constraintViolationCreationContext.getMessageParameters(), constraintViolationCreationContext.getExpressionVariables(), @@ -368,6 +366,8 @@ public ConstraintViolation createConstraintViolation( dynamicPayload ); } + + this.failingConstraintViolations.add( violation ); } public boolean hasMetaConstraintBeenProcessed(Object bean, Path path, MetaConstraint metaConstraint) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java index 241cb5db8b..1481c1af9a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java @@ -75,7 +75,7 @@ public final boolean validateConstraints(ValidationContext validationCont for ( ConstraintValidatorContextImpl constraintValidatorContext : violatedConstraintValidatorContexts ) { for ( ConstraintViolationCreationContext constraintViolationCreationContext : constraintValidatorContext.getConstraintViolationCreationContexts() ) { validationContext.addConstraintFailure( - validationContext.createConstraintViolation( valueContext, constraintViolationCreationContext, constraintValidatorContext.getConstraintDescriptor() ) + valueContext, constraintViolationCreationContext, constraintValidatorContext.getConstraintDescriptor() ); } } From 7af799ee3ca3750bcf2b6ff5885e585571c353bf Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Tue, 24 Apr 2018 22:22:37 +0200 Subject: [PATCH 027/393] HV-1526 Add different implementations of ValidationContext - add implementations for bean, property/value, executable parameter and executable return value contexts - extract builder for validation contexts to its own class --- .../internal/engine/ValidationContext.java | 868 ------------------ .../internal/engine/ValidatorFactoryImpl.java | 2 +- .../internal/engine/ValidatorImpl.java | 76 +- .../ComposingConstraintTree.java | 2 +- .../constraintvalidation/ConstraintTree.java | 2 +- .../SimpleConstraintTree.java | 2 +- .../AbstractValidationContext.java | 458 +++++++++ .../BeanValidationContext.java | 78 ++ .../ExecutableValidationContext.java | 25 + .../ParameterExecutableValidationContext.java | 153 +++ .../PropertyValidationContext.java | 115 +++ ...eturnValueExecutableValidationContext.java | 121 +++ .../validationcontext/ValidationContext.java | 77 ++ .../ValidationContextBuilder.java | 139 +++ .../ValidatorScopedContext.java | 110 +++ .../validationcontext/package-info.java | 10 + .../metadata/core/MetaConstraint.java | 2 +- 17 files changed, 1320 insertions(+), 920 deletions(-) delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BeanValidationContext.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ExecutableValidationContext.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ParameterExecutableValidationContext.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ReturnValueExecutableValidationContext.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContext.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidatorScopedContext.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/package-info.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java deleted file mode 100644 index ebce881fbe..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidationContext.java +++ /dev/null @@ -1,868 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.engine; - -import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; - -import java.lang.invoke.MethodHandles; -import java.lang.reflect.Executable; -import java.time.Duration; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; - -import javax.validation.ClockProvider; -import javax.validation.ConstraintValidatorFactory; -import javax.validation.ConstraintViolation; -import javax.validation.MessageInterpolator; -import javax.validation.ParameterNameProvider; -import javax.validation.Path; -import javax.validation.TraversableResolver; -import javax.validation.ValidationException; -import javax.validation.Validator; -import javax.validation.metadata.ConstraintDescriptor; - -import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; -import org.hibernate.validator.internal.engine.ValidatorFactoryImpl.ValidatorFactoryScopedContext; -import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl; -import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; -import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext; -import org.hibernate.validator.internal.engine.constraintvalidation.CrossParameterConstraintValidatorContextImpl; -import org.hibernate.validator.internal.engine.path.PathImpl; -import org.hibernate.validator.internal.metadata.BeanMetaDataManager; -import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; -import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; -import org.hibernate.validator.internal.metadata.core.MetaConstraint; -import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; -import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; -import org.hibernate.validator.internal.metadata.facets.Validatable; -import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; -import org.hibernate.validator.internal.util.logging.Log; -import org.hibernate.validator.internal.util.logging.LoggerFactory; -import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; - -/** - * Context object keeping track of all required data for a validation call. - * - * We use this object to collect all failing constraints, but also to have access to resources like - * constraint validator factory, message interpolator, traversable resolver, etc. - * - * @author Hardy Ferentschik - * @author Emmanuel Bernard - * @author Gunnar Morling - * @author Guillaume Smet - */ -public class ValidationContext { - - private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - - /** - * The current validation operation (e.g. bean validation, parameter validation). - */ - private final ValidationOperation validationOperation; - - /** - * Caches and manages life cycle of constraint validator instances. - */ - private final ConstraintValidatorManager constraintValidatorManager; - - /** - * The root bean of the validation. - */ - private final T rootBean; - - /** - * The root bean class of the validation. - */ - private final Class rootBeanClass; - - /** - * The metadata of the root bean. - */ - private final BeanMetaData rootBeanMetaData; - - /** - * The method of the current validation call in case of executable validation. - */ - private final Executable executable; - - /** - * The validated parameters in case of executable parameter validation. - */ - private final Object[] executableParameters; - - /** - * The validated return value in case of executable return value validation. - */ - private final Object executableReturnValue; - - /** - * The metadata of the Executable. Will be non empty if we are in the case of method validation and the method is constrained. - */ - private final Optional executableMetaData; - - /** - * The set of already processed meta constraints per bean - path ({@link BeanPathMetaConstraintProcessedUnit}). - */ - private final Set processedPathUnits; - - /** - * The set of already processed groups per bean ({@link BeanGroupProcessedUnit}). - */ - private final Set processedGroupUnits; - - /** - * Maps an object to a list of paths in which it has been validated. The objects are the bean instances. - */ - private final Map> processedPathsPerBean; - - /** - * Contains all failing constraints so far. - */ - private final Set> failingConstraintViolations; - - /** - * The constraint factory which should be used in this context. - */ - private final ConstraintValidatorFactory constraintValidatorFactory; - - /** - * Context containing all {@link Validator} level helpers and configuration properties. - */ - private final ValidatorScopedContext validatorScopedContext; - - /** - * Allows a JPA provider to decide whether a property should be validated. - */ - private final TraversableResolver traversableResolver; - - /** - * The constraint validator initialization context. - */ - private final HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext; - - /** - * Indicates if the tracking of already validated bean should be disabled. - */ - private final boolean disableAlreadyValidatedBeanTracking; - - /** - * The name of the validated (leaf) property in case of a validateProperty()/validateValue() call. - */ - private String validatedProperty; - - private ValidationContext(ValidationOperation validationOperation, - ConstraintValidatorManager constraintValidatorManager, - ConstraintValidatorFactory constraintValidatorFactory, - ValidatorScopedContext validatorScopedContext, - TraversableResolver traversableResolver, - HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext, - T rootBean, - Class rootBeanClass, - BeanMetaData rootBeanMetaData, - Executable executable, - Object[] executableParameters, - Object executableReturnValue, - Optional executableMetaData) { - this.validationOperation = validationOperation; - - this.constraintValidatorManager = constraintValidatorManager; - this.validatorScopedContext = validatorScopedContext; - this.constraintValidatorFactory = constraintValidatorFactory; - this.traversableResolver = traversableResolver; - this.constraintValidatorInitializationContext = constraintValidatorInitializationContext; - - this.rootBean = rootBean; - this.rootBeanClass = rootBeanClass; - this.rootBeanMetaData = rootBeanMetaData; - this.executable = executable; - this.executableParameters = executableParameters; - this.executableReturnValue = executableReturnValue; - - this.processedGroupUnits = new HashSet<>(); - this.processedPathUnits = new HashSet<>(); - this.processedPathsPerBean = new IdentityHashMap<>(); - this.failingConstraintViolations = newHashSet(); - - this.executableMetaData = executableMetaData; - - this.disableAlreadyValidatedBeanTracking = buildDisableAlreadyValidatedBeanTracking( validationOperation, rootBeanMetaData, executableMetaData ); - } - - public static ValidationContextBuilder getValidationContextBuilder( - BeanMetaDataManager beanMetaDataManager, - ConstraintValidatorManager constraintValidatorManager, - ConstraintValidatorFactory constraintValidatorFactory, - ValidatorScopedContext validatorScopedContext, - TraversableResolver traversableResolver, - HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext) { - - return new ValidationContextBuilder( - beanMetaDataManager, - constraintValidatorManager, - constraintValidatorFactory, - validatorScopedContext, - traversableResolver, - constraintValidatorInitializationContext - ); - } - - public T getRootBean() { - return rootBean; - } - - public Class getRootBeanClass() { - return rootBeanClass; - } - - public BeanMetaData getRootBeanMetaData() { - return rootBeanMetaData; - } - - public Executable getExecutable() { - return executable; - } - - public Optional getExecutableMetaData() { - return executableMetaData; - } - - public TraversableResolver getTraversableResolver() { - return traversableResolver; - } - - public boolean isFailFastModeEnabled() { - return validatorScopedContext.isFailFast(); - } - - public ConstraintValidatorManager getConstraintValidatorManager() { - return constraintValidatorManager; - } - - /** - * Returns a list with the current executable's parameter names as retrieved - * from the current {@link ParameterNameProvider}. - * - * @return The current executable's parameter names,if this context was - * created for parameter validation, {@code null} otherwise. - */ - private List getParameterNames() { - if ( !ValidationOperation.PARAMETER_VALIDATION.equals( validationOperation ) ) { - return null; - } - - return validatorScopedContext.getParameterNameProvider().getParameterNames( executable ); - } - - public HibernateConstraintValidatorInitializationContext getConstraintValidatorInitializationContext() { - return constraintValidatorInitializationContext; - } - - public ConstraintValidatorFactory getConstraintValidatorFactory() { - return constraintValidatorFactory; - } - - public boolean isBeanAlreadyValidated(Object value, Class group, PathImpl path) { - if ( disableAlreadyValidatedBeanTracking ) { - return false; - } - - boolean alreadyValidated; - alreadyValidated = isAlreadyValidatedForCurrentGroup( value, group ); - - if ( alreadyValidated ) { - alreadyValidated = isAlreadyValidatedForPath( value, path ); - } - - return alreadyValidated; - } - - public void markCurrentBeanAsProcessed(ValueContext valueContext) { - if ( disableAlreadyValidatedBeanTracking ) { - return; - } - - markCurrentBeanAsProcessedForCurrentGroup( valueContext.getCurrentBean(), valueContext.getCurrentGroup() ); - markCurrentBeanAsProcessedForCurrentPath( valueContext.getCurrentBean(), valueContext.getPropertyPath() ); - } - - public Set> getFailingConstraints() { - return failingConstraintViolations; - } - - public void addConstraintFailure( - ValueContext localContext, - ConstraintViolationCreationContext constraintViolationCreationContext, - ConstraintDescriptor descriptor - ) { - String messageTemplate = constraintViolationCreationContext.getMessage(); - String interpolatedMessage = interpolate( - messageTemplate, - localContext.getCurrentValidatedValue(), - descriptor, - constraintViolationCreationContext.getMessageParameters(), - constraintViolationCreationContext.getExpressionVariables() - ); - // at this point we make a copy of the path to avoid side effects - Path path = PathImpl.createCopy( constraintViolationCreationContext.getPath() ); - Object dynamicPayload = constraintViolationCreationContext.getDynamicPayload(); - ConstraintViolation violation; - switch ( validationOperation ) { - case PARAMETER_VALIDATION: - violation = ConstraintViolationImpl.forParameterValidation( - messageTemplate, - constraintViolationCreationContext.getMessageParameters(), - constraintViolationCreationContext.getExpressionVariables(), - interpolatedMessage, - getRootBeanClass(), - getRootBean(), - localContext.getCurrentBean(), - localContext.getCurrentValidatedValue(), - path, - descriptor, - localContext.getElementType(), - executableParameters, - dynamicPayload - ); - break; - case RETURN_VALUE_VALIDATION: - violation = ConstraintViolationImpl.forReturnValueValidation( - messageTemplate, - constraintViolationCreationContext.getMessageParameters(), - constraintViolationCreationContext.getExpressionVariables(), - interpolatedMessage, - getRootBeanClass(), - getRootBean(), - localContext.getCurrentBean(), - localContext.getCurrentValidatedValue(), - path, - descriptor, - localContext.getElementType(), - executableReturnValue, - dynamicPayload - ); - break; - default: - violation = ConstraintViolationImpl.forBeanValidation( - messageTemplate, - constraintViolationCreationContext.getMessageParameters(), - constraintViolationCreationContext.getExpressionVariables(), - interpolatedMessage, - getRootBeanClass(), - getRootBean(), - localContext.getCurrentBean(), - localContext.getCurrentValidatedValue(), - path, - descriptor, - localContext.getElementType(), - dynamicPayload - ); - } - - this.failingConstraintViolations.add( violation ); - } - - public boolean hasMetaConstraintBeenProcessed(Object bean, Path path, MetaConstraint metaConstraint) { - // this is only useful if the constraint is defined for more than 1 group as in the case it's only - // defined for one group, there is no chance it's going to be called twice. - if ( metaConstraint.isDefinedForOneGroupOnly() ) { - return false; - } - - return processedPathUnits.contains( new BeanPathMetaConstraintProcessedUnit( bean, path, metaConstraint ) ); - } - - public void markConstraintProcessed(Object bean, Path path, MetaConstraint metaConstraint) { - // this is only useful if the constraint is defined for more than 1 group as in the case it's only - // defined for one group, there is no chance it's going to be called twice. - if ( metaConstraint.isDefinedForOneGroupOnly() ) { - return; - } - - processedPathUnits.add( new BeanPathMetaConstraintProcessedUnit( bean, path, metaConstraint ) ); - } - - public String getValidatedProperty() { - return validatedProperty; - } - - public void setValidatedProperty(String validatedProperty) { - this.validatedProperty = validatedProperty; - } - - public ConstraintValidatorContextImpl createConstraintValidatorContextFor(ConstraintDescriptorImpl constraintDescriptor, PathImpl path) { - if ( ConstraintType.CROSS_PARAMETER.equals( constraintDescriptor.getConstraintType() ) ) { - return new CrossParameterConstraintValidatorContextImpl( - getParameterNames(), - validatorScopedContext.getClockProvider(), - path, - constraintDescriptor, - validatorScopedContext.getConstraintValidatorPayload() - ); - } - - return new ConstraintValidatorContextImpl( - validatorScopedContext.getClockProvider(), - path, - constraintDescriptor, - validatorScopedContext.getConstraintValidatorPayload() - ); - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append( "ValidationContext" ); - sb.append( "{rootBean=" ).append( rootBean ); - sb.append( '}' ); - return sb.toString(); - } - - private static boolean buildDisableAlreadyValidatedBeanTracking(ValidationOperation validationOperation, BeanMetaData rootBeanMetaData, - Optional executableMetaData) { - Validatable validatable; - switch ( validationOperation ) { - case BEAN_VALIDATION: - case PROPERTY_VALIDATION: - case VALUE_VALIDATION: - // note that in the case of property and value validation, we are considering the root bean, whereas we - // could consider the bean of the property or the value. We don't really have the info here though so it - // will do for now. - validatable = rootBeanMetaData; - break; - case PARAMETER_VALIDATION: - if ( !executableMetaData.isPresent() ) { - // the method is unconstrained so there's no need to worry about the tracking - return false; - } - validatable = executableMetaData.get().getValidatableParametersMetaData(); - break; - case RETURN_VALUE_VALIDATION: - if ( !executableMetaData.isPresent() ) { - // the method is unconstrained so there's no need to worry about the tracking - return false; - } - validatable = executableMetaData.get().getReturnValueMetaData(); - break; - default: - return false; - } - - return !validatable.hasCascadables(); - } - - private String interpolate(String messageTemplate, - Object validatedValue, - ConstraintDescriptor descriptor, - Map messageParameters, - Map expressionVariables) { - MessageInterpolatorContext context = new MessageInterpolatorContext( - descriptor, - validatedValue, - getRootBeanClass(), - messageParameters, - expressionVariables - ); - - try { - return validatorScopedContext.getMessageInterpolator().interpolate( - messageTemplate, - context - ); - } - catch (ValidationException ve) { - throw ve; - } - catch (Exception e) { - throw LOG.getExceptionOccurredDuringMessageInterpolationException( e ); - } - } - - private boolean isAlreadyValidatedForPath(Object value, PathImpl path) { - Set pathSet = processedPathsPerBean.get( value ); - if ( pathSet == null ) { - return false; - } - - for ( PathImpl p : pathSet ) { - if ( path.isRootPath() || p.isRootPath() || isSubPathOf( path, p ) || isSubPathOf( p, path ) ) { - return true; - } - } - - return false; - } - - private boolean isSubPathOf(Path p1, Path p2) { - Iterator p1Iter = p1.iterator(); - Iterator p2Iter = p2.iterator(); - while ( p1Iter.hasNext() ) { - Path.Node p1Node = p1Iter.next(); - if ( !p2Iter.hasNext() ) { - return false; - } - Path.Node p2Node = p2Iter.next(); - if ( !p1Node.equals( p2Node ) ) { - return false; - } - } - return true; - } - - private boolean isAlreadyValidatedForCurrentGroup(Object value, Class group) { - return processedGroupUnits.contains( new BeanGroupProcessedUnit( value, group ) ); - } - - private void markCurrentBeanAsProcessedForCurrentPath(Object bean, PathImpl path) { - // HV-1031 The path object is mutated as we traverse the object tree, hence copy it before saving it - processedPathsPerBean.computeIfAbsent( bean, b -> new HashSet<>() ) - .add( PathImpl.createCopy( path ) ); - } - - private void markCurrentBeanAsProcessedForCurrentGroup(Object bean, Class group) { - processedGroupUnits.add( new BeanGroupProcessedUnit( bean, group ) ); - } - - /** - * Builder for creating {@link ValidationContext}s suited for the different kinds of validation. - * - * @author Gunnar Morling - */ - public static class ValidationContextBuilder { - private final BeanMetaDataManager beanMetaDataManager; - private final ConstraintValidatorManager constraintValidatorManager; - private final ConstraintValidatorFactory constraintValidatorFactory; - private final TraversableResolver traversableResolver; - private final HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext; - private final ValidatorScopedContext validatorScopedContext; - - private ValidationContextBuilder( - BeanMetaDataManager beanMetaDataManager, - ConstraintValidatorManager constraintValidatorManager, - ConstraintValidatorFactory constraintValidatorFactory, - ValidatorScopedContext validatorScopedContext, - TraversableResolver traversableResolver, - HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext) { - this.beanMetaDataManager = beanMetaDataManager; - this.constraintValidatorManager = constraintValidatorManager; - this.constraintValidatorFactory = constraintValidatorFactory; - this.traversableResolver = traversableResolver; - this.constraintValidatorInitializationContext = constraintValidatorInitializationContext; - this.validatorScopedContext = validatorScopedContext; - } - - public ValidationContext forValidate(T rootBean) { - @SuppressWarnings("unchecked") - Class rootBeanClass = (Class) rootBean.getClass(); - return new ValidationContext<>( - ValidationOperation.BEAN_VALIDATION, - constraintValidatorManager, - constraintValidatorFactory, - validatorScopedContext, - traversableResolver, - constraintValidatorInitializationContext, - rootBean, - rootBeanClass, - beanMetaDataManager.getBeanMetaData( rootBeanClass ), - null, //executable - null, //executable parameters - null, //executable return value - null //executable metadata - ); - } - - public ValidationContext forValidateProperty(T rootBean) { - @SuppressWarnings("unchecked") - Class rootBeanClass = (Class) rootBean.getClass(); - return new ValidationContext<>( - ValidationOperation.PROPERTY_VALIDATION, - constraintValidatorManager, - constraintValidatorFactory, - validatorScopedContext, - traversableResolver, - constraintValidatorInitializationContext, - rootBean, - rootBeanClass, - beanMetaDataManager.getBeanMetaData( rootBeanClass ), - null, //executable - null, //executable parameters - null, //executable return value - null //executable metadata - ); - } - - public ValidationContext forValidateValue(Class rootBeanClass) { - return new ValidationContext<>( - ValidationOperation.VALUE_VALIDATION, - constraintValidatorManager, - constraintValidatorFactory, - validatorScopedContext, - traversableResolver, - constraintValidatorInitializationContext, - null, //root bean - rootBeanClass, - beanMetaDataManager.getBeanMetaData( rootBeanClass ), - null, //executable - null, //executable parameters - null, //executable return value - null //executable metadata - ); - } - - public ValidationContext forValidateParameters( - ExecutableParameterNameProvider parameterNameProvider, - T rootBean, - Executable executable, - Object[] executableParameters) { - @SuppressWarnings("unchecked") - Class rootBeanClass = rootBean != null ? (Class) rootBean.getClass() : (Class) executable.getDeclaringClass(); - BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); - - return new ValidationContext<>( - ValidationOperation.PARAMETER_VALIDATION, - constraintValidatorManager, - constraintValidatorFactory, - validatorScopedContext, - traversableResolver, - constraintValidatorInitializationContext, - rootBean, - rootBeanClass, - rootBeanMetaData, - executable, - executableParameters, - null, //executable return value - rootBeanMetaData.getMetaDataFor( executable ) - ); - } - - public ValidationContext forValidateReturnValue( - T rootBean, - Executable executable, - Object executableReturnValue) { - @SuppressWarnings("unchecked") - Class rootBeanClass = rootBean != null ? (Class) rootBean.getClass() : (Class) executable.getDeclaringClass(); - BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); - return new ValidationContext<>( - ValidationOperation.RETURN_VALUE_VALIDATION, - constraintValidatorManager, - constraintValidatorFactory, - validatorScopedContext, - traversableResolver, - constraintValidatorInitializationContext, - rootBean, - rootBeanClass, - beanMetaDataManager.getBeanMetaData( rootBeanClass ), - executable, - null, //executable parameters - executableReturnValue, - rootBeanMetaData.getMetaDataFor( executable ) - ); - } - } - - private static final class BeanGroupProcessedUnit { - - // these fields are final but we don't mark them as final as an optimization - private Object bean; - private Class group; - private int hashCode; - - private BeanGroupProcessedUnit(Object bean, Class group) { - this.bean = bean; - this.group = group; - this.hashCode = createHashCode(); - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - - // No need to check if the class matches because of how this class is used in the set. - BeanGroupProcessedUnit that = (BeanGroupProcessedUnit) o; - - if ( bean != that.bean ) { // instance equality - return false; - } - if ( !group.equals( that.group ) ) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - return hashCode; - } - - private int createHashCode() { - int result = System.identityHashCode( bean ); - result = 31 * result + group.hashCode(); - return result; - } - } - - private static final class BeanPathMetaConstraintProcessedUnit { - - // these fields are final but we don't mark them as final as an optimization - private Object bean; - private Path path; - private MetaConstraint metaConstraint; - private int hashCode; - - private BeanPathMetaConstraintProcessedUnit(Object bean, Path path, MetaConstraint metaConstraint) { - this.bean = bean; - this.path = path; - this.metaConstraint = metaConstraint; - this.hashCode = createHashCode(); - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - - // No need to check if the class matches because of how this class is used in the set. - BeanPathMetaConstraintProcessedUnit that = (BeanPathMetaConstraintProcessedUnit) o; - - if ( bean != that.bean ) { // instance equality - return false; - } - if ( metaConstraint != that.metaConstraint ) { - return false; - } - if ( !path.equals( that.path ) ) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - return hashCode; - } - - private int createHashCode() { - int result = System.identityHashCode( bean ); - result = 31 * result + path.hashCode(); - result = 31 * result + System.identityHashCode( metaConstraint ); - return result; - } - } - - /** - * Context object storing the {@link Validator} level helper and configuration properties. - *

- * There should be only one per {@code Validator} instance. - */ - static class ValidatorScopedContext { - - /** - * The message interpolator. - */ - private final MessageInterpolator messageInterpolator; - - /** - * The parameter name provider. - */ - private final ExecutableParameterNameProvider parameterNameProvider; - - /** - * Provider for the current time when validating {@code @Future} or {@code @Past} - */ - private final ClockProvider clockProvider; - - /** - * Defines the temporal validation tolerance i.e. the allowed margin of error when comparing date/time in temporal - * constraints. - */ - private final Duration temporalValidationTolerance; - - /** - * Used to get the {@code ScriptEvaluatorFactory} when validating {@code @ScriptAssert} and - * {@code @ParameterScriptAssert} constraints. - */ - private final ScriptEvaluatorFactory scriptEvaluatorFactory; - - /** - * Hibernate Validator specific flag to abort validation on first constraint violation. - */ - private final boolean failFast; - - /** - * Hibernate Validator specific flag to disable the {@code TraversableResolver} result cache. - */ - private final boolean traversableResolverResultCacheEnabled; - - /** - * Hibernate Validator specific payload passed to the constraint validators. - */ - private final Object constraintValidatorPayload; - - ValidatorScopedContext(ValidatorFactoryScopedContext validatorFactoryScopedContext) { - this.messageInterpolator = validatorFactoryScopedContext.getMessageInterpolator(); - this.parameterNameProvider = validatorFactoryScopedContext.getParameterNameProvider(); - this.clockProvider = validatorFactoryScopedContext.getClockProvider(); - this.temporalValidationTolerance = validatorFactoryScopedContext.getTemporalValidationTolerance(); - this.scriptEvaluatorFactory = validatorFactoryScopedContext.getScriptEvaluatorFactory(); - this.failFast = validatorFactoryScopedContext.isFailFast(); - this.traversableResolverResultCacheEnabled = validatorFactoryScopedContext.isTraversableResolverResultCacheEnabled(); - this.constraintValidatorPayload = validatorFactoryScopedContext.getConstraintValidatorPayload(); - } - - public MessageInterpolator getMessageInterpolator() { - return this.messageInterpolator; - } - - public ExecutableParameterNameProvider getParameterNameProvider() { - return this.parameterNameProvider; - } - - public ClockProvider getClockProvider() { - return this.clockProvider; - } - - public Duration getTemporalValidationTolerance() { - return this.temporalValidationTolerance; - } - - public ScriptEvaluatorFactory getScriptEvaluatorFactory() { - return this.scriptEvaluatorFactory; - } - - public boolean isFailFast() { - return this.failFast; - } - - public boolean isTraversableResolverResultCacheEnabled() { - return this.traversableResolverResultCacheEnabled; - } - - public Object getConstraintValidatorPayload() { - return this.constraintValidatorPayload; - } - } - - /** - * The different validation operations that can occur. - */ - private enum ValidationOperation { - BEAN_VALIDATION, - PROPERTY_VALIDATION, - VALUE_VALIDATION, - PARAMETER_VALIDATION, - RETURN_VALUE_VALIDATION - } -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java index a50baef0fb..0297b1d599 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java @@ -664,7 +664,7 @@ public String toString() { } } - static class ValidatorFactoryScopedContext { + public static class ValidatorFactoryScopedContext { /** * The default message interpolator for this factory. */ diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index 7b9319c61e..82ca24e750 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -20,7 +20,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -36,8 +35,6 @@ import javax.validation.valueextraction.ValueExtractor; import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; -import org.hibernate.validator.internal.engine.ValidationContext.ValidationContextBuilder; -import org.hibernate.validator.internal.engine.ValidationContext.ValidatorScopedContext; import org.hibernate.validator.internal.engine.ValidatorFactoryImpl.ValidatorFactoryScopedContext; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; import org.hibernate.validator.internal.engine.groups.Group; @@ -48,6 +45,10 @@ import org.hibernate.validator.internal.engine.path.NodeImpl; import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.engine.resolver.TraversableResolvers; +import org.hibernate.validator.internal.engine.validationcontext.ExecutableValidationContext; +import org.hibernate.validator.internal.engine.validationcontext.ValidationContext; +import org.hibernate.validator.internal.engine.validationcontext.ValidationContextBuilder; +import org.hibernate.validator.internal.engine.validationcontext.ValidatorScopedContext; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorDescriptor; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorHelper; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; @@ -62,10 +63,6 @@ import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.facets.Cascadable; import org.hibernate.validator.internal.metadata.facets.Validatable; -import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.metadata.location.FieldConstraintLocation; -import org.hibernate.validator.internal.metadata.location.GetterConstraintLocation; -import org.hibernate.validator.internal.metadata.location.TypeArgumentConstraintLocation; import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ReflectionHelper; @@ -175,13 +172,13 @@ public final Set> validateProperty(T object, String p sanityCheckPropertyPath( propertyName ); sanityCheckGroups( groups ); - ValidationContext validationContext = getValidationContextBuilder().forValidateProperty( object ); + PathImpl propertyPath = PathImpl.createPathFromString( propertyName ); + ValidationContext validationContext = getValidationContextBuilder().forValidateProperty( object, propertyPath ); if ( !validationContext.getRootBeanMetaData().hasConstraints() ) { return Collections.emptySet(); } - PathImpl propertyPath = PathImpl.createPathFromString( propertyName ); ValueContext valueContext = getValueContextForPropertyValidation( validationContext, propertyPath ); if ( valueContext.getCurrentBean() == null ) { @@ -199,7 +196,8 @@ public final Set> validateValue(Class beanType, St sanityCheckPropertyPath( propertyName ); sanityCheckGroups( groups ); - ValidationContext validationContext = getValidationContextBuilder().forValidateValue( beanType ); + PathImpl propertyPath = PathImpl.createPathFromString( propertyName ); + ValidationContext validationContext = getValidationContextBuilder().forValidateValue( beanType, propertyPath ); if ( !validationContext.getRootBeanMetaData().hasConstraints() ) { return Collections.emptySet(); @@ -210,7 +208,7 @@ public final Set> validateValue(Class beanType, St return validateValueInContext( validationContext, value, - PathImpl.createPathFromString( propertyName ), + propertyPath, validationOrder ); } @@ -251,8 +249,7 @@ public Set> validateReturnValue(T object, Method meth private Set> validateParameters(T object, Executable executable, Object[] parameterValues, Class... groups) { sanityCheckGroups( groups ); - ValidationContext validationContext = getValidationContextBuilder().forValidateParameters( - validatorScopedContext.getParameterNameProvider(), + ExecutableValidationContext validationContext = getValidationContextBuilder().forValidateParameters( object, executable, parameterValues @@ -272,7 +269,7 @@ private Set> validateParameters(T object, Executable private Set> validateReturnValue(T object, Executable executable, Object returnValue, Class... groups) { sanityCheckGroups( groups ); - ValidationContext validationContext = getValidationContextBuilder().forValidateReturnValue( + ExecutableValidationContext validationContext = getValidationContextBuilder().forValidateReturnValue( object, executable, returnValue @@ -312,7 +309,7 @@ public ExecutableValidator forExecutables() { } private ValidationContextBuilder getValidationContextBuilder() { - return ValidationContext.getValidationContextBuilder( + return new ValidationContextBuilder( beanMetaDataManager, constraintValidatorManager, constraintValidatorFactory, @@ -352,10 +349,10 @@ private ValidationOrder determineGroupValidationOrder(Class[] groups) { /** * Validates the given object using the available context information. + * * @param validationContext the global validation context * @param valueContext the current validation context * @param validationOrder Contains the information which and in which order groups have to be executed - * * @param The root bean type * * @return Set of constraint violations or the empty set if there were no violations. @@ -765,7 +762,7 @@ private ValueContext buildNewLocalExecutionContext(ValueContext private Set> validateValueInContext(ValidationContext validationContext, Object value, PathImpl propertyPath, ValidationOrder validationOrder) { - ValueContext valueContext = getValueContextForValueValidation( validationContext, propertyPath ); + ValueContext valueContext = getValueContextForValueValidation( validationContext.getRootBeanClass(), propertyPath ); valueContext.setCurrentValidatedValue( value ); BeanMetaData beanMetaData = valueContext.getCurrentBeanMetaData(); @@ -806,7 +803,7 @@ private Set> validateValueInContext(ValidationContext return validationContext.getFailingConstraints(); } - private void validateParametersInContext(ValidationContext validationContext, + private void validateParametersInContext(ExecutableValidationContext validationContext, Object[] parameterValues, ValidationOrder validationOrder) { BeanMetaData beanMetaData = validationContext.getRootBeanMetaData(); @@ -894,7 +891,7 @@ private void validateParametersInContext(ValidationContext validationCont } } - private void validateParametersForGroup(ValidationContext validationContext, ExecutableMetaData executableMetaData, Object[] parameterValues, + private void validateParametersForGroup(ExecutableValidationContext validationContext, ExecutableMetaData executableMetaData, Object[] parameterValues, Group group) { Contracts.assertNotNull( executableMetaData, "executableMetaData may not be null" ); @@ -931,7 +928,7 @@ private void validateParametersForGroup(ValidationContext validationConte } } - private void validateParametersForSingleGroup(ValidationContext validationContext, Object[] parameterValues, ExecutableMetaData executableMetaData, Class currentValidatedGroup) { + private void validateParametersForSingleGroup(ExecutableValidationContext validationContext, Object[] parameterValues, ExecutableMetaData executableMetaData, Class currentValidatedGroup) { if ( !executableMetaData.getCrossParameterConstraints().isEmpty() ) { ValueContext valueContext = getExecutableValueContext( validationContext.getRootBean(), executableMetaData, executableMetaData.getValidatableParametersMetaData(), currentValidatedGroup @@ -1005,7 +1002,7 @@ private ValueContext getExecutableValueContext(T object, Executab return valueContext; } - private void validateReturnValueInContext(ValidationContext validationContext, T bean, V value, ValidationOrder validationOrder) { + private void validateReturnValueInContext(ExecutableValidationContext validationContext, T bean, V value, ValidationOrder validationOrder) { BeanMetaData beanMetaData = validationContext.getRootBeanMetaData(); Optional executableMetaDataOptional = validationContext.getExecutableMetaData(); @@ -1141,8 +1138,9 @@ private void validateReturnValueForSingleGroup(ValidationContext validati * * @param validationContext The validation context. * @param propertyPath The property path for which constraints have to be collected. + * * @return Returns an instance of {@code ValueContext} which describes the local validation context associated to - * the given property path. + * the given property path. */ private ValueContext getValueContextForPropertyValidation(ValidationContext validationContext, PathImpl propertyPath) { Class clazz = validationContext.getRootBeanClass(); @@ -1204,7 +1202,6 @@ else if ( propertyPathNode.getKey() != null ) { throw LOG.getInvalidPropertyPathException( clazz, propertyPath.asString() ); } - validationContext.setValidatedProperty( propertyMetaData.getName() ); propertyPath.removeLeafNode(); return ValueContext.getLocalExecutionContext( validatorScopedContext.getParameterNameProvider(), value, beanMetaData, propertyPath ); @@ -1216,14 +1213,14 @@ else if ( propertyPathNode.getKey() != null ) { * We are only able to use the static types as we don't have the value. *

* - * @param validationContext The validation context. + * @param rootBeanClass The class of the root bean. * @param propertyPath The property path for which constraints have to be collected. * @return Returns an instance of {@code ValueContext} which describes the local validation context associated to * the given property path. */ - private ValueContext getValueContextForValueValidation(ValidationContext validationContext, + private ValueContext getValueContextForValueValidation(Class rootBeanClass, PathImpl propertyPath) { - Class clazz = validationContext.getRootBeanClass(); + Class clazz = rootBeanClass; BeanMetaData beanMetaData = null; PropertyMetaData propertyMetaData = null; @@ -1257,7 +1254,6 @@ private ValueContext getValueContextForValueValidation(ValidationConte throw LOG.getInvalidPropertyPathException( clazz, propertyPath.asString() ); } - validationContext.setValidatedProperty( propertyMetaData.getName() ); propertyPath.removeLeafNode(); return ValueContext.getLocalExecutionContext( validatorScopedContext.getParameterNameProvider(), clazz, beanMetaData, propertyPath ); @@ -1266,10 +1262,11 @@ private ValueContext getValueContextForValueValidation(ValidationConte private boolean isValidationRequired(ValidationContext validationContext, ValueContext valueContext, MetaConstraint metaConstraint) { - // validateProperty()/validateValue() call, but this constraint is for another property - if ( validationContext.getValidatedProperty() != null && - !Objects.equals( validationContext.getValidatedProperty(), getPropertyName( metaConstraint.getLocation() ) ) ) { - return false; + // check if this validation context is qualified to validate the current meta constraint. + // For instance, in the case of validateProperty()/validateValue(), the current meta constraint + // could be for another property and, in this case, we don't validate it. + if ( !validationContext.appliesTo( metaConstraint ) ) { + return false; } if ( validationContext.hasMetaConstraintBeenProcessed( valueContext.getCurrentBean(), @@ -1366,7 +1363,7 @@ private boolean shouldFailFast(ValidationContext validationContext) { return validationContext.isFailFastModeEnabled() && !validationContext.getFailingConstraints().isEmpty(); } - private PropertyMetaData getBeanPropertyMetaData(BeanMetaData beanMetaData, Path.Node propertyNode ) { + private PropertyMetaData getBeanPropertyMetaData(BeanMetaData beanMetaData, Path.Node propertyNode) { if ( !ElementKind.PROPERTY.equals( propertyNode.getKind() ) ) { throw LOG.getInvalidPropertyPathException( beanMetaData.getBeanClass(), propertyNode.getName() ); } @@ -1377,19 +1374,4 @@ private PropertyMetaData getBeanPropertyMetaData(BeanMetaData beanMetaData, P private Object getCascadableValue(ValidationContext validationContext, Object object, Cascadable cascadable) { return cascadable.getValue( object ); } - - private String getPropertyName(ConstraintLocation location) { - if ( location instanceof TypeArgumentConstraintLocation ) { - location = ( (TypeArgumentConstraintLocation) location ).getOuterDelegate(); - } - - if ( location instanceof FieldConstraintLocation ) { - return ( (FieldConstraintLocation) location ).getPropertyName(); - } - else if ( location instanceof GetterConstraintLocation ) { - return ( (GetterConstraintLocation) location ).getPropertyName(); - } - - return null; - } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java index 4c705771a4..06d8dd0cbb 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java @@ -22,8 +22,8 @@ import javax.validation.ConstraintValidator; import org.hibernate.validator.constraints.CompositionType; -import org.hibernate.validator.internal.engine.ValidationContext; import org.hibernate.validator.internal.engine.ValueContext; +import org.hibernate.validator.internal.engine.validationcontext.ValidationContext; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.logging.Log; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java index 1481c1af9a..ac0b8002d3 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java @@ -20,8 +20,8 @@ import javax.validation.ConstraintValidator; import javax.validation.ValidationException; -import org.hibernate.validator.internal.engine.ValidationContext; import org.hibernate.validator.internal.engine.ValueContext; +import org.hibernate.validator.internal.engine.validationcontext.ValidationContext; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java index dbf11412ac..331cb90a38 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java @@ -13,8 +13,8 @@ import javax.validation.ConstraintValidator; -import org.hibernate.validator.internal.engine.ValidationContext; import org.hibernate.validator.internal.engine.ValueContext; +import org.hibernate.validator.internal.engine.validationcontext.ValidationContext; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java new file mode 100644 index 0000000000..f804dc431c --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java @@ -0,0 +1,458 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.validationcontext; + +import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; + +import java.lang.invoke.MethodHandles; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import javax.validation.ConstraintValidatorFactory; +import javax.validation.ConstraintViolation; +import javax.validation.Path; +import javax.validation.TraversableResolver; +import javax.validation.ValidationException; +import javax.validation.Validator; +import javax.validation.metadata.ConstraintDescriptor; + +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; +import org.hibernate.validator.internal.engine.MessageInterpolatorContext; +import org.hibernate.validator.internal.engine.ValueContext; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext; +import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; +import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; + +/** + * Context object keeping track of all required data for a validation call. + *

+ * We use this object to collect all failing constraints, but also to have access to resources like + * constraint validator factory, message interpolator, traversable resolver, etc. + * + * @author Hardy Ferentschik + * @author Emmanuel Bernard + * @author Gunnar Morling + * @author Guillaume Smet + * @author Marko Bekhta + */ +abstract class AbstractValidationContext implements ValidationContext { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + /** + * Caches and manages life cycle of constraint validator instances. + */ + private final ConstraintValidatorManager constraintValidatorManager; + + /** + * The root bean of the validation. + */ + private final T rootBean; + + /** + * The root bean class of the validation. + */ + private final Class rootBeanClass; + + /** + * The metadata of the root bean. + */ + private final BeanMetaData rootBeanMetaData; + + /** + * The set of already processed meta constraints per bean - path ({@link BeanPathMetaConstraintProcessedUnit}). + */ + private final Set processedPathUnits; + + /** + * The set of already processed groups per bean ({@link BeanGroupProcessedUnit}). + */ + private final Set processedGroupUnits; + + /** + * Maps an object to a list of paths in which it has been validated. The objects are the bean instances. + */ + private final Map> processedPathsPerBean; + + /** + * Contains all failing constraints so far. + */ + private final Set> failingConstraintViolations; + + /** + * The constraint factory which should be used in this context. + */ + private final ConstraintValidatorFactory constraintValidatorFactory; + + /** + * Context containing all {@link Validator} level helpers and configuration properties. + */ + protected final ValidatorScopedContext validatorScopedContext; + + /** + * Allows a JPA provider to decide whether a property should be validated. + */ + private final TraversableResolver traversableResolver; + + /** + * The constraint validator initialization context. + */ + private final HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext; + + /** + * Indicates if the tracking of already validated bean should be disabled. + */ + private final boolean disableAlreadyValidatedBeanTracking; + + protected AbstractValidationContext( + ConstraintValidatorManager constraintValidatorManager, + ConstraintValidatorFactory constraintValidatorFactory, + ValidatorScopedContext validatorScopedContext, + TraversableResolver traversableResolver, + HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext, + T rootBean, + Class rootBeanClass, + BeanMetaData rootBeanMetaData, + boolean disableAlreadyValidatedBeanTracking + ) { + this.constraintValidatorManager = constraintValidatorManager; + this.validatorScopedContext = validatorScopedContext; + this.constraintValidatorFactory = constraintValidatorFactory; + this.traversableResolver = traversableResolver; + this.constraintValidatorInitializationContext = constraintValidatorInitializationContext; + + this.rootBean = rootBean; + this.rootBeanClass = rootBeanClass; + this.rootBeanMetaData = rootBeanMetaData; + + this.processedGroupUnits = new HashSet<>(); + this.processedPathUnits = new HashSet<>(); + this.processedPathsPerBean = new IdentityHashMap<>(); + this.failingConstraintViolations = newHashSet(); + + this.disableAlreadyValidatedBeanTracking = disableAlreadyValidatedBeanTracking; + } + + @Override + public T getRootBean() { + return rootBean; + } + + @Override + public Class getRootBeanClass() { + return rootBeanClass; + } + + @Override + public BeanMetaData getRootBeanMetaData() { + return rootBeanMetaData; + } + + @Override + public TraversableResolver getTraversableResolver() { + return traversableResolver; + } + + @Override + public boolean isFailFastModeEnabled() { + return validatorScopedContext.isFailFast(); + } + + @Override + public ConstraintValidatorManager getConstraintValidatorManager() { + return constraintValidatorManager; + } + + @Override + public HibernateConstraintValidatorInitializationContext getConstraintValidatorInitializationContext() { + return constraintValidatorInitializationContext; + } + + @Override + public ConstraintValidatorFactory getConstraintValidatorFactory() { + return constraintValidatorFactory; + } + + @Override + public boolean isBeanAlreadyValidated(Object value, Class group, PathImpl path) { + if ( disableAlreadyValidatedBeanTracking ) { + return false; + } + + boolean alreadyValidated; + alreadyValidated = isAlreadyValidatedForCurrentGroup( value, group ); + + if ( alreadyValidated ) { + alreadyValidated = isAlreadyValidatedForPath( value, path ); + } + + return alreadyValidated; + } + + @Override + public void markCurrentBeanAsProcessed(ValueContext valueContext) { + if ( disableAlreadyValidatedBeanTracking ) { + return; + } + + markCurrentBeanAsProcessedForCurrentGroup( valueContext.getCurrentBean(), valueContext.getCurrentGroup() ); + markCurrentBeanAsProcessedForCurrentPath( valueContext.getCurrentBean(), valueContext.getPropertyPath() ); + } + + @Override + public Set> getFailingConstraints() { + return failingConstraintViolations; + } + + @Override + public void addConstraintFailure( + ValueContext valueContext, + ConstraintViolationCreationContext constraintViolationCreationContext, + ConstraintDescriptor descriptor + ) { + String messageTemplate = constraintViolationCreationContext.getMessage(); + String interpolatedMessage = interpolate( + messageTemplate, + valueContext.getCurrentValidatedValue(), + descriptor, + constraintViolationCreationContext.getMessageParameters(), + constraintViolationCreationContext.getExpressionVariables() + ); + // at this point we make a copy of the path to avoid side effects + Path path = PathImpl.createCopy( constraintViolationCreationContext.getPath() ); + + this.failingConstraintViolations.add( + createConstraintViolation( + messageTemplate, + interpolatedMessage, + path, + descriptor, + valueContext, + constraintViolationCreationContext + ) + ); + } + + protected abstract ConstraintViolation createConstraintViolation( + String messageTemplate, + String interpolatedMessage, + Path propertyPath, + ConstraintDescriptor constraintDescriptor, + ValueContext valueContext, + ConstraintViolationCreationContext constraintViolationCreationContext); + + @Override + public boolean hasMetaConstraintBeenProcessed(Object bean, Path path, MetaConstraint metaConstraint) { + // this is only useful if the constraint is defined for more than 1 group as in the case it's only + // defined for one group, there is no chance it's going to be called twice. + if ( metaConstraint.isDefinedForOneGroupOnly() ) { + return false; + } + + return processedPathUnits.contains( new BeanPathMetaConstraintProcessedUnit( bean, path, metaConstraint ) ); + } + + @Override + public void markConstraintProcessed(Object bean, Path path, MetaConstraint metaConstraint) { + // this is only useful if the constraint is defined for more than 1 group as in the case it's only + // defined for one group, there is no chance it's going to be called twice. + if ( metaConstraint.isDefinedForOneGroupOnly() ) { + return; + } + + processedPathUnits.add( new BeanPathMetaConstraintProcessedUnit( bean, path, metaConstraint ) ); + } + + @Override + public ConstraintValidatorContextImpl createConstraintValidatorContextFor(ConstraintDescriptorImpl constraintDescriptor, PathImpl path) { + return new ConstraintValidatorContextImpl( + validatorScopedContext.getClockProvider(), + path, + constraintDescriptor, + validatorScopedContext.getConstraintValidatorPayload() + ); + } + + @Override + public abstract String toString(); + + private String interpolate( + String messageTemplate, + Object validatedValue, + ConstraintDescriptor descriptor, + Map messageParameters, + Map expressionVariables) { + MessageInterpolatorContext context = new MessageInterpolatorContext( + descriptor, + validatedValue, + getRootBeanClass(), + messageParameters, + expressionVariables + ); + + try { + return validatorScopedContext.getMessageInterpolator().interpolate( + messageTemplate, + context + ); + } + catch (ValidationException ve) { + throw ve; + } + catch (Exception e) { + throw LOG.getExceptionOccurredDuringMessageInterpolationException( e ); + } + } + + private boolean isAlreadyValidatedForPath(Object value, PathImpl path) { + Set pathSet = processedPathsPerBean.get( value ); + if ( pathSet == null ) { + return false; + } + + for ( PathImpl p : pathSet ) { + if ( path.isRootPath() || p.isRootPath() || isSubPathOf( path, p ) || isSubPathOf( p, path ) ) { + return true; + } + } + + return false; + } + + private boolean isSubPathOf(Path p1, Path p2) { + Iterator p1Iter = p1.iterator(); + Iterator p2Iter = p2.iterator(); + while ( p1Iter.hasNext() ) { + Path.Node p1Node = p1Iter.next(); + if ( !p2Iter.hasNext() ) { + return false; + } + Path.Node p2Node = p2Iter.next(); + if ( !p1Node.equals( p2Node ) ) { + return false; + } + } + return true; + } + + private boolean isAlreadyValidatedForCurrentGroup(Object value, Class group) { + return processedGroupUnits.contains( new BeanGroupProcessedUnit( value, group ) ); + } + + private void markCurrentBeanAsProcessedForCurrentPath(Object bean, PathImpl path) { + // HV-1031 The path object is mutated as we traverse the object tree, hence copy it before saving it + processedPathsPerBean.computeIfAbsent( bean, b -> new HashSet<>() ) + .add( PathImpl.createCopy( path ) ); + } + + private void markCurrentBeanAsProcessedForCurrentGroup(Object bean, Class group) { + processedGroupUnits.add( new BeanGroupProcessedUnit( bean, group ) ); + } + + private static final class BeanPathMetaConstraintProcessedUnit { + + // these fields are final but we don't mark them as final as an optimization + private Object bean; + private Path path; + private MetaConstraint metaConstraint; + private int hashCode; + + BeanPathMetaConstraintProcessedUnit(Object bean, Path path, MetaConstraint metaConstraint) { + this.bean = bean; + this.path = path; + this.metaConstraint = metaConstraint; + this.hashCode = createHashCode(); + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + + // No need to check if the class matches because of how this class is used in the set. + BeanPathMetaConstraintProcessedUnit that = (BeanPathMetaConstraintProcessedUnit) o; + + if ( bean != that.bean ) { // instance equality + return false; + } + if ( metaConstraint != that.metaConstraint ) { + return false; + } + if ( !path.equals( that.path ) ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return hashCode; + } + + private int createHashCode() { + int result = System.identityHashCode( bean ); + result = 31 * result + path.hashCode(); + result = 31 * result + System.identityHashCode( metaConstraint ); + return result; + } + } + + private static final class BeanGroupProcessedUnit { + + // these fields are final but we don't mark them as final as an optimization + private Object bean; + private Class group; + private int hashCode; + + BeanGroupProcessedUnit(Object bean, Class group) { + this.bean = bean; + this.group = group; + this.hashCode = createHashCode(); + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + + // No need to check if the class matches because of how this class is used in the set. + BeanGroupProcessedUnit that = (BeanGroupProcessedUnit) o; + + if ( bean != that.bean ) { // instance equality + return false; + } + if ( !group.equals( that.group ) ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return hashCode; + } + + private int createHashCode() { + int result = System.identityHashCode( bean ); + result = 31 * result + group.hashCode(); + return result; + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BeanValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BeanValidationContext.java new file mode 100644 index 0000000000..3aaee06783 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BeanValidationContext.java @@ -0,0 +1,78 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.validationcontext; + +import javax.validation.ConstraintValidatorFactory; +import javax.validation.ConstraintViolation; +import javax.validation.Path; +import javax.validation.TraversableResolver; +import javax.validation.metadata.ConstraintDescriptor; + +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; +import org.hibernate.validator.internal.engine.ConstraintViolationImpl; +import org.hibernate.validator.internal.engine.ValueContext; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; + +/** + * Implementation of {@link AbstractValidationContext} for the validation of a bean. + * + * @author Marko Bekhta + */ +class BeanValidationContext extends AbstractValidationContext { + + BeanValidationContext( + ConstraintValidatorManager constraintValidatorManager, + ConstraintValidatorFactory constraintValidatorFactory, + ValidatorScopedContext validatorScopedContext, + TraversableResolver traversableResolver, + HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext, + T rootBean, + Class rootBeanClass, + BeanMetaData rootBeanMetaData + ) { + super( constraintValidatorManager, constraintValidatorFactory, validatorScopedContext, traversableResolver, constraintValidatorInitializationContext, + rootBean, rootBeanClass, rootBeanMetaData, buildDisableAlreadyValidatedBeanTracking( rootBeanMetaData ) + ); + } + + private static boolean buildDisableAlreadyValidatedBeanTracking(BeanMetaData rootBeanMetaData) { + return !rootBeanMetaData.hasCascadables(); + } + + @Override + protected ConstraintViolation createConstraintViolation( + String messageTemplate, String interpolatedMessage, Path propertyPath, + ConstraintDescriptor constraintDescriptor, ValueContext localContext, + ConstraintViolationCreationContext constraintViolationCreationContext) { + return ConstraintViolationImpl.forBeanValidation( + messageTemplate, + constraintViolationCreationContext.getMessageParameters(), + constraintViolationCreationContext.getExpressionVariables(), + interpolatedMessage, + getRootBeanClass(), + getRootBean(), + localContext.getCurrentBean(), + localContext.getCurrentValidatedValue(), + propertyPath, + constraintDescriptor, + localContext.getElementType(), + constraintViolationCreationContext.getDynamicPayload() + ); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder( getClass().getSimpleName() ); + sb.append( '{' ); + sb.append( "rootBeanClass=" ).append( getRootBeanClass() ); + sb.append( '}' ); + return sb.toString(); + } + +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ExecutableValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ExecutableValidationContext.java new file mode 100644 index 0000000000..821ab9a567 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ExecutableValidationContext.java @@ -0,0 +1,25 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.validationcontext; + +import java.lang.reflect.Executable; +import java.util.Optional; + +import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; + +/** + * Extension of {@link ValidationContext} for executable validation. + * + * @author Marko Bekhta + */ +public interface ExecutableValidationContext extends ValidationContext { + + Executable getExecutable(); + + Optional getExecutableMetaData(); + +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ParameterExecutableValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ParameterExecutableValidationContext.java new file mode 100644 index 0000000000..c581746598 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ParameterExecutableValidationContext.java @@ -0,0 +1,153 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.validationcontext; + +import java.lang.reflect.Executable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +import javax.validation.ConstraintValidatorFactory; +import javax.validation.ConstraintViolation; +import javax.validation.Path; +import javax.validation.TraversableResolver; +import javax.validation.metadata.ConstraintDescriptor; + +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; +import org.hibernate.validator.internal.engine.ConstraintViolationImpl; +import org.hibernate.validator.internal.engine.ValueContext; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext; +import org.hibernate.validator.internal.engine.constraintvalidation.CrossParameterConstraintValidatorContextImpl; +import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; +import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; +import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; +import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; + +/** + * Implementation of {@link AbstractValidationContext} for executable's parameter validation. + * + * @author Marko Bekhta + */ +public class ParameterExecutableValidationContext extends AbstractValidationContext + implements ExecutableValidationContext { + + /** + * The method of the current validation call. + */ + private final Executable executable; + + /** + * The validated parameters. + */ + private final Object[] executableParameters; + + /** + * The metadata of the Executable. Will be non empty if the method is constrained. + */ + private final Optional executableMetaData; + + ParameterExecutableValidationContext( + ConstraintValidatorManager constraintValidatorManager, + ConstraintValidatorFactory constraintValidatorFactory, + ValidatorScopedContext validatorScopedContext, + TraversableResolver traversableResolver, + HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext, + T rootBean, + Class rootBeanClass, + BeanMetaData rootBeanMetaData, + Executable executable, + Optional executableMetaData, + Object[] executableParameters + ) { + super( constraintValidatorManager, constraintValidatorFactory, validatorScopedContext, traversableResolver, + constraintValidatorInitializationContext, rootBean, rootBeanClass, rootBeanMetaData, + buildDisableAlreadyValidatedBeanTracking( executableMetaData ) + ); + this.executable = executable; + this.executableMetaData = executableMetaData; + this.executableParameters = executableParameters; + } + + @Override + public Executable getExecutable() { + return executable; + } + + @Override + public Optional getExecutableMetaData() { + return executableMetaData; + } + + private static boolean buildDisableAlreadyValidatedBeanTracking(Optional executableMetaData) { + if ( !executableMetaData.isPresent() ) { + // the method is unconstrained so there's no need to worry about the tracking + return false; + } + + return !executableMetaData.get().getReturnValueMetaData().hasCascadables(); + } + + @Override + public ConstraintValidatorContextImpl createConstraintValidatorContextFor(ConstraintDescriptorImpl constraintDescriptor, PathImpl path) { + if ( ConstraintType.CROSS_PARAMETER.equals( constraintDescriptor.getConstraintType() ) ) { + return new CrossParameterConstraintValidatorContextImpl( + getParameterNames(), + validatorScopedContext.getClockProvider(), + path, + constraintDescriptor, + validatorScopedContext.getConstraintValidatorPayload() + ); + } + + return new ConstraintValidatorContextImpl( + validatorScopedContext.getClockProvider(), + path, + constraintDescriptor, + validatorScopedContext.getConstraintValidatorPayload() + ); + } + + @Override + protected ConstraintViolation createConstraintViolation( + String messageTemplate, String interpolatedMessage, Path propertyPath, ConstraintDescriptor constraintDescriptor, ValueContext valueContext, + ConstraintViolationCreationContext constraintViolationCreationContext) { + return ConstraintViolationImpl.forParameterValidation( + messageTemplate, + constraintViolationCreationContext.getMessageParameters(), + constraintViolationCreationContext.getExpressionVariables(), + interpolatedMessage, + getRootBeanClass(), + getRootBean(), + valueContext.getCurrentBean(), + valueContext.getCurrentValidatedValue(), + propertyPath, + constraintDescriptor, + valueContext.getElementType(), + executableParameters, + constraintViolationCreationContext.getDynamicPayload() + ); + } + + private List getParameterNames() { + return validatorScopedContext.getParameterNameProvider().getParameterNames( executable ); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder( getClass().getSimpleName() ); + sb.append( '{' ); + sb.append( "rootBeanClass=" ).append( getRootBeanClass() ); + sb.append( ", executable=" ).append( executable ); + sb.append( ", executableParameters=" ).append( Arrays.toString( executableParameters ) ); + sb.append( ", executableMetaData=" ).append( executableMetaData ); + sb.append( '}' ); + return sb.toString(); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java new file mode 100644 index 0000000000..1a2a1d8a1f --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java @@ -0,0 +1,115 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.validationcontext; + +import java.util.Objects; + +import javax.validation.ConstraintValidatorFactory; +import javax.validation.ConstraintViolation; +import javax.validation.Path; +import javax.validation.TraversableResolver; +import javax.validation.Validator; +import javax.validation.metadata.ConstraintDescriptor; + +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; +import org.hibernate.validator.internal.engine.ConstraintViolationImpl; +import org.hibernate.validator.internal.engine.ValueContext; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; +import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.location.FieldConstraintLocation; +import org.hibernate.validator.internal.metadata.location.GetterConstraintLocation; +import org.hibernate.validator.internal.metadata.location.TypeArgumentConstraintLocation; + +/** + * Implementation of {@link AbstractValidationContext} for property/value validation + * (used in calls to {@link Validator#validateProperty(Object, String, Class[])} or + * {@link Validator#validateValue(Class, String, Object, Class[])}). + * + * @author Marko Bekhta + */ +class PropertyValidationContext extends AbstractValidationContext { + + /** + * The name of the validated (leaf) property in case of a validateProperty()/validateValue() call. + */ + private String validatedProperty; + + PropertyValidationContext( + ConstraintValidatorManager constraintValidatorManager, + ConstraintValidatorFactory constraintValidatorFactory, + ValidatorScopedContext validatorScopedContext, + TraversableResolver traversableResolver, + HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext, + T rootBean, + Class rootBeanClass, + BeanMetaData rootBeanMetaData, + String validatedProperty + ) { + super( constraintValidatorManager, constraintValidatorFactory, validatorScopedContext, traversableResolver, constraintValidatorInitializationContext, + rootBean, rootBeanClass, rootBeanMetaData, buildDisableAlreadyValidatedBeanTracking( rootBeanMetaData ) + ); + this.validatedProperty = validatedProperty; + } + + private static boolean buildDisableAlreadyValidatedBeanTracking(BeanMetaData rootBeanMetaData) { + return !rootBeanMetaData.hasCascadables(); + } + + @Override + public boolean appliesTo(MetaConstraint metaConstraint) { + return Objects.equals( validatedProperty, getPropertyName( metaConstraint.getLocation() ) ); + } + + private String getPropertyName(ConstraintLocation location) { + if ( location instanceof TypeArgumentConstraintLocation ) { + location = ( (TypeArgumentConstraintLocation) location ).getOuterDelegate(); + } + + if ( location instanceof FieldConstraintLocation ) { + return ( (FieldConstraintLocation) location ).getPropertyName(); + } + else if ( location instanceof GetterConstraintLocation ) { + return ( (GetterConstraintLocation) location ).getPropertyName(); + } + + return null; + } + + @Override + protected ConstraintViolation createConstraintViolation( + String messageTemplate, String interpolatedMessage, Path propertyPath, + ConstraintDescriptor constraintDescriptor, ValueContext localContext, + ConstraintViolationCreationContext constraintViolationCreationContext) { + return ConstraintViolationImpl.forBeanValidation( + messageTemplate, + constraintViolationCreationContext.getMessageParameters(), + constraintViolationCreationContext.getExpressionVariables(), + interpolatedMessage, + getRootBeanClass(), + getRootBean(), + localContext.getCurrentBean(), + localContext.getCurrentValidatedValue(), + propertyPath, + constraintDescriptor, + localContext.getElementType(), + constraintViolationCreationContext.getDynamicPayload() + ); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder( getClass().getSimpleName() ); + sb.append( '{' ); + sb.append( "rootBeanClass=" ).append( getRootBeanClass() ); + sb.append( ", validatedProperty='" ).append( validatedProperty ).append( '\'' ); + sb.append( '}' ); + return sb.toString(); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ReturnValueExecutableValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ReturnValueExecutableValidationContext.java new file mode 100644 index 0000000000..1c2455fa4d --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ReturnValueExecutableValidationContext.java @@ -0,0 +1,121 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.validationcontext; + +import java.lang.reflect.Executable; +import java.util.Optional; + +import javax.validation.ConstraintValidatorFactory; +import javax.validation.ConstraintViolation; +import javax.validation.Path; +import javax.validation.TraversableResolver; +import javax.validation.metadata.ConstraintDescriptor; + +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; +import org.hibernate.validator.internal.engine.ConstraintViolationImpl; +import org.hibernate.validator.internal.engine.ValueContext; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; +import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; + +/** + * Implementation of {@link AbstractValidationContext} for executable's return value validation. + * + * @author Marko Bekhta + */ +public class ReturnValueExecutableValidationContext extends AbstractValidationContext + implements ExecutableValidationContext { + + /** + * The method of the current validation call. + */ + private final Executable executable; + + /** + * The validated return value. + */ + private final Object executableReturnValue; + + /** + * The metadata of the Executable. Will be non empty if the method is constrained. + */ + private final Optional executableMetaData; + + ReturnValueExecutableValidationContext( + ConstraintValidatorManager constraintValidatorManager, + ConstraintValidatorFactory constraintValidatorFactory, + ValidatorScopedContext validatorScopedContext, + TraversableResolver traversableResolver, + HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext, + T rootBean, + Class rootBeanClass, + BeanMetaData rootBeanMetaData, + Executable executable, + Optional executableMetaData, + Object executableReturnValue + ) { + super( constraintValidatorManager, constraintValidatorFactory, validatorScopedContext, traversableResolver, + constraintValidatorInitializationContext, rootBean, rootBeanClass, rootBeanMetaData, + buildDisableAlreadyValidatedBeanTracking( executableMetaData ) + ); + this.executable = executable; + this.executableMetaData = executableMetaData; + this.executableReturnValue = executableReturnValue; + } + + @Override + public Executable getExecutable() { + return executable; + } + + @Override + public Optional getExecutableMetaData() { + return executableMetaData; + } + + private static boolean buildDisableAlreadyValidatedBeanTracking(Optional executableMetaData) { + if ( !executableMetaData.isPresent() ) { + // the method is unconstrained so there's no need to worry about the tracking + return false; + } + + return !executableMetaData.get().getReturnValueMetaData().hasCascadables(); + } + + @Override + protected ConstraintViolation createConstraintViolation(String messageTemplate, String interpolatedMessage, Path propertyPath, ConstraintDescriptor constraintDescriptor, ValueContext valueContext, + ConstraintViolationCreationContext constraintViolationCreationContext) { + return ConstraintViolationImpl.forReturnValueValidation( + messageTemplate, + constraintViolationCreationContext.getMessageParameters(), + constraintViolationCreationContext.getExpressionVariables(), + interpolatedMessage, + getRootBeanClass(), + getRootBean(), + valueContext.getCurrentBean(), + valueContext.getCurrentValidatedValue(), + propertyPath, + constraintDescriptor, + valueContext.getElementType(), + executableReturnValue, + constraintViolationCreationContext.getDynamicPayload() + ); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder( getClass().getSimpleName() ); + sb.append( '{' ); + sb.append( "rootBeanClass=" ).append( getRootBeanClass() ); + sb.append( ", executable=" ).append( executable ); + sb.append( ", executableReturnValue=" ).append( executableReturnValue ); + sb.append( ", executableMetaData=" ).append( executableMetaData ); + sb.append( '}' ); + return sb.toString(); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContext.java new file mode 100644 index 0000000000..afa575aacf --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContext.java @@ -0,0 +1,77 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.validationcontext; + +import java.util.Set; + +import javax.validation.ConstraintValidatorFactory; +import javax.validation.ConstraintViolation; +import javax.validation.Path; +import javax.validation.TraversableResolver; +import javax.validation.metadata.ConstraintDescriptor; + +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; +import org.hibernate.validator.internal.engine.ValueContext; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext; +import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; +import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; + +/** + * Interface that exposes contextual information required for a validation call. + *

+ * Provides ability to collect failing constraints and gives access to resources like + * constraint validator factory, traversable resolver, etc. + * + * @author Hardy Ferentschik + * @author Emmanuel Bernard + * @author Gunnar Morling + * @author Guillaume Smet + */ +public interface ValidationContext { + + T getRootBean(); + + Class getRootBeanClass(); + + BeanMetaData getRootBeanMetaData(); + + TraversableResolver getTraversableResolver(); + + boolean isFailFastModeEnabled(); + + ConstraintValidatorManager getConstraintValidatorManager(); + + HibernateConstraintValidatorInitializationContext getConstraintValidatorInitializationContext(); + + ConstraintValidatorFactory getConstraintValidatorFactory(); + + boolean isBeanAlreadyValidated(Object value, Class group, PathImpl path); + + void markCurrentBeanAsProcessed(ValueContext valueContext); + + Set> getFailingConstraints(); + + void addConstraintFailure( + ValueContext localContext, + ConstraintViolationCreationContext constraintViolationCreationContext, + ConstraintDescriptor descriptor + ); + + boolean hasMetaConstraintBeenProcessed(Object bean, Path path, MetaConstraint metaConstraint); + + void markConstraintProcessed(Object bean, Path path, MetaConstraint metaConstraint); + + default boolean appliesTo(MetaConstraint metaConstraint) { + return true; + } + + ConstraintValidatorContextImpl createConstraintValidatorContextFor(ConstraintDescriptorImpl constraintDescriptor, PathImpl path); +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java new file mode 100644 index 0000000000..d3e4244f55 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java @@ -0,0 +1,139 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.validationcontext; + +import java.lang.reflect.Executable; + +import javax.validation.ConstraintValidatorFactory; +import javax.validation.TraversableResolver; + +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; +import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.metadata.BeanMetaDataManager; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; + +/** + * Builder for creating {@link AbstractValidationContext}s suited for the different kinds of validation. + * + * @author Gunnar Morling + * @author Marko Bekhta + */ +public class ValidationContextBuilder { + + private final BeanMetaDataManager beanMetaDataManager; + private final ConstraintValidatorManager constraintValidatorManager; + private final ConstraintValidatorFactory constraintValidatorFactory; + private final TraversableResolver traversableResolver; + private final HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext; + private final ValidatorScopedContext validatorScopedContext; + + public ValidationContextBuilder( + BeanMetaDataManager beanMetaDataManager, + ConstraintValidatorManager constraintValidatorManager, + ConstraintValidatorFactory constraintValidatorFactory, + ValidatorScopedContext validatorScopedContext, + TraversableResolver traversableResolver, + HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext) { + this.beanMetaDataManager = beanMetaDataManager; + this.constraintValidatorManager = constraintValidatorManager; + this.constraintValidatorFactory = constraintValidatorFactory; + this.traversableResolver = traversableResolver; + this.constraintValidatorInitializationContext = constraintValidatorInitializationContext; + this.validatorScopedContext = validatorScopedContext; + } + + public ValidationContext forValidate(T rootBean) { + @SuppressWarnings("unchecked") + Class rootBeanClass = (Class) rootBean.getClass(); + return new BeanValidationContext<>( + constraintValidatorManager, + constraintValidatorFactory, + validatorScopedContext, + traversableResolver, + constraintValidatorInitializationContext, + rootBean, + rootBeanClass, + beanMetaDataManager.getBeanMetaData( rootBeanClass ) + ); + } + + public ValidationContext forValidateProperty(T rootBean, PathImpl propertyPath) { + @SuppressWarnings("unchecked") + Class rootBeanClass = (Class) rootBean.getClass(); + return new PropertyValidationContext<>( + constraintValidatorManager, + constraintValidatorFactory, + validatorScopedContext, + traversableResolver, + constraintValidatorInitializationContext, + rootBean, + rootBeanClass, + beanMetaDataManager.getBeanMetaData( rootBeanClass ), + propertyPath.getLeafNode().getName() + ); + } + + public ValidationContext forValidateValue(Class rootBeanClass, PathImpl propertyPath) { + return new PropertyValidationContext<>( + constraintValidatorManager, + constraintValidatorFactory, + validatorScopedContext, + traversableResolver, + constraintValidatorInitializationContext, + null, //root bean + rootBeanClass, + beanMetaDataManager.getBeanMetaData( rootBeanClass ), + propertyPath.getLeafNode().getName() + ); + } + + public ExecutableValidationContext forValidateParameters( + T rootBean, + Executable executable, + Object[] executableParameters) { + @SuppressWarnings("unchecked") + Class rootBeanClass = rootBean != null ? (Class) rootBean.getClass() : (Class) executable.getDeclaringClass(); + BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); + + return new ParameterExecutableValidationContext<>( + constraintValidatorManager, + constraintValidatorFactory, + validatorScopedContext, + traversableResolver, + constraintValidatorInitializationContext, + rootBean, + rootBeanClass, + rootBeanMetaData, + executable, + rootBeanMetaData.getMetaDataFor( executable ), + executableParameters + ); + } + + public ExecutableValidationContext forValidateReturnValue( + T rootBean, + Executable executable, + Object executableReturnValue) { + @SuppressWarnings("unchecked") + Class rootBeanClass = rootBean != null ? (Class) rootBean.getClass() : (Class) executable.getDeclaringClass(); + BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); + return new ReturnValueExecutableValidationContext<>( + constraintValidatorManager, + constraintValidatorFactory, + validatorScopedContext, + traversableResolver, + constraintValidatorInitializationContext, + rootBean, + rootBeanClass, + beanMetaDataManager.getBeanMetaData( rootBeanClass ), + executable, + rootBeanMetaData.getMetaDataFor( executable ), + executableReturnValue + ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidatorScopedContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidatorScopedContext.java new file mode 100644 index 0000000000..b4c6c8c9c5 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidatorScopedContext.java @@ -0,0 +1,110 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.validationcontext; + +import java.time.Duration; + +import javax.validation.ClockProvider; +import javax.validation.MessageInterpolator; +import javax.validation.Validator; + +import org.hibernate.validator.internal.engine.ValidatorFactoryImpl; +import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; +import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; + +/** + * Context object storing the {@link Validator} level helper and configuration properties. + *

+ * There should be only one per {@code Validator} instance. + */ +public class ValidatorScopedContext { + + /** + * The message interpolator. + */ + private final MessageInterpolator messageInterpolator; + + /** + * The parameter name provider. + */ + private final ExecutableParameterNameProvider parameterNameProvider; + + /** + * Provider for the current time when validating {@code @Future} or {@code @Past} + */ + private final ClockProvider clockProvider; + + /** + * Defines the temporal validation tolerance i.e. the allowed margin of error when comparing date/time in temporal + * constraints. + */ + private final Duration temporalValidationTolerance; + + /** + * Used to get the {@code ScriptEvaluatorFactory} when validating {@code @ScriptAssert} and + * {@code @ParameterScriptAssert} constraints. + */ + private final ScriptEvaluatorFactory scriptEvaluatorFactory; + + /** + * Hibernate Validator specific flag to abort validation on first constraint violation. + */ + private final boolean failFast; + + /** + * Hibernate Validator specific flag to disable the {@code TraversableResolver} result cache. + */ + private final boolean traversableResolverResultCacheEnabled; + + /** + * Hibernate Validator specific payload passed to the constraint validators. + */ + private final Object constraintValidatorPayload; + + public ValidatorScopedContext(ValidatorFactoryImpl.ValidatorFactoryScopedContext validatorFactoryScopedContext) { + this.messageInterpolator = validatorFactoryScopedContext.getMessageInterpolator(); + this.parameterNameProvider = validatorFactoryScopedContext.getParameterNameProvider(); + this.clockProvider = validatorFactoryScopedContext.getClockProvider(); + this.temporalValidationTolerance = validatorFactoryScopedContext.getTemporalValidationTolerance(); + this.scriptEvaluatorFactory = validatorFactoryScopedContext.getScriptEvaluatorFactory(); + this.failFast = validatorFactoryScopedContext.isFailFast(); + this.traversableResolverResultCacheEnabled = validatorFactoryScopedContext.isTraversableResolverResultCacheEnabled(); + this.constraintValidatorPayload = validatorFactoryScopedContext.getConstraintValidatorPayload(); + } + + public MessageInterpolator getMessageInterpolator() { + return this.messageInterpolator; + } + + public ExecutableParameterNameProvider getParameterNameProvider() { + return this.parameterNameProvider; + } + + public ClockProvider getClockProvider() { + return this.clockProvider; + } + + public Duration getTemporalValidationTolerance() { + return this.temporalValidationTolerance; + } + + public ScriptEvaluatorFactory getScriptEvaluatorFactory() { + return this.scriptEvaluatorFactory; + } + + public boolean isFailFast() { + return this.failFast; + } + + public boolean isTraversableResolverResultCacheEnabled() { + return this.traversableResolverResultCacheEnabled; + } + + public Object getConstraintValidatorPayload() { + return this.constraintValidatorPayload; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/package-info.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/package-info.java new file mode 100644 index 0000000000..dbf3047e80 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/package-info.java @@ -0,0 +1,10 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +/** + * Contains various implementation of validation contexts and supporting classes. + */ +package org.hibernate.validator.internal.engine.validationcontext; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java index 48143f07a5..a08f40a6b9 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java @@ -16,9 +16,9 @@ import javax.validation.valueextraction.ValueExtractor; -import org.hibernate.validator.internal.engine.ValidationContext; import org.hibernate.validator.internal.engine.ValueContext; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree; +import org.hibernate.validator.internal.engine.validationcontext.ValidationContext; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorDescriptor; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorHelper; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; From 2e062647875d510ce9340753316201323991c65b Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Wed, 25 Apr 2018 21:37:55 +0200 Subject: [PATCH 028/393] HV-1526 Split ValidationContext into two parts As the methods used in ConstraintTree could be potentially reused for other kinds of validation contexts e.g. property holder contexts that won't have bean metadata related methods, we can separate these concerns and split the interface into two. --- .../internal/engine/ValidatorImpl.java | 52 ++++++++--------- .../ComposingConstraintTree.java | 9 ++- .../constraintvalidation/ConstraintTree.java | 6 +- .../SimpleConstraintTree.java | 2 +- .../AbstractValidationContext.java | 2 +- .../BaseBeanValidationContext.java | 58 +++++++++++++++++++ .../ExecutableValidationContext.java | 4 +- .../validationcontext/ValidationContext.java | 39 ++++--------- .../ValidationContextBuilder.java | 6 +- 9 files changed, 108 insertions(+), 70 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BaseBeanValidationContext.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index 82ca24e750..b41b6ae78e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -45,8 +45,8 @@ import org.hibernate.validator.internal.engine.path.NodeImpl; import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.engine.resolver.TraversableResolvers; +import org.hibernate.validator.internal.engine.validationcontext.BaseBeanValidationContext; import org.hibernate.validator.internal.engine.validationcontext.ExecutableValidationContext; -import org.hibernate.validator.internal.engine.validationcontext.ValidationContext; import org.hibernate.validator.internal.engine.validationcontext.ValidationContextBuilder; import org.hibernate.validator.internal.engine.validationcontext.ValidatorScopedContext; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorDescriptor; @@ -149,7 +149,7 @@ public final Set> validate(T object, Class... grou Contracts.assertNotNull( object, MESSAGES.validatedObjectMustNotBeNull() ); sanityCheckGroups( groups ); - ValidationContext validationContext = getValidationContextBuilder().forValidate( object ); + BaseBeanValidationContext validationContext = getValidationContextBuilder().forValidate( object ); if ( !validationContext.getRootBeanMetaData().hasConstraints() ) { return Collections.emptySet(); @@ -173,7 +173,7 @@ public final Set> validateProperty(T object, String p sanityCheckGroups( groups ); PathImpl propertyPath = PathImpl.createPathFromString( propertyName ); - ValidationContext validationContext = getValidationContextBuilder().forValidateProperty( object, propertyPath ); + BaseBeanValidationContext validationContext = getValidationContextBuilder().forValidateProperty( object, propertyPath ); if ( !validationContext.getRootBeanMetaData().hasConstraints() ) { return Collections.emptySet(); @@ -197,7 +197,7 @@ public final Set> validateValue(Class beanType, St sanityCheckGroups( groups ); PathImpl propertyPath = PathImpl.createPathFromString( propertyName ); - ValidationContext validationContext = getValidationContextBuilder().forValidateValue( beanType, propertyPath ); + BaseBeanValidationContext validationContext = getValidationContextBuilder().forValidateValue( beanType, propertyPath ); if ( !validationContext.getRootBeanMetaData().hasConstraints() ) { return Collections.emptySet(); @@ -357,7 +357,7 @@ private ValidationOrder determineGroupValidationOrder(Class[] groups) { * * @return Set of constraint violations or the empty set if there were no violations. */ - private Set> validateInContext(ValidationContext validationContext, ValueContext valueContext, + private Set> validateInContext(BaseBeanValidationContext validationContext, ValueContext valueContext, ValidationOrder validationOrder) { if ( valueContext.getCurrentBean() == null ) { return Collections.emptySet(); @@ -417,7 +417,7 @@ private Set> validateInContext(ValidationContext validationContext, ValueContext valueContext) { + private void validateConstraintsForCurrentGroup(BaseBeanValidationContext validationContext, ValueContext valueContext) { // we are not validating the default group there is nothing special to consider. If we are validating the default // group sequence we have to consider that a class in the hierarchy could redefine the default group sequence. if ( !valueContext.validatingDefault() ) { @@ -428,7 +428,7 @@ private void validateConstraintsForCurrentGroup(ValidationContext validationC } } - private void validateConstraintsForDefaultGroup(ValidationContext validationContext, ValueContext valueContext) { + private void validateConstraintsForDefaultGroup(BaseBeanValidationContext validationContext, ValueContext valueContext) { final BeanMetaData beanMetaData = valueContext.getCurrentBeanMetaData(); final Map, Class> validatedInterfaces = new HashMap<>(); @@ -472,7 +472,7 @@ private void validateConstraintsForDefaultGroup(ValidationContext validat } } - private boolean validateConstraintsForSingleDefaultGroupElement(ValidationContext validationContext, ValueContext valueContext, final Map, Class> validatedInterfaces, + private boolean validateConstraintsForSingleDefaultGroupElement(BaseBeanValidationContext validationContext, ValueContext valueContext, final Map, Class> validatedInterfaces, Class clazz, Set> metaConstraints, Group defaultSequenceMember) { boolean validationSuccessful = true; @@ -500,12 +500,12 @@ private boolean validateConstraintsForSingleDefaultGroupElement(ValidationCo return validationSuccessful; } - private void validateConstraintsForNonDefaultGroup(ValidationContext validationContext, ValueContext valueContext) { + private void validateConstraintsForNonDefaultGroup(BaseBeanValidationContext validationContext, ValueContext valueContext) { validateMetaConstraints( validationContext, valueContext, valueContext.getCurrentBean(), valueContext.getCurrentBeanMetaData().getMetaConstraints() ); validationContext.markCurrentBeanAsProcessed( valueContext ); } - private void validateMetaConstraints(ValidationContext validationContext, ValueContext valueContext, Object parent, + private void validateMetaConstraints(BaseBeanValidationContext validationContext, ValueContext valueContext, Object parent, Iterable> constraints) { for ( MetaConstraint metaConstraint : constraints ) { @@ -516,7 +516,7 @@ private void validateMetaConstraints(ValidationContext validationContext, Val } } - private boolean validateMetaConstraint(ValidationContext validationContext, ValueContext valueContext, Object parent, MetaConstraint metaConstraint) { + private boolean validateMetaConstraint(BaseBeanValidationContext validationContext, ValueContext valueContext, Object parent, MetaConstraint metaConstraint) { ValueContext.ValueState originalValueState = valueContext.getCurrentValueState(); valueContext.appendNode( metaConstraint.getLocation() ); boolean success = true; @@ -545,7 +545,7 @@ private boolean validateMetaConstraint(ValidationContext validationContext, V * @param validationContext The execution context * @param valueContext Collected information for single validation */ - private void validateCascadedConstraints(ValidationContext validationContext, ValueContext valueContext) { + private void validateCascadedConstraints(BaseBeanValidationContext validationContext, ValueContext valueContext) { Validatable validatable = valueContext.getCurrentValidatable(); ValueContext.ValueState originalValueState = valueContext.getCurrentValueState(); @@ -582,7 +582,7 @@ private void validateCascadedConstraints(ValidationContext validationContext, } } - private void validateCascadedAnnotatedObjectForCurrentGroup(Object value, ValidationContext validationContext, ValueContext valueContext, + private void validateCascadedAnnotatedObjectForCurrentGroup(Object value, BaseBeanValidationContext validationContext, ValueContext valueContext, CascadingMetaData cascadingMetaData) { if ( validationContext.isBeanAlreadyValidated( value, valueContext.getCurrentGroup(), valueContext.getPropertyPath() ) || shouldFailFast( validationContext ) ) { @@ -602,7 +602,7 @@ private void validateCascadedAnnotatedObjectForCurrentGroup(Object value, Valida validateInContext( validationContext, cascadedValueContext, validationOrder ); } - private void validateCascadedContainerElementsForCurrentGroup(Object value, ValidationContext validationContext, ValueContext valueContext, + private void validateCascadedContainerElementsForCurrentGroup(Object value, BaseBeanValidationContext validationContext, ValueContext valueContext, List containerElementTypesCascadingMetaData) { for ( ContainerCascadingMetaData cascadingMetaData : containerElementTypesCascadingMetaData ) { if ( !cascadingMetaData.isMarkedForCascadingOnAnnotatedObjectOrContainerElements() ) { @@ -627,11 +627,11 @@ private void validateCascadedContainerElementsForCurrentGroup(Object value, Vali private class CascadingValueReceiver implements ValueExtractor.ValueReceiver { - private final ValidationContext validationContext; + private final BaseBeanValidationContext validationContext; private final ValueContext valueContext; private final ContainerCascadingMetaData cascadingMetaData; - public CascadingValueReceiver(ValidationContext validationContext, ValueContext valueContext, ContainerCascadingMetaData cascadingMetaData) { + public CascadingValueReceiver(BaseBeanValidationContext validationContext, ValueContext valueContext, ContainerCascadingMetaData cascadingMetaData) { this.validationContext = validationContext; this.valueContext = valueContext; this.cascadingMetaData = cascadingMetaData; @@ -702,7 +702,7 @@ private void doValidate(Object value, String nodeName) { } } - private void validateCascadedContainerElementsInContext(Object value, ValidationContext validationContext, ValueContext valueContext, + private void validateCascadedContainerElementsInContext(Object value, BaseBeanValidationContext validationContext, ValueContext valueContext, ContainerCascadingMetaData cascadingMetaData, ValidationOrder validationOrder) { Iterator groupIterator = validationOrder.getGroupIterator(); while ( groupIterator.hasNext() ) { @@ -760,7 +760,7 @@ private ValueContext buildNewLocalExecutionContext(ValueContext return newValueContext; } - private Set> validateValueInContext(ValidationContext validationContext, Object value, PathImpl propertyPath, + private Set> validateValueInContext(BaseBeanValidationContext validationContext, Object value, PathImpl propertyPath, ValidationOrder validationOrder) { ValueContext valueContext = getValueContextForValueValidation( validationContext.getRootBeanClass(), propertyPath ); valueContext.setCurrentValidatedValue( value ); @@ -1080,7 +1080,7 @@ private void validateReturnValueInContext(ExecutableValidationContext } //TODO GM: if possible integrate with validateParameterForGroup() - private void validateReturnValueForGroup(ValidationContext validationContext, ExecutableMetaData executableMetaData, T bean, Object value, + private void validateReturnValueForGroup(BaseBeanValidationContext validationContext, ExecutableMetaData executableMetaData, T bean, Object value, Group group) { Contracts.assertNotNull( executableMetaData, "executableMetaData may not be null" ); @@ -1118,7 +1118,7 @@ private void validateReturnValueForGroup(ValidationContext validationCont } } - private void validateReturnValueForSingleGroup(ValidationContext validationContext, ExecutableMetaData executableMetaData, T bean, Object value, Class oneGroup) { + private void validateReturnValueForSingleGroup(BaseBeanValidationContext validationContext, ExecutableMetaData executableMetaData, T bean, Object value, Class oneGroup) { // validate constraints at return value itself ValueContext valueContext = getExecutableValueContext( executableMetaData.getKind() == ElementKind.CONSTRUCTOR ? value : bean, @@ -1142,7 +1142,7 @@ private void validateReturnValueForSingleGroup(ValidationContext validati * @return Returns an instance of {@code ValueContext} which describes the local validation context associated to * the given property path. */ - private ValueContext getValueContextForPropertyValidation(ValidationContext validationContext, PathImpl propertyPath) { + private ValueContext getValueContextForPropertyValidation(BaseBeanValidationContext validationContext, PathImpl propertyPath) { Class clazz = validationContext.getRootBeanClass(); BeanMetaData beanMetaData = validationContext.getRootBeanMetaData(); Object value = validationContext.getRootBean(); @@ -1259,7 +1259,7 @@ private ValueContext getValueContextForValueValidation(Class rootBe return ValueContext.getLocalExecutionContext( validatorScopedContext.getParameterNameProvider(), clazz, beanMetaData, propertyPath ); } - private boolean isValidationRequired(ValidationContext validationContext, + private boolean isValidationRequired(BaseBeanValidationContext validationContext, ValueContext valueContext, MetaConstraint metaConstraint) { // check if this validation context is qualified to validate the current meta constraint. @@ -1287,7 +1287,7 @@ private boolean isValidationRequired(ValidationContext validationContext, ); } - private boolean isReachable(ValidationContext validationContext, Object traversableObject, PathImpl path, ElementType type) { + private boolean isReachable(BaseBeanValidationContext validationContext, Object traversableObject, PathImpl path, ElementType type) { if ( needToCallTraversableResolver( path, type ) ) { return true; } @@ -1318,7 +1318,7 @@ private boolean needToCallTraversableResolver(PathImpl path, ElementType type) { || isReturnValueValidation( path ); } - private boolean isCascadeRequired(ValidationContext validationContext, Object traversableObject, PathImpl path, ElementType type) { + private boolean isCascadeRequired(BaseBeanValidationContext validationContext, Object traversableObject, PathImpl path, ElementType type) { if ( needToCallTraversableResolver( path, type ) ) { return true; } @@ -1359,7 +1359,7 @@ private boolean isReturnValueValidation(PathImpl path) { return path.getLeafNode().getKind() == ElementKind.RETURN_VALUE; } - private boolean shouldFailFast(ValidationContext validationContext) { + private boolean shouldFailFast(BaseBeanValidationContext validationContext) { return validationContext.isFailFastModeEnabled() && !validationContext.getFailingConstraints().isEmpty(); } @@ -1371,7 +1371,7 @@ private PropertyMetaData getBeanPropertyMetaData(BeanMetaData beanMetaData, P return beanMetaData.getMetaDataFor( propertyNode.getName() ); } - private Object getCascadableValue(ValidationContext validationContext, Object object, Cascadable cascadable) { + private Object getCascadableValue(BaseBeanValidationContext validationContext, Object object, Cascadable cascadable) { return cascadable.getValue( object ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java index 06d8dd0cbb..3b01a1cf88 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java @@ -64,7 +64,7 @@ private ConstraintTree createConstraintTree(Constraint } @Override - protected void validateConstraints(ValidationContext validationContext, + protected void validateConstraints(ValidationContext validationContext, ValueContext valueContext, Collection violatedConstraintValidatorContexts) { CompositionResult compositionResult = validateComposingConstraints( @@ -119,7 +119,7 @@ protected void validateConstraints(ValidationContext validationContext, } } - private boolean mainConstraintNeedsEvaluation(ValidationContext validationContext, + private boolean mainConstraintNeedsEvaluation(ValidationContext validationContext, Collection violatedConstraintValidatorContexts) { // we are dealing with a composing constraint with no validator for the main constraint if ( !descriptor.getComposingConstraints().isEmpty() && descriptor.getMatchingConstraintValidatorDescriptors().isEmpty() ) { @@ -151,9 +151,8 @@ private boolean mainConstraintNeedsEvaluation(ValidationContext validatio * @param valueContext meta data for currently validated value * @param violatedConstraintValidatorContexts used to accumulate constraint validator contexts that cause constraint violations * @param localConstraintValidatorContext an optional of constraint violations of top level constraint - * */ - private void prepareFinalConstraintViolations(ValidationContext validationContext, + private void prepareFinalConstraintViolations(ValidationContext validationContext, ValueContext valueContext, Collection violatedConstraintValidatorContexts, Optional localConstraintValidatorContext) { @@ -196,7 +195,7 @@ private void prepareFinalConstraintViolations(ValidationContext validatio * * @return Returns an instance of {@code CompositionResult} relevant for boolean composition of constraints */ - private CompositionResult validateComposingConstraints(ValidationContext validationContext, + private CompositionResult validateComposingConstraints(ValidationContext validationContext, ValueContext valueContext, Collection violatedConstraintValidatorContexts) { CompositionResult compositionResult = new CompositionResult( true, false ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java index ac0b8002d3..295c3526b9 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java @@ -68,7 +68,7 @@ public static ConstraintTree of(ConstraintDescriptorIm } } - public final boolean validateConstraints(ValidationContext validationContext, ValueContext valueContext) { + public final boolean validateConstraints(ValidationContext validationContext, ValueContext valueContext) { List violatedConstraintValidatorContexts = new ArrayList( 5 ); validateConstraints( validationContext, valueContext, violatedConstraintValidatorContexts ); if ( !violatedConstraintValidatorContexts.isEmpty() ) { @@ -84,7 +84,7 @@ public final boolean validateConstraints(ValidationContext validationCont return true; } - protected abstract void validateConstraints(ValidationContext executionContext, ValueContext valueContext, Collection violatedConstraintValidatorContexts); + protected abstract void validateConstraints(ValidationContext validationContext, ValueContext valueContext, Collection violatedConstraintValidatorContexts); public final ConstraintDescriptorImpl getDescriptor() { return descriptor; @@ -115,7 +115,7 @@ private ValidationException getExceptionForNullValidator(Type validatedValueType } } - protected final ConstraintValidator getInitializedConstraintValidator(ValidationContext validationContext, ValueContext valueContext) { + protected final ConstraintValidator getInitializedConstraintValidator(ValidationContext validationContext, ValueContext valueContext) { ConstraintValidator validator; if ( validationContext.getConstraintValidatorFactory() == validationContext.getConstraintValidatorManager().getDefaultConstraintValidatorFactory() diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java index 331cb90a38..cfbbeb0657 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java @@ -38,7 +38,7 @@ public SimpleConstraintTree(ConstraintDescriptorImpl descriptor, Type validat } @Override - protected void validateConstraints(ValidationContext validationContext, + protected void validateConstraints(ValidationContext validationContext, ValueContext valueContext, Collection violatedConstraintValidatorContexts) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java index f804dc431c..5700eb9ec1 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java @@ -48,7 +48,7 @@ * @author Guillaume Smet * @author Marko Bekhta */ -abstract class AbstractValidationContext implements ValidationContext { +abstract class AbstractValidationContext implements BaseBeanValidationContext { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BaseBeanValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BaseBeanValidationContext.java new file mode 100644 index 0000000000..8428b05483 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BaseBeanValidationContext.java @@ -0,0 +1,58 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.validationcontext; + +import javax.validation.Path; +import javax.validation.TraversableResolver; +import javax.validation.Validator; + +import org.hibernate.validator.internal.engine.ValidatorImpl; +import org.hibernate.validator.internal.engine.ValueContext; +import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; +import org.hibernate.validator.internal.metadata.core.MetaConstraint; + +/** + * Interface that exposes contextual information required for a validation call related to a bean. + *

+ * Provides ability to collect failing constraints and gives access to resources like constraint validator factory, + * traversable resolver, etc. + * + * @author Hardy Ferentschik + * @author Emmanuel Bernard + * @author Gunnar Morling + * @author Guillaume Smet + */ +public interface BaseBeanValidationContext extends ValidationContext { + + T getRootBean(); + + Class getRootBeanClass(); + + BeanMetaData getRootBeanMetaData(); + + TraversableResolver getTraversableResolver(); + + boolean isBeanAlreadyValidated(Object value, Class group, PathImpl path); + + void markCurrentBeanAsProcessed(ValueContext valueContext); + + boolean hasMetaConstraintBeenProcessed(Object bean, Path path, MetaConstraint metaConstraint); + + void markConstraintProcessed(Object bean, Path path, MetaConstraint metaConstraint); + + /** + * @return {@code true} if current validation context can and should process passed meta constraint. Is used in + * {@link ValidatorImpl} to check if validation is required in case of calls to + * {@link Validator#validateValue(Class, String, Object, Class[])} or + * {@link Validator#validateProperty(Object, String, Class[])}. In these cases, as we iterate through all meta + * constraints of the bean, we expect those that are not defined for the validated property. + */ + default boolean appliesTo(MetaConstraint metaConstraint) { + return true; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ExecutableValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ExecutableValidationContext.java index 821ab9a567..aaf30447b7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ExecutableValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ExecutableValidationContext.java @@ -12,11 +12,11 @@ import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; /** - * Extension of {@link ValidationContext} for executable validation. + * Extension of {@link BaseBeanValidationContext} for executable validation. * * @author Marko Bekhta */ -public interface ExecutableValidationContext extends ValidationContext { +public interface ExecutableValidationContext extends BaseBeanValidationContext { Executable getExecutable(); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContext.java index afa575aacf..f13e148f17 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContext.java @@ -8,43 +8,36 @@ import java.util.Set; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; import javax.validation.ConstraintValidatorFactory; import javax.validation.ConstraintViolation; -import javax.validation.Path; -import javax.validation.TraversableResolver; import javax.validation.metadata.ConstraintDescriptor; import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; import org.hibernate.validator.internal.engine.ValueContext; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext; import org.hibernate.validator.internal.engine.path.PathImpl; -import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; -import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; /** - * Interface that exposes contextual information required for a validation call. + * Context object interface keeping track of all required data for operations inside {@link ConstraintTree} + * and its subclasses. *

- * Provides ability to collect failing constraints and gives access to resources like - * constraint validator factory, traversable resolver, etc. + * Allows to collect all failing constraints, creates {@link ConstraintValidatorContext}s based on the constraint + * descriptors, and exposes other resources needed to initialize a new {@link ConstraintValidator}. * * @author Hardy Ferentschik * @author Emmanuel Bernard * @author Gunnar Morling * @author Guillaume Smet + * @author Marko Bekhta */ public interface ValidationContext { - T getRootBean(); - - Class getRootBeanClass(); - - BeanMetaData getRootBeanMetaData(); - - TraversableResolver getTraversableResolver(); - boolean isFailFastModeEnabled(); ConstraintValidatorManager getConstraintValidatorManager(); @@ -53,25 +46,13 @@ public interface ValidationContext { ConstraintValidatorFactory getConstraintValidatorFactory(); - boolean isBeanAlreadyValidated(Object value, Class group, PathImpl path); - - void markCurrentBeanAsProcessed(ValueContext valueContext); - - Set> getFailingConstraints(); - void addConstraintFailure( - ValueContext localContext, + ValueContext valueContext, ConstraintViolationCreationContext constraintViolationCreationContext, ConstraintDescriptor descriptor ); - boolean hasMetaConstraintBeenProcessed(Object bean, Path path, MetaConstraint metaConstraint); - - void markConstraintProcessed(Object bean, Path path, MetaConstraint metaConstraint); - - default boolean appliesTo(MetaConstraint metaConstraint) { - return true; - } + Set> getFailingConstraints(); ConstraintValidatorContextImpl createConstraintValidatorContextFor(ConstraintDescriptorImpl constraintDescriptor, PathImpl path); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java index d3e4244f55..8db1873385 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java @@ -47,7 +47,7 @@ public ValidationContextBuilder( this.validatorScopedContext = validatorScopedContext; } - public ValidationContext forValidate(T rootBean) { + public BaseBeanValidationContext forValidate(T rootBean) { @SuppressWarnings("unchecked") Class rootBeanClass = (Class) rootBean.getClass(); return new BeanValidationContext<>( @@ -62,7 +62,7 @@ public ValidationContext forValidate(T rootBean) { ); } - public ValidationContext forValidateProperty(T rootBean, PathImpl propertyPath) { + public BaseBeanValidationContext forValidateProperty(T rootBean, PathImpl propertyPath) { @SuppressWarnings("unchecked") Class rootBeanClass = (Class) rootBean.getClass(); return new PropertyValidationContext<>( @@ -78,7 +78,7 @@ public ValidationContext forValidateProperty(T rootBean, PathImpl propert ); } - public ValidationContext forValidateValue(Class rootBeanClass, PathImpl propertyPath) { + public BaseBeanValidationContext forValidateValue(Class rootBeanClass, PathImpl propertyPath) { return new PropertyValidationContext<>( constraintValidatorManager, constraintValidatorFactory, From ebcd2cd214dc396b285e342006387beb725c5a3f Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Wed, 9 May 2018 16:06:07 +0200 Subject: [PATCH 029/393] HV-1614 Add check if the container element context exists when adding a nested type argument constraints programmatically Rather than simply put a new context into the map we need to check if there's one already created by any previous calls. This might happen when someone wants to add constraints for different type arguments of a nested container. --- ...dableConstraintMappingContextImplBase.java | 13 ++++++---- ...erElementConstraintMappingContextImpl.java | 18 +++++++------ ...ntainerElementConstraintsForFieldTest.java | 25 +++++++++++++++++++ 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/CascadableConstraintMappingContextImplBase.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/CascadableConstraintMappingContextImplBase.java index 323ee74c7a..a8f40b8944 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/CascadableConstraintMappingContextImplBase.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/CascadableConstraintMappingContextImplBase.java @@ -130,11 +130,14 @@ public ContainerElementConstraintMappingContext containerElement(ContainerElemen ); } - ContainerElementConstraintMappingContextImpl containerElementContext = new ContainerElementConstraintMappingContextImpl( - typeContext, parent, location, index - ); - - containerElementContexts.put( index, containerElementContext ); + // As we already checked that the specific path was not yet configured we should not worry about returning the same context here, + // as it means that there are some nested indexes which make a difference, And at the end a new context will be returned by call + // to containerElementContext#nestedContainerElement(). + ContainerElementConstraintMappingContextImpl containerElementContext = containerElementContexts.get( index ); + if ( containerElementContext == null ) { + containerElementContext = new ContainerElementConstraintMappingContextImpl( typeContext, parent, location, index ); + containerElementContexts.put( index, containerElementContext ); + } if ( nestedIndexes.length > 0 ) { return containerElementContext.nestedContainerElement( nestedIndexes ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java index ca7d0f7514..cf33e40d86 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java @@ -168,14 +168,16 @@ ContainerElementConstraintMappingContext nestedContainerElement(int[] nestedInde throw LOG.getTypeIsNotAParameterizedNorArrayTypeException( configuredType ); } - ContainerElementConstraintMappingContextImpl nestedContext = new ContainerElementConstraintMappingContextImpl( - typeContext, - parentContainerElementTarget, - ConstraintLocation.forTypeArgument( parentLocation, typeParameter, getContainerElementType() ), - nestedIndexes[0] - ); - - nestedContainerElementContexts.put( nestedIndexes[0], nestedContext ); + ContainerElementConstraintMappingContextImpl nestedContext = nestedContainerElementContexts.get( nestedIndexes[0] ); + if ( nestedContext == null ) { + nestedContext = new ContainerElementConstraintMappingContextImpl( + typeContext, + parentContainerElementTarget, + ConstraintLocation.forTypeArgument( parentLocation, typeParameter, getContainerElementType() ), + nestedIndexes[0] + ); + nestedContainerElementContexts.put( nestedIndexes[0], nestedContext ); + } if ( nestedIndexes.length > 1 ) { return nestedContext.nestedContainerElement( Arrays.copyOfRange( nestedIndexes, 1, nestedIndexes.length ) ); diff --git a/engine/src/test/java/org/hibernate/validator/test/cfg/ProgrammaticContainerElementConstraintsForFieldTest.java b/engine/src/test/java/org/hibernate/validator/test/cfg/ProgrammaticContainerElementConstraintsForFieldTest.java index cb9aa67121..60a8953a37 100644 --- a/engine/src/test/java/org/hibernate/validator/test/cfg/ProgrammaticContainerElementConstraintsForFieldTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/cfg/ProgrammaticContainerElementConstraintsForFieldTest.java @@ -30,9 +30,11 @@ import org.hibernate.validator.HibernateValidator; import org.hibernate.validator.HibernateValidatorConfiguration; import org.hibernate.validator.cfg.ConstraintMapping; +import org.hibernate.validator.cfg.defs.LengthDef; import org.hibernate.validator.cfg.defs.MinDef; import org.hibernate.validator.cfg.defs.NotNullDef; import org.hibernate.validator.cfg.defs.SizeDef; +import org.hibernate.validator.constraints.Length; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.testutil.TestForIssue; import org.testng.annotations.BeforeMethod; @@ -142,6 +144,29 @@ public void canDeclareContainerElementCascadesForFieldProgrammatically() { ); } + @Test + @TestForIssue(jiraKey = "HV-1614") + public void canDeclareDeeplyNestedContainerElementConstraintsOnMultipleDifferentTypeArgumentsForFieldProgrammatically() { + ConstraintMapping newMapping = config.createConstraintMapping(); + newMapping + .type( FishTank.class ) + .property( "tagsOfFishOfTheMonth", FIELD ) + .containerElementType( 0, 0 ) + .constraint( new LengthDef().min( 10 ).max( 20 ) ) + .containerElementType( 0, 1, 0 ) + .constraint( new NotNullDef() ); + + config.addMapping( newMapping ); + Validator validator = config.buildValidatorFactory().getValidator(); + + Set> violations = validator.validate( new FishTank() ); + + assertThat( violations ).containsOnlyViolations( + violationOf( NotNull.class ).withMessage( "must not be null" ), + violationOf( Length.class ).withMessage( "length must be between 10 and 20" ) + ); + } + // HV-1428 Container element support is disabled for arrays @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000226:.*") @TestForIssue(jiraKey = "HV-1239") From b7d48c3fe6ba4805e7990908f0a4ff9d1b36cf67 Mon Sep 17 00:00:00 2001 From: Rob Dickinson Date: Wed, 9 May 2018 09:13:30 +0100 Subject: [PATCH 030/393] HV-1534 Allow getter constraints to be specified for subclasses in XML configuration It was possible in Hibernate Validator 4.3 and got somehow broken during the 5 development cycle. It's not exactly something we would support nowadays but as some users were relying on it and it's not complicating the code, for now, we can try to support it, hoping it won't be in the way later. --- .../metadata/aggregated/PropertyMetaData.java | 17 +++++- .../metadata/location/ConstraintLocation.java | 23 +++++++- .../location/GetterConstraintLocation.java | 13 ++++- .../mapping/ConstrainedGetterStaxBuilder.java | 2 +- .../validator/test/internal/xml/Child.java | 19 +++++++ .../validator/test/internal/xml/Parent.java | 37 ++++++++++++ .../test/internal/xml/XmlMappingTest.java | 56 +++++++++++++++++++ .../test/internal/xml/hv-1534-mapping.xml | 28 ++++++++++ 8 files changed, 189 insertions(+), 6 deletions(-) create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/xml/Child.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/xml/Parent.java create mode 100644 engine/src/test/resources/org/hibernate/validator/test/internal/xml/hv-1534-mapping.xml diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java index c1731a8678..df31d488eb 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java @@ -33,6 +33,7 @@ import org.hibernate.validator.internal.metadata.descriptor.PropertyDescriptorImpl; import org.hibernate.validator.internal.metadata.facets.Cascadable; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.location.GetterConstraintLocation; import org.hibernate.validator.internal.metadata.location.TypeArgumentConstraintLocation; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; @@ -262,7 +263,13 @@ private MetaConstraint withGetterLocation(ConstraintLocation getterConstraint // fast track if it's a regular constraint if ( !(constraint.getLocation() instanceof TypeArgumentConstraintLocation) ) { - converted = getterConstraintLocation; + // Change the constraint location to a GetterConstraintLocation if it is not already one + if ( constraint.getLocation() instanceof GetterConstraintLocation ) { + converted = constraint.getLocation(); + } + else { + converted = getterConstraintLocation; + } } else { Deque locationStack = new ArrayDeque<>(); @@ -283,7 +290,13 @@ private MetaConstraint withGetterLocation(ConstraintLocation getterConstraint // 2. beginning at the root, transform each location so it references the transformed delegate for ( ConstraintLocation location : locationStack ) { if ( !(location instanceof TypeArgumentConstraintLocation) ) { - converted = getterConstraintLocation; + // Change the constraint location to a GetterConstraintLocation if it is not already one + if ( location instanceof GetterConstraintLocation ) { + converted = location; + } + else { + converted = getterConstraintLocation; + } } else { converted = ConstraintLocation.forTypeArgument( diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java index 429d7d711d..1277f85051 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java @@ -43,8 +43,29 @@ static ConstraintLocation forField(Field field) { return new FieldConstraintLocation( field ); } + /** + * Create a new {@link GetterConstraintLocation} for the given getter method. + * + * @param getter The getter method being constrained + * @return A new GetterConstraintLocation + */ static ConstraintLocation forGetter(Method getter) { - return new GetterConstraintLocation( getter ); + return new GetterConstraintLocation( getter.getDeclaringClass(), getter ); + } + + /** + * Create a new {@link GetterConstraintLocation} for the given declaring class and getter method. + *

+ * This provides an alternative to {@link ConstraintLocation#forGetter(Method)} where the given declaring class is usually a sub-class of the + * actual class on which the getter method is declared. This is provided to support XML mapping configurations used to specify constraints on + * subclasses for inherited getter methods. + * + * @param declaringClass The class on which the constraint is defined. + * @param getter The getter method being constrained. + * @return A new GetterConstraintLocation + */ + static ConstraintLocation forGetter(Class declaringClass, Method getter ) { + return new GetterConstraintLocation( declaringClass, getter ); } static ConstraintLocation forTypeArgument(ConstraintLocation delegate, TypeVariable typeParameter, Type typeOfAnnotatedElement) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java index 0e59e27cf4..3e3aa8fe6a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java @@ -44,17 +44,26 @@ public class GetterConstraintLocation implements ConstraintLocation { */ private final Type typeForValidatorResolution; + /** + * The class of the method for which the constraint was defined. + *

+ * It is usually the same as the declaring class of the method itself, except in the XML case when a user could + * declare a constraint for a specific subclass. + */ + private final Class declaringClass; + - GetterConstraintLocation(Method method) { + GetterConstraintLocation( Class declaringClass, Method method ) { this.method = method; this.accessibleMethod = getAccessible( method ); this.propertyName = ReflectionHelper.getPropertyName( method ); this.typeForValidatorResolution = ReflectionHelper.boxedType( ReflectionHelper.typeOf( method ) ); + this.declaringClass = declaringClass; } @Override public Class getDeclaringClass() { - return method.getDeclaringClass(); + return declaringClass; } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java index 92ee72d0de..ba1b607ffd 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java @@ -71,7 +71,7 @@ ConstrainedExecutable build(Class beanClass, List alreadyProcessedGet alreadyProcessedGetterNames.add( mainAttributeValue ); } Method getter = findGetter( beanClass, mainAttributeValue ); - ConstraintLocation constraintLocation = ConstraintLocation.forGetter( getter ); + ConstraintLocation constraintLocation = ConstraintLocation.forGetter( beanClass, getter ); Set> metaConstraints = constraintTypeStaxBuilders.stream() .map( builder -> builder.build( constraintLocation, java.lang.annotation.ElementType.METHOD, null ) ) diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/xml/Child.java b/engine/src/test/java/org/hibernate/validator/test/internal/xml/Child.java new file mode 100644 index 0000000000..9d12cbfd83 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/xml/Child.java @@ -0,0 +1,19 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.xml; + +/** + * Test class for HV-1534. + * + * @author Rob Dickinson + */ +public class Child extends Parent { + + public Child( String parentAttribute ) { + super( parentAttribute ); + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/xml/Parent.java b/engine/src/test/java/org/hibernate/validator/test/internal/xml/Parent.java new file mode 100644 index 0000000000..6b662e1286 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/xml/Parent.java @@ -0,0 +1,37 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.xml; + +import java.util.ArrayList; +import java.util.List; + +/** + * Test class for HV-1534. + * + * @author Rob Dickinson + */ +public class Parent { + + private String parentAttribute = null; + private List parentListAttribute = new ArrayList<>(); + + public Parent( String parentAttribute ) { + this.parentAttribute = parentAttribute; + } + + public final String getParentAttribute() { + return parentAttribute; + } + + public void addToListAttribute(String element) { + parentListAttribute.add( element ); + } + + public final List getParentListAttribute() { + return parentListAttribute; + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/xml/XmlMappingTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/xml/XmlMappingTest.java index f62ee1f70b..f70307f3b5 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/xml/XmlMappingTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/xml/XmlMappingTest.java @@ -9,6 +9,7 @@ import static org.hibernate.validator.internal.util.CollectionHelper.asSet; import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertNoViolations; import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.pathWith; import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; import static org.testng.Assert.assertEquals; @@ -376,4 +377,59 @@ public void testCascadedValidation() { violationOf( NotNull.class ) ); } + + @Test + @TestForIssue(jiraKey = "HV-1534") + public void test_constraint_is_applied_to_inherited_getter() { + final Configuration configuration = ValidatorUtil.getConfiguration(); + configuration.addMapping( XmlMappingTest.class.getResourceAsStream( "hv-1534-mapping.xml" ) ); + + final ValidatorFactory validatorFactory = configuration.buildValidatorFactory(); + final Validator validator = validatorFactory.getValidator(); + + Parent parent = new Parent( null ); + + Set> parentViolations = validator.validate( parent ); + + assertNoViolations( parentViolations ); + + Child child = new Child( null ); + + Set> childViolations = validator.validate( child ); + + assertThat( childViolations ).containsOnlyViolations( + violationOf( NotNull.class ).withProperty( "parentAttribute" ) + ); + } + + @Test + @TestForIssue(jiraKey = "HV-1534") + public void test_constraint_is_applied_to_type_argument_of_inherited_getter() { + final Configuration configuration = ValidatorUtil.getConfiguration(); + configuration.addMapping( XmlMappingTest.class.getResourceAsStream( "hv-1534-mapping.xml" ) ); + + final ValidatorFactory validatorFactory = configuration.buildValidatorFactory(); + final Validator validator = validatorFactory.getValidator(); + + Parent parent = new Parent( "someValue" ); + parent.addToListAttribute( null ); + + Set> parentViolations = validator.validate( parent ); + + assertNoViolations( parentViolations ); + + Child child = new Child( "someValue" ); + child.addToListAttribute( null ); + + Set> childViolations = validator.validate( child ); + + assertThat( childViolations ).containsOnlyViolations( + violationOf( NotNull.class ) + .withPropertyPath( + pathWith() + .property( "parentListAttribute" ) + .containerElement( "", true, null, 0, List.class, 0 ) ) + ); + } + } diff --git a/engine/src/test/resources/org/hibernate/validator/test/internal/xml/hv-1534-mapping.xml b/engine/src/test/resources/org/hibernate/validator/test/internal/xml/hv-1534-mapping.xml new file mode 100644 index 0000000000..58fac1a395 --- /dev/null +++ b/engine/src/test/resources/org/hibernate/validator/test/internal/xml/hv-1534-mapping.xml @@ -0,0 +1,28 @@ + + + + + org.hibernate.validator.internal.xml + + + + + + + + + + + + + From 8c5ce4e8956ff8047b221f2a1eaa26e3d28425c3 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 10 May 2018 14:23:29 +0200 Subject: [PATCH 031/393] HV-1534 Add Rob Dickinson to copyright.txt --- copyright.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/copyright.txt b/copyright.txt index 3c78287f8e..a386c100bc 100644 --- a/copyright.txt +++ b/copyright.txt @@ -51,6 +51,7 @@ Nicola Ferraro Nicolas François Paolo Perrotta Pete Muir +Rob Dickinson Sanne Grinovero Sebastian Bayerl Shahram Goodarzi From 830e68c8f49b886f2341c174ad015f62aee8a747 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Tue, 15 May 2018 10:46:07 +0000 Subject: [PATCH 032/393] [Jenkins release job] README.md updated by release build 6.0.10.Final --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b3ce5be777..e7a515586e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hibernate Validator -*Version: 6.0.9.Final - 27-03-2018* +*Version: 6.0.10.Final - 15-05-2018* ## What is it? @@ -35,7 +35,7 @@ Logging will delegate any log requests to that provider. org.hibernate.validator hibernate-validator - 6.0.9.Final + 6.0.10.Final You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. @@ -54,7 +54,7 @@ extension by adding the following dependency: org.hibernate.validator hibernate-validator-cdi - 6.0.9.Final + 6.0.10.Final * _hibernate-validator-annotation-processor-<version>.jar_ is an optional jar which can be integrated with your build From 37b6fa72b67d5346f14ea7b5f360353fa157df48 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Tue, 15 May 2018 10:46:08 +0000 Subject: [PATCH 033/393] [Jenkins release job] changelog.txt updated by release build 6.0.10.Final --- changelog.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/changelog.txt b/changelog.txt index 9693c913f7..ad70f7062e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,26 @@ Hibernate Validator Changelog ============================= +6.0.10.Final (15-05-2018) +------------------------- + +** Bug + * HV-1614 - engine - Unable to specify constraints at more than 1 nested parameter of a typed container + * HV-1609 - integration - CDI extension should not rely on @WithAnnotations filtering + * HV-1604 - engine - Initializing JPATraversableResolver fails with IllegalAccessException + * HV-1598 - engine - Fix the behavior of XML default-validated-executable-types + +** Improvement + * HV-1612 - translations - Add Dutch translation of the validation messages + * HV-1611 - translations - Be consistent in the case of the validation messages + * HV-1592 - engine - Make ConstraintValidator declaration stricter + * HV-1534 - engine - Allow getter constraints to be specified for subclasses in XML configuration + +** Task + * HV-1607 - build - Have the build work with JDK 10 + * HV-1606 - tck-runner - Update TCK to 2.0.3.Final + * HV-1605 - build - Update Surefire to 2.21.0 for JDK 10 support + 6.0.9.Final (27-03-2018) ------------------------- From 4dc1d2f4f33f200bc9d448ba849d525c75fff2c5 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Wed, 16 May 2018 13:40:53 +0100 Subject: [PATCH 034/393] HV-1615 Some typo fixes and improvements to the Dutch translation --- .../org/hibernate/validator/ValidationMessages_nl.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties index e2da1b36a1..dffd8c049d 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties @@ -1,5 +1,5 @@ javax.validation.constraints.AssertFalse.message = moet onwaar zijn -javax.validation.constraints.AssertTrue.message = moet waar zijn sein +javax.validation.constraints.AssertTrue.message = moet waar zijn javax.validation.constraints.DecimalMax.message = moet kleiner dan ${strict == false ? 'of gelijk aan ' : ''}{value} zijn javax.validation.constraints.DecimalMin.message = moet groter dan ${inclusive == true ? 'of gelijk aan ' : ''}{value} zijn javax.validation.constraints.Digits.message = numerieke waarde ligt buiten het toegestane bereik (<{integer} cijfers>,<{fraction} cijfers> verwacht) @@ -17,7 +17,7 @@ javax.validation.constraints.Null.message = moet null zijn javax.validation.constraints.Past.message = moet in het verleden zijn javax.validation.constraints.PastOrPresent.message = moet in het heden of in het verleden zijn javax.validation.constraints.Pattern.message = moet overeenkomen met "{regexp}" -javax.validation.constraints.Positive.message = moet gtoter dan 0 sein +javax.validation.constraints.Positive.message = moet groter dan 0 zijn javax.validation.constraints.PositiveOrZero.message = moet groter of gelijk zijn aan 0 javax.validation.constraints.Size.message = moet tussen {min} en {max} liggen From 3b2fbac82495778a8d7fbd6f20d1d88e3df1b55f Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 10 May 2018 20:34:18 +0200 Subject: [PATCH 035/393] HV-1484 Unify JPMS module names and OSGi bundle names --- cdi/pom.xml | 4 ++-- engine/pom.xml | 2 +- pom.xml | 3 --- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/cdi/pom.xml b/cdi/pom.xml index 02535a0199..12d2bb9ba8 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -166,8 +166,8 @@ maven-bundle-plugin - ${hibernate-validator-cdi.bundle-name} - ${hibernate-validator.bundle-name} + ${hibernate-validator-cdi.module-name} + ${hibernate-validator.module-name} javax.validation.*;version="[2.0,3.0)", javax.annotation.*;version="[1.2,2.0)", diff --git a/engine/pom.xml b/engine/pom.xml index fd6d26aa8b..8ab9fb8842 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -206,7 +206,7 @@ maven-bundle-plugin - ${hibernate-validator.bundle-name} + ${hibernate-validator.module-name} javax.persistence.*;version="[2.0.0,3.0.0)";resolution:=optional, javax.validation.*;version="[2.0.0,3.0.0)", diff --git a/pom.xml b/pom.xml index a33cea01d4..6bac0f59c3 100644 --- a/pom.xml +++ b/pom.xml @@ -101,9 +101,6 @@ org.hibernate.validator org.hibernate.validator.cdi - - org.hibernate.validator.hibernate-validator - org.hibernate.validator.hibernate-validator-cdi UTF-8 From 913d7f7c2383d3392da8aa139175bb5f834f0f91 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 6 Jun 2018 12:24:22 +0200 Subject: [PATCH 036/393] Fix a recurring typo in the javadoc --- .../validator/cfg/context/ConstraintDefinitionTarget.java | 2 +- .../org/hibernate/validator/cfg/context/ConstructorTarget.java | 2 +- .../hibernate/validator/cfg/context/CrossParameterTarget.java | 2 +- .../java/org/hibernate/validator/cfg/context/MethodTarget.java | 2 +- .../org/hibernate/validator/cfg/context/ParameterTarget.java | 2 +- .../org/hibernate/validator/cfg/context/PropertyTarget.java | 2 +- .../org/hibernate/validator/cfg/context/ReturnValueTarget.java | 2 +- .../java/org/hibernate/validator/cfg/context/TypeTarget.java | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/cfg/context/ConstraintDefinitionTarget.java b/engine/src/main/java/org/hibernate/validator/cfg/context/ConstraintDefinitionTarget.java index 9d95376c39..be60cfe004 100644 --- a/engine/src/main/java/org/hibernate/validator/cfg/context/ConstraintDefinitionTarget.java +++ b/engine/src/main/java/org/hibernate/validator/cfg/context/ConstraintDefinitionTarget.java @@ -9,7 +9,7 @@ import java.lang.annotation.Annotation; /** - * Facet of a constraint definition creational context which allows to the select the constraint (annotation type) to + * Facet of a constraint definition creational context which allows to select the constraint (annotation type) to * which the next operations shall apply. * * @author Yoann Rodiere diff --git a/engine/src/main/java/org/hibernate/validator/cfg/context/ConstructorTarget.java b/engine/src/main/java/org/hibernate/validator/cfg/context/ConstructorTarget.java index e764b84f8b..5df88fd96b 100644 --- a/engine/src/main/java/org/hibernate/validator/cfg/context/ConstructorTarget.java +++ b/engine/src/main/java/org/hibernate/validator/cfg/context/ConstructorTarget.java @@ -7,7 +7,7 @@ package org.hibernate.validator.cfg.context; /** - * Facet of a constraint mapping creational context which allows to the select the bean + * Facet of a constraint mapping creational context which allows to select the bean * constructor to which the next operations shall apply. * * @author Gunnar Morling diff --git a/engine/src/main/java/org/hibernate/validator/cfg/context/CrossParameterTarget.java b/engine/src/main/java/org/hibernate/validator/cfg/context/CrossParameterTarget.java index 8caa0449b3..a7e12b75be 100644 --- a/engine/src/main/java/org/hibernate/validator/cfg/context/CrossParameterTarget.java +++ b/engine/src/main/java/org/hibernate/validator/cfg/context/CrossParameterTarget.java @@ -7,7 +7,7 @@ package org.hibernate.validator.cfg.context; /** - * Facet of a constraint mapping creational context which allows to the select the cross-parameter element of a method + * Facet of a constraint mapping creational context which allows to select the cross-parameter element of a method * or constructor as target of the next operations. * * @author Gunnar Morling diff --git a/engine/src/main/java/org/hibernate/validator/cfg/context/MethodTarget.java b/engine/src/main/java/org/hibernate/validator/cfg/context/MethodTarget.java index bb46e208be..280998d393 100644 --- a/engine/src/main/java/org/hibernate/validator/cfg/context/MethodTarget.java +++ b/engine/src/main/java/org/hibernate/validator/cfg/context/MethodTarget.java @@ -7,7 +7,7 @@ package org.hibernate.validator.cfg.context; /** - * Facet of a constraint mapping creational context which allows to the select the bean + * Facet of a constraint mapping creational context which allows to select the bean * method to which the next operations shall apply. * * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI diff --git a/engine/src/main/java/org/hibernate/validator/cfg/context/ParameterTarget.java b/engine/src/main/java/org/hibernate/validator/cfg/context/ParameterTarget.java index 7159075290..f2bac6be31 100644 --- a/engine/src/main/java/org/hibernate/validator/cfg/context/ParameterTarget.java +++ b/engine/src/main/java/org/hibernate/validator/cfg/context/ParameterTarget.java @@ -7,7 +7,7 @@ package org.hibernate.validator.cfg.context; /** - * Facet of a constraint mapping creational context which allows to the select a method or constructor parameter to + * Facet of a constraint mapping creational context which allows to select a method or constructor parameter to * which the next operations shall apply. * * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI diff --git a/engine/src/main/java/org/hibernate/validator/cfg/context/PropertyTarget.java b/engine/src/main/java/org/hibernate/validator/cfg/context/PropertyTarget.java index bce7f0c448..3fae3760fa 100644 --- a/engine/src/main/java/org/hibernate/validator/cfg/context/PropertyTarget.java +++ b/engine/src/main/java/org/hibernate/validator/cfg/context/PropertyTarget.java @@ -9,7 +9,7 @@ import java.lang.annotation.ElementType; /** - * Facet of a constraint mapping creational context which allows to the select the bean + * Facet of a constraint mapping creational context which allows to select the bean * property to which the next operations shall apply. * * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI diff --git a/engine/src/main/java/org/hibernate/validator/cfg/context/ReturnValueTarget.java b/engine/src/main/java/org/hibernate/validator/cfg/context/ReturnValueTarget.java index b632c6dc22..46a5e4b39b 100644 --- a/engine/src/main/java/org/hibernate/validator/cfg/context/ReturnValueTarget.java +++ b/engine/src/main/java/org/hibernate/validator/cfg/context/ReturnValueTarget.java @@ -7,7 +7,7 @@ package org.hibernate.validator.cfg.context; /** - * Facet of a constraint mapping creational context which allows to the select the current method's or constructor's + * Facet of a constraint mapping creational context which allows to select the current method's or constructor's * return value as target for the next operations. * * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI diff --git a/engine/src/main/java/org/hibernate/validator/cfg/context/TypeTarget.java b/engine/src/main/java/org/hibernate/validator/cfg/context/TypeTarget.java index 471511efb1..588ae68bad 100644 --- a/engine/src/main/java/org/hibernate/validator/cfg/context/TypeTarget.java +++ b/engine/src/main/java/org/hibernate/validator/cfg/context/TypeTarget.java @@ -7,7 +7,7 @@ package org.hibernate.validator.cfg.context; /** - * Facet of a constraint mapping creational context which allows to the select the bean + * Facet of a constraint mapping creational context which allows to select the bean * type to which the next operations shall apply. * * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI From f8c0a7e3509c77116e0081e49e8ad97231f0d9d0 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 1 Jun 2018 14:58:21 +0200 Subject: [PATCH 037/393] HV-667 Create the Bean Validation descriptor model lazily --- .../metadata/aggregated/BeanMetaDataImpl.java | 103 ++++++++++++------ 1 file changed, 67 insertions(+), 36 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java index 386ba70b63..d7460ef8b7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java @@ -134,11 +134,6 @@ public final class BeanMetaDataImpl implements BeanMetaData { @Immutable private final Set cascadedProperties; - /** - * The bean descriptor for this bean. - */ - private final BeanDescriptor beanDescriptor; - /** * The default groups sequence for this bean class. */ @@ -162,6 +157,22 @@ public final class BeanMetaDataImpl implements BeanMetaData { @Immutable private final List> classHierarchyWithoutInterfaces; + /** + * {code true} if the default group sequence is redefined, either via a group sequence redefinition or a group + * sequence provider. + */ + private final boolean defaultGroupSequenceRedefined; + + /** + * The resolved default group sequence. + */ + private final List> resolvedDefaultGroupSequence; + + /** + * The bean descriptor for this bean. Lazily created. + */ + private volatile BeanDescriptor beanDescriptor; + /** * Creates a new {@link BeanMetaDataImpl} * @@ -233,36 +244,9 @@ public BeanMetaDataImpl(Class beanClass, this.executableMetaDataMap = CollectionHelper.toImmutableMap( bySignature( executableMetaDataSet ) ); this.unconstrainedExecutables = CollectionHelper.toImmutableSet( tmpUnconstrainedExecutables ); - boolean defaultGroupSequenceIsRedefined = defaultGroupSequenceIsRedefined(); - List> resolvedDefaultGroupSequence = getDefaultGroupSequence( null ); - - Map propertyDescriptors = getConstrainedPropertiesAsDescriptors( - propertyMetaDataMap, - defaultGroupSequenceIsRedefined, - resolvedDefaultGroupSequence - ); - - Map methodsDescriptors = getConstrainedMethodsAsDescriptors( - executableMetaDataMap, - defaultGroupSequenceIsRedefined, - resolvedDefaultGroupSequence - ); - - Map constructorsDescriptors = getConstrainedConstructorsAsDescriptors( - executableMetaDataMap, - defaultGroupSequenceIsRedefined, - resolvedDefaultGroupSequence - ); - - this.beanDescriptor = new BeanDescriptorImpl( - beanClass, - getClassLevelConstraintsAsDescriptors( allMetaConstraints ), - propertyDescriptors, - methodsDescriptors, - constructorsDescriptors, - defaultGroupSequenceIsRedefined, - resolvedDefaultGroupSequence - ); + // We initialize those elements eagerly so that any eventual error is thrown when bootstrapping the bean metadata + this.defaultGroupSequenceRedefined = this.defaultGroupSequence.size() > 1 || hasDefaultGroupSequenceProvider(); + this.resolvedDefaultGroupSequence = getDefaultGroupSequence( null ); } @Override @@ -277,6 +261,21 @@ public boolean hasConstraints() { @Override public BeanDescriptor getBeanDescriptor() { + BeanDescriptor beanDescriptor = this.beanDescriptor; + + if ( beanDescriptor == null ) { + synchronized ( this ) { + beanDescriptor = this.beanDescriptor; + + if ( beanDescriptor == null ) { + beanDescriptor = createBeanDescriptor( beanClass, allMetaConstraints, propertyMetaDataMap, executableMetaDataMap, + defaultGroupSequenceRedefined, resolvedDefaultGroupSequence ); + + this.beanDescriptor = beanDescriptor; + } + } + } + return beanDescriptor; } @@ -359,7 +358,7 @@ public Iterator getDefaultValidationSequence(T beanState) { @Override public boolean defaultGroupSequenceIsRedefined() { - return defaultGroupSequence.size() > 1 || hasDefaultGroupSequenceProvider(); + return defaultGroupSequenceRedefined; } @Override @@ -367,6 +366,38 @@ public List> getClassHierarchy() { return classHierarchyWithoutInterfaces; } + private static BeanDescriptor createBeanDescriptor(Class beanClass, Set> allMetaConstraints, + Map propertyMetaDataMap, Map executableMetaDataMap, boolean defaultGroupSequenceRedefined, + List> resolvedDefaultGroupSequence) { + Map propertyDescriptors = getConstrainedPropertiesAsDescriptors( + propertyMetaDataMap, + defaultGroupSequenceRedefined, + resolvedDefaultGroupSequence + ); + + Map methodsDescriptors = getConstrainedMethodsAsDescriptors( + executableMetaDataMap, + defaultGroupSequenceRedefined, + resolvedDefaultGroupSequence + ); + + Map constructorsDescriptors = getConstrainedConstructorsAsDescriptors( + executableMetaDataMap, + defaultGroupSequenceRedefined, + resolvedDefaultGroupSequence + ); + + return new BeanDescriptorImpl( + beanClass, + getClassLevelConstraintsAsDescriptors( allMetaConstraints ), + propertyDescriptors, + methodsDescriptors, + constructorsDescriptors, + defaultGroupSequenceRedefined, + resolvedDefaultGroupSequence + ); + } + private static Set> getClassLevelConstraintsAsDescriptors(Set> constraints) { return constraints.stream() .filter( c -> c.getElementType() == ElementType.TYPE ) From 061df699466f80f038aa6db7d222d7e9a5402952 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 1 Jun 2018 15:00:42 +0200 Subject: [PATCH 038/393] HV-667 Rename a method for more consistency --- .../validator/internal/engine/ValidatorImpl.java | 10 +++++----- .../internal/metadata/aggregated/BeanMetaData.java | 2 +- .../internal/metadata/aggregated/BeanMetaDataImpl.java | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index b41b6ae78e..202c758875 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -364,7 +364,7 @@ private Set> validateInContext(BaseBeanValidationC } BeanMetaData beanMetaData = valueContext.getCurrentBeanMetaData(); - if ( beanMetaData.defaultGroupSequenceIsRedefined() ) { + if ( beanMetaData.isDefaultGroupSequenceRedefined() ) { validationOrder.assertDefaultGroupSequenceIsExpandable( beanMetaData.getDefaultGroupSequence( valueContext.getCurrentBean() ) ); } @@ -435,7 +435,7 @@ private void validateConstraintsForDefaultGroup(BaseBeanValidationContext // evaluating the constraints of a bean per class in hierarchy, this is necessary to detect potential default group re-definitions for ( Class clazz : beanMetaData.getClassHierarchy() ) { BeanMetaData hostingBeanMetaData = beanMetaDataManager.getBeanMetaData( clazz ); - boolean defaultGroupSequenceIsRedefined = hostingBeanMetaData.defaultGroupSequenceIsRedefined(); + boolean defaultGroupSequenceIsRedefined = hostingBeanMetaData.isDefaultGroupSequenceRedefined(); // if the current class redefined the default group sequence, this sequence has to be applied to all the class hierarchy. if ( defaultGroupSequenceIsRedefined ) { @@ -766,7 +766,7 @@ private Set> validateValueInContext(BaseBeanValidatio valueContext.setCurrentValidatedValue( value ); BeanMetaData beanMetaData = valueContext.getCurrentBeanMetaData(); - if ( beanMetaData.defaultGroupSequenceIsRedefined() ) { + if ( beanMetaData.isDefaultGroupSequenceRedefined() ) { validationOrder.assertDefaultGroupSequenceIsExpandable( beanMetaData.getDefaultGroupSequence( null ) ); } @@ -828,7 +828,7 @@ private void validateParametersInContext(ExecutableValidationContext vali ); } - if ( beanMetaData.defaultGroupSequenceIsRedefined() ) { + if ( beanMetaData.isDefaultGroupSequenceRedefined() ) { validationOrder.assertDefaultGroupSequenceIsExpandable( beanMetaData.getDefaultGroupSequence( validationContext.getRootBean() @@ -1014,7 +1014,7 @@ private void validateReturnValueInContext(ExecutableValidationContext ExecutableMetaData executableMetaData = executableMetaDataOptional.get(); - if ( beanMetaData.defaultGroupSequenceIsRedefined() ) { + if ( beanMetaData.isDefaultGroupSequenceRedefined() ) { validationOrder.assertDefaultGroupSequenceIsExpandable( beanMetaData.getDefaultGroupSequence( bean ) ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaData.java index 3a9f5a00dc..fdeac0ffa5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaData.java @@ -79,7 +79,7 @@ public interface BeanMetaData extends Validatable { /** * @return {@code true} if the entity redefines the default group sequence, {@code false} otherwise. */ - boolean defaultGroupSequenceIsRedefined(); + boolean isDefaultGroupSequenceRedefined(); /** * @return A set of {@code MetaConstraint} instances encapsulating the information of all the constraints diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java index d7460ef8b7..dedbfd2128 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java @@ -357,7 +357,7 @@ public Iterator getDefaultValidationSequence(T beanState) { } @Override - public boolean defaultGroupSequenceIsRedefined() { + public boolean isDefaultGroupSequenceRedefined() { return defaultGroupSequenceRedefined; } From 8b81b9eee4b8b873077c998887f4efdc4e51793d Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 7 Jun 2018 11:44:53 +0200 Subject: [PATCH 039/393] HV-1626 Remove useless Maven plugins and extensions --- pom.xml | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/pom.xml b/pom.xml index 6bac0f59c3..3006bed233 100644 --- a/pom.xml +++ b/pom.xml @@ -435,13 +435,6 @@ - - - org.apache.maven.wagon - wagon-webdav - 1.0-beta-2 - - maven-enforcer-plugin @@ -746,15 +739,6 @@ documentation-pdf - - org.codehaus.mojo - exec-maven-plugin - - 1.5.0 - org.asciidoctor asciidoctor-maven-plugin @@ -787,10 +771,6 @@ copy-maven-plugin 0.0.6 - - maven-project-info-reports-plugin - 2.9 - org.apache.felix maven-bundle-plugin From 798b3400184b5d7bc2e60ef257771d8f69ce2d16 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 7 Jun 2018 11:52:28 +0200 Subject: [PATCH 040/393] HV-1627 Upgrade our JPA dependency to 2.2 --- distribution/pom.xml | 4 ++-- distribution/src/main/assembly/dist.xml | 2 +- engine/pom.xml | 4 ++-- integration/pom.xml | 4 ++-- pom.xml | 8 ++++---- tck-runner/pom.xml | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/distribution/pom.xml b/distribution/pom.xml index dcbb0a4d8d..e62d014efd 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -54,8 +54,8 @@ log4j - org.hibernate.javax.persistence - hibernate-jpa-2.1-api + javax.persistence + javax.persistence-api joda-time diff --git a/distribution/src/main/assembly/dist.xml b/distribution/src/main/assembly/dist.xml index 686cb34420..fa2d71e776 100644 --- a/distribution/src/main/assembly/dist.xml +++ b/distribution/src/main/assembly/dist.xml @@ -44,7 +44,7 @@ log4j:log4j joda-time:joda-time - org.hibernate.javax.persistence:hibernate-jpa-2.1-api + javax.persistence:javax.persistence-api org.jsoup:jsoup com.thoughtworks.paranamer:paranamer diff --git a/engine/pom.xml b/engine/pom.xml index 8ab9fb8842..4b50ce6717 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -79,8 +79,8 @@ Optional dependencies --> - org.hibernate.javax.persistence - hibernate-jpa-2.1-api + javax.persistence + javax.persistence-api true diff --git a/integration/pom.xml b/integration/pom.xml index 2195ede544..ac2e0a80cf 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -93,8 +93,8 @@ test - org.hibernate.javax.persistence - hibernate-jpa-2.1-api + javax.persistence + javax.persistence-api test diff --git a/pom.xml b/pom.xml index 3006bed233..24e7880409 100644 --- a/pom.xml +++ b/pom.xml @@ -134,7 +134,7 @@ 1.8.3 2.9.7 1.7.22 - 1.0.2.Final + 2.2 - --add-opens java.base/java.lang=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED diff --git a/distribution/pom.xml b/distribution/pom.xml index e62d014efd..68e669143d 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -93,13 +93,13 @@ ${project.groupId} hibernate-validator-modules - wildfly-${wildfly.version}-patch + wildfly-${version.wildfly}-patch zip ${project.groupId} hibernate-validator-modules - wildfly-${wildfly-secondary.version}-patch + wildfly-${version.wildfly.secondary}-patch zip diff --git a/documentation/pom.xml b/documentation/pom.xml index 1d0dff51df..03553c86f7 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -40,7 +40,7 @@ true - -Duser.language=en + -Duser.language=en forbidden-allow-junit.txt .. @@ -126,7 +126,7 @@ org.hibernate.infra hibernate-asciidoctor-theme - ${hibernate-asciidoctor-theme.version} + ${version.org.hibernate.infra.hibernate-asciidoctor-theme} zip true ${project.build.directory}/ @@ -250,13 +250,13 @@ ${asciidoctor.osgi-integrationtest-source-dir} ${project.version} - ${bv.api.version} - ${jboss.logging.version} - ${classmate.version} - ${javax.el.version} + ${version.javax.validation} + ${version.org.jboss.logging.jboss-logging} + ${version.com.fasterxml.classmate} + ${version.org.glassfish.javax.el} - ${wildfly.version} - ${wildfly-secondary.version} + ${version.wildfly} + ${version.wildfly.secondary} ${java.api-docs.base-url}/ diff --git a/engine/pom.xml b/engine/pom.xml index 4b50ce6717..6163f950a4 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -279,7 +279,7 @@ [9,) - --illegal-access=deny + --illegal-access=deny @@ -301,7 +301,7 @@ org.hibernate.beanvalidation.tck beanvalidation-tck-tests - ${tck.version} + ${version.org.hibernate.beanvalidation.tck} jar true diff --git a/integration/pom.xml b/integration/pom.xml index ac2e0a80cf..15618dd186 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -21,10 +21,10 @@ Hibernate Validator WildFly integration tests. - ${project.build.directory}/wildfly-${wildfly.version} + ${project.build.directory}/wildfly-${version.wildfly} ${wildfly.target-dir}/modules/system/layers/base - ${project.build.directory}/wildfly-${wildfly-secondary.version} + ${project.build.directory}/wildfly-${version.wildfly.secondary} ${wildfly-secondary.target-dir}/modules/system/layers/base .. @@ -120,7 +120,7 @@ ${project.groupId} hibernate-validator-modules - wildfly-${wildfly.version}-patch + wildfly-${version.wildfly}-patch zip test @@ -207,7 +207,7 @@ org.wildfly wildfly-dist - ${wildfly.version} + ${version.wildfly} tar.gz false ${project.build.directory} @@ -216,7 +216,7 @@ org.wildfly wildfly-dist - ${wildfly-secondary.version} + ${version.wildfly.secondary} tar.gz false ${project.build.directory} @@ -237,7 +237,7 @@ ${project.groupId} hibernate-validator-modules ${project.version} - wildfly-${wildfly.version}-patch + wildfly-${version.wildfly}-patch zip ${project.build.directory} @@ -246,7 +246,7 @@ ${project.groupId} hibernate-validator-modules ${project.version} - wildfly-${wildfly-secondary.version}-patch + wildfly-${version.wildfly.secondary}-patch zip ${project.build.directory} @@ -265,26 +265,26 @@ javax.money money-api - ${javax-money.version} + ${version.javax.money} ${wildfly.modules-dir}/javax/money/api/main/ org.javamoney moneta - ${moneta.version} + ${version.org.javamoney.moneta} ${wildfly.modules-dir}/org/javamoney/moneta/main/ javax.money money-api - ${javax-money.version} + ${version.javax.money} ${wildfly-secondary.modules-dir}/javax/money/api/main/ org.javamoney moneta - ${moneta.version} + ${version.org.javamoney.moneta} ${wildfly-secondary.modules-dir}/org/javamoney/moneta/main/ @@ -344,10 +344,10 @@ true - ${project.build.directory}/wildfly-${wildfly.version}/ + ${project.build.directory}/wildfly-${version.wildfly}/ false - patch apply ${project.build.directory}/hibernate-validator-modules-${project.version}-wildfly-${wildfly.version}-patch.zip + patch apply ${project.build.directory}/hibernate-validator-modules-${project.version}-wildfly-${version.wildfly}-patch.zip @@ -360,10 +360,10 @@ true - ${project.build.directory}/wildfly-${wildfly-secondary.version}/ + ${project.build.directory}/wildfly-${version.wildfly.secondary}/ false - patch apply ${project.build.directory}/hibernate-validator-modules-${project.version}-wildfly-${wildfly-secondary.version}-patch.zip + patch apply ${project.build.directory}/hibernate-validator-modules-${project.version}-wildfly-${version.wildfly.secondary}-patch.zip @@ -379,7 +379,7 @@ - --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED + --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED diff --git a/integration/src/test/modules/javax/money/api/main/module.xml b/integration/src/test/modules/javax/money/api/main/module.xml index 9602e1a952..75fdeff223 100644 --- a/integration/src/test/modules/javax/money/api/main/module.xml +++ b/integration/src/test/modules/javax/money/api/main/module.xml @@ -7,6 +7,6 @@ --> - + diff --git a/integration/src/test/modules/org/javamoney/moneta/main/module.xml b/integration/src/test/modules/org/javamoney/moneta/main/module.xml index 801109908e..710be343b0 100644 --- a/integration/src/test/modules/org/javamoney/moneta/main/module.xml +++ b/integration/src/test/modules/org/javamoney/moneta/main/module.xml @@ -7,7 +7,7 @@ --> - + diff --git a/integration/src/test/resources/arquillian.xml b/integration/src/test/resources/arquillian.xml index 0802cd63a1..9116248ee6 100644 --- a/integration/src/test/resources/arquillian.xml +++ b/integration/src/test/resources/arquillian.xml @@ -22,9 +22,9 @@ REMOTE - ${basedir}/target/wildfly-${wildfly.version} + ${basedir}/target/wildfly-${version.wildfly} - -Dee8.preview.mode=true ${arquillian.javaVmArguments.add-opens} + -Dee8.preview.mode=true ${arquillian.wildfly.jvm.args} - ${project.build.directory}/wildfly-original/wildfly-${wildfly.version} - ${project.build.directory}/wildfly-patched/wildfly-${wildfly.version} + ${project.build.directory}/wildfly-original/wildfly-${version.wildfly} + ${project.build.directory}/wildfly-patched/wildfly-${version.wildfly} ${project.build.directory}/wildfly-current-hv-patch.zip - ${project.build.directory}/wildfly-original/wildfly-${wildfly-secondary.version} - ${project.build.directory}/wildfly-patched/wildfly-${wildfly-secondary.version} + ${project.build.directory}/wildfly-original/wildfly-${version.wildfly.secondary} + ${project.build.directory}/wildfly-patched/wildfly-${version.wildfly.secondary} ${project.build.directory}/wildfly-secondary-hv-patch.zip - + + ${patch-gen.jvm.args.add-opens} .. @@ -105,13 +103,13 @@ ${wildfly-main.patch-file} zip - wildfly-${wildfly.version}-patch + wildfly-${version.wildfly}-patch ${wildfly-secondary.patch-file} zip - wildfly-${wildfly-secondary.version}-patch + wildfly-${version.wildfly.secondary}-patch @@ -173,7 +171,7 @@ org.wildfly wildfly-dist - ${wildfly.version} + ${version.wildfly} tar.gz false ${project.build.directory}/wildfly-original @@ -181,7 +179,7 @@ org.wildfly wildfly-dist - ${wildfly.version} + ${version.wildfly} tar.gz false ${project.build.directory}/wildfly-patched @@ -190,7 +188,7 @@ org.wildfly wildfly-dist - ${wildfly-secondary.version} + ${version.wildfly.secondary} tar.gz false ${project.build.directory}/wildfly-original @@ -198,7 +196,7 @@ org.wildfly wildfly-dist - ${wildfly-secondary.version} + ${version.wildfly.secondary} tar.gz false ${project.build.directory}/wildfly-patched @@ -219,11 +217,11 @@ javax.validation validation-api - ${bv.api.version} + ${version.javax.validation} false ${wildfly-main.patched.target-dir}/modules/system/layers/base/javax/validation/api/main - validation-api-${bv.api.version}.jar + validation-api-${version.javax.validation}.jar ${project.groupId} @@ -245,11 +243,11 @@ javax.validation validation-api - ${bv.api.version} + ${version.javax.validation} false ${wildfly-secondary.patched.target-dir}/modules/system/layers/base/javax/validation/api/main - validation-api-${bv.api.version}.jar + validation-api-${version.javax.validation}.jar ${project.groupId} @@ -284,7 +282,7 @@ generate-patch - ${patch-gen-maven-plugin.argLine.add-opens} + ${patch-gen.jvm.args} ${wildfly-main.original.target-dir} ${module.xml.targetdir}/wildfly-current-patch.xml ${wildfly-main.patched.target-dir} @@ -298,7 +296,7 @@ generate-patch - ${patch-gen-maven-plugin.argLine.add-opens} + ${patch-gen.jvm.args} ${wildfly-secondary.original.target-dir} ${module.xml.targetdir}/wildfly-secondary-patch.xml ${wildfly-secondary.patched.target-dir} @@ -317,7 +315,7 @@ [9,) - --add-opens=java.base/java.lang=ALL-UNNAMED + --add-opens=java.base/java.lang=ALL-UNNAMED diff --git a/modules/src/main/modules/wildfly-current-patch.xml b/modules/src/main/modules/wildfly-current-patch.xml index 3f8f6178f2..5b759320a2 100644 --- a/modules/src/main/modules/wildfly-current-patch.xml +++ b/modules/src/main/modules/wildfly-current-patch.xml @@ -6,11 +6,11 @@ ~ See the license.txt file in the root directory or . --> - wildfly-${wildfly.version}-hibernate-validator-${project.version} - This patch upgrades Hibernate Validator to ${project.version} within a WildFly ${wildfly.version} installation - + wildfly-${version.wildfly}-hibernate-validator-${project.version} + This patch upgrades Hibernate Validator to ${project.version} within a WildFly ${version.wildfly} installation + - This patch upgrades Hibernate Validator to ${project.version} within a WildFly ${wildfly.version} installation + This patch upgrades Hibernate Validator to ${project.version} within a WildFly ${version.wildfly} installation diff --git a/modules/src/main/modules/wildfly-secondary-patch.xml b/modules/src/main/modules/wildfly-secondary-patch.xml index 8692b9b7f8..5700566477 100644 --- a/modules/src/main/modules/wildfly-secondary-patch.xml +++ b/modules/src/main/modules/wildfly-secondary-patch.xml @@ -6,11 +6,11 @@ ~ See the license.txt file in the root directory or . --> - wildfly-${wildfly-secondary.version}-hibernate-validator-${project.version} - This patch upgrades Hibernate Validator to ${project.version} within a WildFly ${wildfly-secondary.version} installation - + wildfly-${version.wildfly.secondary}-hibernate-validator-${project.version} + This patch upgrades Hibernate Validator to ${project.version} within a WildFly ${version.wildfly.secondary} installation + - This patch upgrades Hibernate Validator to ${project.version} within a WildFly ${wildfly-secondary.version} installation + This patch upgrades Hibernate Validator to ${project.version} within a WildFly ${version.wildfly.secondary} installation diff --git a/modules/src/script/setupModules.groovy b/modules/src/script/setupModules.groovy index ce849302dd..93092db5c0 100644 --- a/modules/src/script/setupModules.groovy +++ b/modules/src/script/setupModules.groovy @@ -23,7 +23,7 @@ def removeDependency(File file, String dependencyToRemove) { // BV API bvModuleXml = new File( wildflyPatchedTargetDir, 'modules/system/layers/base/javax/validation/api/main/module.xml' ) -def bvArtifactName = 'validation-api-' + project.properties['bv.api.version'] + '.jar'; +def bvArtifactName = 'validation-api-' + project.properties['version.javax.validation'] + '.jar'; println "[INFO] Using BV version " + bvArtifactName; processFileInplace( bvModuleXml ) { text -> text.replaceAll( /validation-api.*jar/, bvArtifactName ) diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index e98de4737b..55c15d1c8c 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -28,7 +28,7 @@ org.jboss.arquillian arquillian-bom - ${arquillian.version} + ${version.org.jboss.arquillian} import pom @@ -76,7 +76,7 @@ fish.payara.arquillian arquillian-payara-server-4-managed - ${payara-arquillian.version} + ${version.fish.payara.arquillian} test @@ -131,7 +131,7 @@ fish.payara.distributions payara - ${payara.version} + ${version.fish.payara} zip false ${project.build.directory} diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 36961223a5..28ce4576ea 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -77,13 +77,13 @@ org.ops4j.pax.exam pax-exam-container-karaf - ${pax.exam.version} + ${version.org.ops4j.pax.exam} test org.apache.karaf apache-karaf - ${apache.karaf.version} + ${version.org.apache.karaf} tar.gz test + + 6.0.9.Final + + + + http://beanvalidation.org/2.0/spec/ + http://docs.oracle.com/javase/8/docs/api + http://docs.oracle.com/javase/8/docs/technotes + http://docs.oracle.com/javaee/7/api + http://docs.oracle.com/javase/8/javase-clienttechnologies.htm + http://docs.jboss.org/hibernate/beanvalidation/spec/2.0/api + http://javamoney.github.io/apidocs + org.hibernate.validator org.hibernate.validator.cdi - - UTF-8 - UTF-8 - - true - - 2.0.1.Final - 2.0.3.Final + - - 6.0.9.Final + 2.0.1.Final + 2.0.3.Final - 2.8 - 3.0.1-b09 - 3.3.2.Final - 2.1.0.Final + 2.8 + 3.0.1-b09 + 3.3.2.Final + 2.1.0.Final - 12.0.0.Final + 12.0.0.Final - 11.0.0.Final + 11.0.0.Final - ${wildfly.version} + ${version.wildfly} - 1.3.4 - 1.8.3 - 2.9.7 - 1.7.22 - 2.2 + 1.3.4 + 1.8.3 + 2.9.7 + 1.7.22 + 1.2.17 + 2.2 - 2.0 - 3.0.3.Final - 2.1.0.Final - 1.0.1.Final + 2.0 + 3.0.4.Final + 2.1.0.Final + 1.0.1.Final + 1.0.0.Final - 1.0.1 - 1.1 + 1.0.1 + 1.1 - 1.2 - - - 2.0.1.Alpha5 - 5.0.3 - 1.2.1.Final - 4.0.0.Final + 1.2 - 1.1.11.Final - 6.8 + 1.1.11.Final + 6.8 - 3.8.0 - 4.12 - 3.4 + 3.8.0 + 4.12 + 3.4 + 2.4.12 + 23.0 + 4.3.10.RELEASE + 1.0.0.Final - 4.11.0 - 2.5.2 - 4.1.1 - 6.0.0 - 5.Beta1 - 1.0.Beta2 + 4.1.2 + 4.11.0 + 2.5.2 + 6.0.0 + 5.181 + 1.0.Beta3 + 8.1 - 2.4.12 + - 23.0 + 1.5.6 + 1.0.2.Final + 1.0.3.Final + 9.1.15.0 + 1.6.0-alpha.5 + 1.5.0-alpha.16 - 4.3.10.RELEASE + - - 1.0.1.Final - 1.0.3.Final - 1.5.5 - 9.1.8.0 - 1.6.0-alpha.5 - 1.5.0-alpha.16 + 1.8 + 3.1.0 + 3.0.0 + 3.5.0 + 2.17 + 3.0.0 + 3.7.0 + 0.0.6 + 3.0.2 + 1.4.0 + 2.8.2 + 3.0.0-M1 + 2.5 + 1.6 + 2.5.2 + 0.11.0 + 3.0.2 + 1.3.0 + 3.0.0 + 3.0 + 2.5.3 + 3.0.2 + 3.1.0 + 1.0 + 3.0.1 + 2.21.0 + ${version.surefire.plugin} + 1.2.1.Final + 5.0.0.Final + 2.0.1.Alpha5 + 5.0.3 - - http://beanvalidation.org/2.0/spec/ - http://docs.oracle.com/javase/8/docs/api - http://docs.oracle.com/javase/8/docs/technotes - http://docs.oracle.com/javaee/7/api - http://docs.oracle.com/javase/8/javase-clienttechnologies.htm - http://docs.jboss.org/hibernate/beanvalidation/spec/2.0/api - http://javamoney.github.io/apidocs + + forbidden-junit.txt - 2.21.0 + - - - - + jboss-releases-repository + https://repository.jboss.org/nexus/service/local/staging/deploy/maven2/ + jboss-snapshots-repository + https://repository.jboss.org/nexus/content/repositories/snapshots/ + + + . + + UTF-8 + UTF-8 + + + true + + 1.8 + 1.8 + ${maven.compiler.target} + ${maven.compiler.source} - java.xml.bind - java.xml.bind + ${maven.compiler.target} + ${maven.compiler.source} + ${maven.compiler.testTarget} + ${maven.compiler.testSource} - - + + + + + ${surefire.jvm.args.additional} ${surefire.jvm.args.add-opens} ${surefire.jvm.args.illegal-access} + ${surefire.jvm.args.additional} ${surefire.jvm.args.add-opens} ${surefire.jvm.args.illegal-access} - - forbidden-junit.txt + + ${arquillian.wildfly.jvm.args.add-opens} - . + + ${maven.compiler.argument.source} + 3.3.1 @@ -248,120 +303,120 @@ ${project.groupId} hibernate-validator-modules ${project.version} - wildfly-${wildfly.version}-patch + wildfly-${version.wildfly}-patch zip ${project.groupId} hibernate-validator-modules ${project.version} - wildfly-${wildfly-secondary.version}-patch + wildfly-${version.wildfly.secondary}-patch zip javax.validation validation-api - ${bv.api.version} + ${version.javax.validation} org.jboss.logging jboss-logging - ${jboss.logging.version} + ${version.org.jboss.logging.jboss-logging} org.jboss.logging jboss-logging-processor - ${jboss.logging.processor.version} + ${version.org.jboss.logging.jboss-logging-tools} org.jboss.logging jboss-logging-annotations - ${jboss.logging.processor.version} + ${version.org.jboss.logging.jboss-logging-tools} org.glassfish javax.el - ${javax.el.version} + ${version.org.glassfish.javax.el} com.fasterxml classmate - ${classmate.version} + ${version.com.fasterxml.classmate} joda-time joda-time - ${joda-time.version} + ${version.joda-time} javax.money money-api - ${javax-money.version} + ${version.javax.money} org.javamoney moneta - ${moneta.version} + ${version.org.javamoney.moneta} org.osgi org.osgi.core - ${osgi-core.version} + ${version.org.osgi.core} org.jsoup jsoup - ${jsoup.version} + ${version.jsoup} log4j log4j - 1.2.17 + ${version.log4j} org.slf4j slf4j-api - ${slf4j.version} + ${version.org.slf4j} org.slf4j slf4j-log4j12 - ${slf4j.version} + ${version.org.slf4j} javax.persistence javax.persistence-api - ${javax.persistence-api.version} + ${version.javax.persistence} junit junit - ${junit.version} + ${version.junit} org.testng testng - ${testng.version} + ${version.org.testng} org.codehaus.groovy groovy-jsr223 - ${groovy.version} + ${version.org.codehaus.groovy} org.easymock easymock - ${easymock.version} + ${version.org.easymock} org.assertj assertj-core - ${assertj-core.version} + ${version.org.assertj.assertj-core} org.jboss.arquillian arquillian-bom - ${arquillian.version} + ${version.org.jboss.arquillian} pom import @@ -373,17 +428,17 @@ org.jboss.spec.javax.interceptor jboss-interceptors-api_1.2_spec - 1.0.0.Final + ${version.org.jboss.spec.javax.interceptor.jboss-interceptors-api_1.2_spec} org.jboss.spec.javax.ejb jboss-ejb-api_3.2_spec - ${jboss-ejb-api_3.2_spec.version} + ${version.org.jboss.spec.javax.ejb.jboss-ejb-api_3.2_spec} javax.enterprise cdi-api - ${cdi-api.version} + ${version.javax.enterprise} javax.interceptor @@ -398,12 +453,12 @@ org.jboss.weld weld-core-impl - ${weld.version} + ${version.org.jboss.weld.weld} org.wildfly.arquillian wildfly-arquillian-container-managed - ${wildfly-arquillian.version} + ${version.org.wildfly.arquillian} sun.jdk @@ -414,22 +469,25 @@ org.jboss.arquillian.container arquillian-weld-se-embedded-1.1 - 1.0.0.Final + ${version.org.jboss.arquillian.container.arquillian-weld-se-embedded-1.1} + test com.thoughtworks.paranamer paranamer - ${paranamer.version} + ${version.com.thoughtworks.paranamer} com.google.guava guava - ${guava.version} + ${version.com.google.guava} + test org.springframework spring-expression - ${spring-expression.version} + ${version.org.springframework.spring-expression} + test @@ -438,7 +496,7 @@ maven-enforcer-plugin - 3.0.0-M1 + ${version.enforcer.plugin} enforce-java @@ -448,10 +506,10 @@ - [1.8.0-20,) + [${jdk.min.version},) - 3.3.1 + ${maven.min.version} @@ -467,15 +525,15 @@ maven-antrun-plugin - 1.8 + ${version.antrun.plugin} maven-clean-plugin - 3.0.0 + ${version.clean.plugin} maven-jar-plugin - 3.0.2 + ${version.jar.plugin} @@ -490,8 +548,12 @@ maven-compiler-plugin - 3.7.0 + ${version.compiler.plugin} + ${maven.compiler.argument.source} + ${maven.compiler.argument.target} + ${maven.compiler.argument.testSource} + ${maven.compiler.argument.testTarget} -Aorg.jboss.logging.tools.addGeneratedAnnotation=false @@ -500,7 +562,7 @@ maven-checkstyle-plugin - 2.17 + ${version.checkstyle.plugin} ${project.groupId} @@ -521,12 +583,12 @@ org.slf4j jcl-over-slf4j - ${slf4j.version} + ${version.org.slf4j} org.slf4j slf4j-jdk14 - ${slf4j.version} + ${version.org.slf4j} @@ -562,7 +624,7 @@ de.thetaphi forbiddenapis - 2.5 + ${version.forbiddenapis.plugin} false @@ -626,7 +688,7 @@ com.mycila license-maven-plugin - 3.0 + ${version.license.plugin}

${hibernate-validator-parent.path}/build-config/src/main/resources/license.header
true @@ -664,19 +726,19 @@ maven-surefire-plugin - ${maven-surefire-plugin.version} + ${version.surefire.plugin} once true **/*Test.java - ${maven-surefire-plugin.argLine} + ${surefire.jvm.args} maven-surefire-report-plugin - ${maven-surefire-plugin.version} + ${version.surefire.plugin} generate-test-report @@ -693,22 +755,22 @@ maven-failsafe-plugin - ${maven-surefire-plugin.version} + ${version.failsafe.plugin} - ${maven-surefire-plugin.argLine} ${maven-surefire-plugin.argLine.add-modules} ${maven-surefire-plugin.argLine.add-opens} + ${failsafe.jvm.args} maven-dependency-plugin - 3.0.2 + ${version.dependency.plugin} maven-install-plugin - 2.5.2 + ${version.install.plugin} maven-assembly-plugin - 3.1.0 + ${version.assembly.plugin} @@ -809,24 +871,24 @@ org.codehaus.gmavenplus gmavenplus-plugin - 1.6 + ${version.gmavenplus.plugin} org.codehaus.groovy groovy-all - ${groovy.version} + ${version.org.codehaus.groovy} org.apache.servicemix.tooling depends-maven-plugin - 1.4.0 + ${version.depends.plugin} org.codehaus.mojo build-helper-maven-plugin - 1.12 + ${version.buildhelper.plugin} com.github.siom79.japicmp japicmp-maven-plugin - 0.11.0 + ${version.japicmp.plugin} @@ -863,50 +925,43 @@ org.apache.maven.plugins maven-shade-plugin - 3.1.0 + ${version.shade.plugin} org.jboss.as patch-gen-maven-plugin - ${wildfly-patch-gen-maven-plugin.version} + ${version.wildfly-patch-gen.plugin} com.fasterxml.woodstox woodstox-core - ${wildfly-patch-gen-maven-plugin.woodstox.version} + ${version.wildfly-patch-gen.plugin.woodstox} org.wildfly.plugins wildfly-maven-plugin - ${wildfly-maven-plugin.version} + ${version.wildfly.plugin} org.wildfly.core wildfly-patching - ${wildfly-core.version} + ${version.org.wildfly.core} - org.wildfly.core wildfly-cli - ${wildfly-core.version} - - - sun.jdk - jconsole - - + ${version.org.wildfly.core} org.netbeans.tools sigtest-maven-plugin - 1.0 + ${version.sigtest.plugin} @@ -1035,18 +1090,18 @@ scm:git:git@github.com:hibernate/hibernate-validator.git http://github.com/hibernate/hibernate-validator HEAD - + - jboss-releases-repository + ${jboss.releases.repo.id} JBoss Releases Repository - https://repository.jboss.org/nexus/service/local/staging/deploy/maven2/ + ${jboss.releases.repo.url} - jboss-snapshots-repository + ${jboss.snapshots.repo.id} JBoss Snapshots Repository - https://repository.jboss.org/nexus/content/repositories/snapshots/ + ${jboss.snapshots.repo.url} @@ -1120,12 +1175,11 @@ [9,) - --add-modules=${maven-surefire-plugin.jigsaw.modules} - + --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED @@ -1140,7 +1194,7 @@ --add-opens=java.management/javax.management=ALL-UNNAMED --add-opens=java.management/javax.management.openmbean=ALL-UNNAMED --add-opens=java.naming/javax.naming=ALL-UNNAMED - + @@ -1151,13 +1205,6 @@ true - - maven-surefire-plugin - ${maven-surefire-plugin.version} - - ${maven-surefire-plugin.argLine} ${maven-surefire-plugin.argLine.add-modules} ${maven-surefire-plugin.argLine.add-opens} - - org.wildfly.plugins wildfly-maven-plugin @@ -1187,7 +1234,7 @@ com.buschmais.jqassistant jqassistant-maven-plugin - 1.3.0 + ${version.jqassistant.plugin} diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 56a4d24c77..d3c3159efd 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -22,7 +22,7 @@ ${project.build.directory}/dependency/beanvalidation-tck-tests-suite.xml - ${project.build.directory}/wildfly-${wildfly-tck.version} + ${project.build.directory}/wildfly-${version.wildfly.tck} org.hibernate.validator.HibernateValidator @@ -58,7 +58,7 @@ org.hibernate.beanvalidation.tck beanvalidation-tck-tests - ${tck.version} + ${version.org.hibernate.beanvalidation.tck} org.jboss.test-audit @@ -184,7 +184,7 @@ org.hibernate.beanvalidation.tck beanvalidation-standalone-container-adapter - ${tck.version} + ${version.org.hibernate.beanvalidation.tck} @@ -253,7 +253,7 @@ org.wildfly wildfly-dist - ${wildfly-tck.version} + ${version.wildfly.tck} tar.gz false ${project.build.directory} @@ -273,7 +273,7 @@ ${project.groupId} hibernate-validator-modules ${project.version} - wildfly-${wildfly-tck.version}-patch + wildfly-${version.wildfly.tck}-patch zip ${project.build.directory} @@ -296,7 +296,7 @@ true false - patch apply ${project.build.directory}/hibernate-validator-modules-${project.version}-wildfly-${wildfly-tck.version}-patch.zip + patch apply ${project.build.directory}/hibernate-validator-modules-${project.version}-wildfly-${version.wildfly.tck}-patch.zip @@ -365,7 +365,7 @@ [9,) - --add-opens java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED diff --git a/tck-runner/src/test/resources/arquillian.xml b/tck-runner/src/test/resources/arquillian.xml index ce14b1b50c..700b29110d 100644 --- a/tck-runner/src/test/resources/arquillian.xml +++ b/tck-runner/src/test/resources/arquillian.xml @@ -26,7 +26,7 @@ ${wildfly.target-dir} - ${arquillian.javaVmArguments.add-opens} + ${arquillian.wildfly.jvm.args} -Xmx1024m -XX:MaxPermSize=512m ${remote.debug} -Dvalidation.provider=${validation.provider} From 1d12c34042246a0ed8105a01a61f10414051e816 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 7 Jun 2018 14:43:55 +0200 Subject: [PATCH 042/393] HV-1617 Remove JDK 9 JVM arguments that are now useless for patch-gen --- modules/pom.xml | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/modules/pom.xml b/modules/pom.xml index 294f96c951..b9eacc9ca4 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -34,9 +34,6 @@ ${project.build.directory}/wildfly-patched/wildfly-${version.wildfly.secondary} ${project.build.directory}/wildfly-secondary-hv-patch.zip - - ${patch-gen.jvm.args.add-opens} - .. @@ -282,7 +279,6 @@ generate-patch - ${patch-gen.jvm.args} ${wildfly-main.original.target-dir} ${module.xml.targetdir}/wildfly-current-patch.xml ${wildfly-main.patched.target-dir} @@ -296,7 +292,6 @@ generate-patch - ${patch-gen.jvm.args} ${wildfly-secondary.original.target-dir} ${module.xml.targetdir}/wildfly-secondary-patch.xml ${wildfly-secondary.patched.target-dir} @@ -307,16 +302,4 @@ - - - - jdk9 - - [9,) - - - --add-opens=java.base/java.lang=ALL-UNNAMED - - - From f12d111c560aea37c0bde1c2ed29f1744f16c940 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 8 Jun 2018 14:12:03 +0200 Subject: [PATCH 043/393] HV-1622 Make WildFly 13 our default WildFly target --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 7036fe5f12..e4f4de0de2 100644 --- a/pom.xml +++ b/pom.xml @@ -125,9 +125,9 @@ 2.1.0.Final - 12.0.0.Final + 13.0.0.Final - 11.0.0.Final + 12.0.0.Final ${version.wildfly} @@ -226,7 +226,7 @@ ${version.surefire.plugin} 1.2.1.Final 5.0.0.Final - 2.0.1.Alpha5 + 2.0.1.Final 5.0.3 From b5aa816b9ab74eccb1169759b76ffe0ed3d9d720 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 8 Jun 2018 11:56:31 +0200 Subject: [PATCH 044/393] HV-1628 Use the Java 8 visitors for the annotation processor We used to use the Java 6 ones and they are deprecated in Java 10. --- .../ap/internal/AbstractElementVisitor.java | 4 +-- .../checks/AnnotationTypeMemberCheck.java | 12 ++++---- .../checks/CrossParameterConstraintCheck.java | 14 ++++----- .../checks/GroupSequenceProviderCheck.java | 8 ++--- .../ap/internal/util/AnnotationApiHelper.java | 4 +-- .../ap/internal/util/ConstraintHelper.java | 30 +++++++++---------- 6 files changed, 36 insertions(+), 36 deletions(-) diff --git a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/AbstractElementVisitor.java b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/AbstractElementVisitor.java index b093800b2a..db9cb070a4 100644 --- a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/AbstractElementVisitor.java +++ b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/AbstractElementVisitor.java @@ -10,7 +10,7 @@ import java.util.Set; import javax.lang.model.element.ElementVisitor; -import javax.lang.model.util.ElementKindVisitor6; +import javax.lang.model.util.ElementKindVisitor8; import org.hibernate.validator.ap.internal.checks.ConstraintCheckIssue; import org.hibernate.validator.ap.internal.util.CollectionHelper; @@ -25,7 +25,7 @@ * * @author Marko Bekhta */ -public class AbstractElementVisitor extends ElementKindVisitor6 { +public class AbstractElementVisitor extends ElementKindVisitor8 { protected final MessagerAdapter messager; diff --git a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/checks/AnnotationTypeMemberCheck.java b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/checks/AnnotationTypeMemberCheck.java index b323fef90c..f4196445be 100644 --- a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/checks/AnnotationTypeMemberCheck.java +++ b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/checks/AnnotationTypeMemberCheck.java @@ -17,8 +17,8 @@ import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; import javax.lang.model.type.WildcardType; -import javax.lang.model.util.SimpleAnnotationValueVisitor6; -import javax.lang.model.util.TypeKindVisitor6; +import javax.lang.model.util.SimpleAnnotationValueVisitor8; +import javax.lang.model.util.TypeKindVisitor8; import javax.lang.model.util.Types; import org.hibernate.validator.ap.internal.util.AnnotationApiHelper; @@ -225,13 +225,13 @@ private ExecutableElement getMethod(TypeElement element, String name) { private DeclaredType getComponentTypeOfArrayReturnType(ExecutableElement method) { return method.getReturnType().accept( - new TypeKindVisitor6() { + new TypeKindVisitor8() { @Override public DeclaredType visitArray(ArrayType t, Void p) { return t.getComponentType().accept( - new TypeKindVisitor6() { + new TypeKindVisitor8() { @Override public DeclaredType visitDeclared(DeclaredType t, Void p) { @@ -259,7 +259,7 @@ public DeclaredType visitDeclared(DeclaredType t, Void p) { private boolean validateWildcardBounds(TypeMirror type, final TypeMirror expectedExtendsBound, final TypeMirror expectedSuperBound) { Boolean theValue = type.accept( - new TypeKindVisitor6() { + new TypeKindVisitor8() { @Override public Boolean visitWildcard(WildcardType t, Void p) { @@ -289,7 +289,7 @@ private boolean isEmptyArray(AnnotationValue annotationValue) { return annotationValue != null && Boolean.TRUE.equals( annotationValue.accept( - new SimpleAnnotationValueVisitor6() { + new SimpleAnnotationValueVisitor8() { @Override public Boolean visitArray(List values, Void p) { diff --git a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/checks/CrossParameterConstraintCheck.java b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/checks/CrossParameterConstraintCheck.java index 0bf9e88250..2c24579ef6 100644 --- a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/checks/CrossParameterConstraintCheck.java +++ b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/checks/CrossParameterConstraintCheck.java @@ -15,9 +15,9 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.DeclaredType; -import javax.lang.model.util.ElementKindVisitor6; -import javax.lang.model.util.SimpleAnnotationValueVisitor6; -import javax.lang.model.util.TypeKindVisitor6; +import javax.lang.model.util.ElementKindVisitor8; +import javax.lang.model.util.SimpleAnnotationValueVisitor8; +import javax.lang.model.util.TypeKindVisitor8; import javax.lang.model.util.Types; import org.hibernate.validator.ap.internal.util.AnnotationApiHelper; @@ -61,7 +61,7 @@ public Set checkAnnotationType(TypeElement element, Annota return Collections.emptySet(); } - DeclaredType elementType = element.asType().accept( new TypeKindVisitor6() { + DeclaredType elementType = element.asType().accept( new TypeKindVisitor8() { @Override public DeclaredType visitDeclared(DeclaredType t, Void p) { @@ -135,7 +135,7 @@ private boolean checkValidationAppliesToReturnType(ExecutableElement validationA final DeclaredType constraintTargetType = annotationApiHelper.getDeclaredTypeByName( BeanValidationTypes.CONSTRAINT_TARGET ); // Check the return type - return validationAppliesToMethod.getReturnType().accept( new TypeKindVisitor6() { + return validationAppliesToMethod.getReturnType().accept( new TypeKindVisitor8() { @Override public Boolean visitDeclared(DeclaredType t, Void p) { @@ -153,7 +153,7 @@ private boolean checkValidationAppliesToDefaultValue(ExecutableElement validatio final DeclaredType constraintTargetType = annotationApiHelper.getDeclaredTypeByName( BeanValidationTypes.CONSTRAINT_TARGET ); // Check the return type - return validationAppliesToMethod.getDefaultValue().accept( new SimpleAnnotationValueVisitor6() { + return validationAppliesToMethod.getDefaultValue().accept( new SimpleAnnotationValueVisitor8() { @Override public Boolean visitEnumConstant(VariableElement c, Void p) { @@ -167,7 +167,7 @@ public Boolean visitEnumConstant(VariableElement c, Void p) { private ExecutableElement getValidationAppliesToMethod(Element annotation) { for ( Element e : annotation.getEnclosedElements() ) { - ExecutableElement method = e.accept( new ElementKindVisitor6() { + ExecutableElement method = e.accept( new ElementKindVisitor8() { @Override public ExecutableElement visitExecutableAsMethod(ExecutableElement e, Void p) { diff --git a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/checks/GroupSequenceProviderCheck.java b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/checks/GroupSequenceProviderCheck.java index 3cadaf801b..9a420a18f5 100644 --- a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/checks/GroupSequenceProviderCheck.java +++ b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/checks/GroupSequenceProviderCheck.java @@ -17,8 +17,8 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.ElementKindVisitor6; -import javax.lang.model.util.SimpleTypeVisitor6; +import javax.lang.model.util.ElementKindVisitor8; +import javax.lang.model.util.SimpleTypeVisitor8; import javax.lang.model.util.Types; import org.hibernate.validator.ap.internal.util.AnnotationApiHelper; @@ -150,7 +150,7 @@ private Set checkAnnotationValue(TypeElement element, Anno */ private boolean hasPublicDefaultConstructor(TypeElement element) { return element.accept( - new ElementKindVisitor6( Boolean.FALSE ) { + new ElementKindVisitor8( Boolean.FALSE ) { @Override public Boolean visitTypeAsClass(TypeElement typeElement, Void aVoid) { @@ -186,7 +186,7 @@ public Boolean visitExecutableAsConstructor(ExecutableElement constructorElement */ private TypeMirror retrieveGenericProviderType(TypeMirror typeMirror) { return typeMirror.accept( - new SimpleTypeVisitor6() { + new SimpleTypeVisitor8() { @Override public TypeMirror visitDeclared(DeclaredType declaredType, Void aVoid) { diff --git a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/AnnotationApiHelper.java b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/AnnotationApiHelper.java index 5040642b8a..b5d8c3ee98 100644 --- a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/AnnotationApiHelper.java +++ b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/AnnotationApiHelper.java @@ -22,7 +22,7 @@ import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; -import javax.lang.model.util.SimpleAnnotationValueVisitor6; +import javax.lang.model.util.SimpleAnnotationValueVisitor8; import javax.lang.model.util.Types; /** @@ -268,7 +268,7 @@ public List getAnnotationArrayValue(AnnotationMirror } List theValue = annotationValue.accept( - new SimpleAnnotationValueVisitor6, Void>() { + new SimpleAnnotationValueVisitor8, Void>() { @Override public List visitArray(List values, Void p) { diff --git a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/ConstraintHelper.java b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/ConstraintHelper.java index 0cc022c357..c390a8f43a 100644 --- a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/ConstraintHelper.java +++ b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/ConstraintHelper.java @@ -44,9 +44,9 @@ import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.ElementKindVisitor6; -import javax.lang.model.util.SimpleAnnotationValueVisitor6; -import javax.lang.model.util.TypeKindVisitor6; +import javax.lang.model.util.ElementKindVisitor8; +import javax.lang.model.util.SimpleAnnotationValueVisitor8; +import javax.lang.model.util.TypeKindVisitor8; import javax.lang.model.util.Types; import org.hibernate.validator.ap.internal.util.TypeNames.BeanValidationTypes; @@ -394,7 +394,7 @@ public List getPartsOfMultiValuedConstraint( .getAnnotationArrayValue( annotationMirror, "value" ) ) { oneValuePart.accept( - new SimpleAnnotationValueVisitor6() { + new SimpleAnnotationValueVisitor8() { @Override public Void visitAnnotation(AnnotationMirror a, Void p) { @@ -454,7 +454,7 @@ public boolean isComposedConstraint(TypeElement element) { return Boolean.TRUE.equals( element.asType().accept( - new TypeKindVisitor6() { + new TypeKindVisitor8() { @Override public Boolean visitDeclared(DeclaredType constraintValidatorImplementation, Void p) { @@ -558,7 +558,7 @@ public ConstraintCheckResult checkCrossParameterTypes(DeclaredType constraintAnn final TypeMirror objectMirror = annotationApiHelper.getMirrorForType( Object.class ); TypeMirror type = determineSupportedType( crossParameterValidator ); - Boolean supported = type.accept( new TypeKindVisitor6() { + Boolean supported = type.accept( new TypeKindVisitor8() { @Override public Boolean visitArray(ArrayType t, Void p) { return typeUtils.isSameType( t.getComponentType(), objectMirror ); @@ -647,7 +647,7 @@ private boolean isMultiValuedConstraint(AnnotationMirror annotationMirror) { for ( AnnotationValue oneAnnotationValue : annotationArrayValue ) { Boolean isConstraintAnnotation = oneAnnotationValue.accept( - new SimpleAnnotationValueVisitor6() { + new SimpleAnnotationValueVisitor8() { @Override public Boolean visitAnnotation( @@ -797,7 +797,7 @@ private AnnotationProcessorConstraintTarget getConstraintTarget(AnnotationMirror for ( Element e : annotation.getAnnotationType().asElement().getEnclosedElements() ) { - Boolean isValidationAppliesToMethod = e.accept( new ElementKindVisitor6() { + Boolean isValidationAppliesToMethod = e.accept( new ElementKindVisitor8() { @Override public Boolean visitExecutableAsMethod(ExecutableElement e, Void p) { if ( e.getSimpleName().contentEquals( "validationAppliesTo" ) ) { @@ -818,7 +818,7 @@ public Boolean visitExecutableAsMethod(ExecutableElement e, Void p) { } return validationAppliesTo.accept( - new SimpleAnnotationValueVisitor6() { + new SimpleAnnotationValueVisitor8() { private final TypeMirror constraintTargetMirror = annotationApiHelper.getDeclaredTypeByName( BeanValidationTypes.CONSTRAINT_TARGET ); @@ -870,7 +870,7 @@ private TypeMirror determineSupportedType(AnnotationValue validatorClassReferenc TypeMirror constraintValidatorImplementation = getConstraintValidatorSuperType( validatorClassReference ); return constraintValidatorImplementation.accept( - new TypeKindVisitor6() { + new TypeKindVisitor8() { @Override public TypeMirror visitDeclared(DeclaredType constraintValidatorImplementation, Void p) { @@ -889,7 +889,7 @@ private boolean isValidationTargetSupported(AnnotationValue oneValidatorClassRef private Set getSupportedValidationTargets(AnnotationValue oneValidatorClassReference) { // determine the class that could contain the @SupportedValidationTarget annotation. TypeMirror validatorClass = oneValidatorClassReference.accept( - new SimpleAnnotationValueVisitor6() { + new SimpleAnnotationValueVisitor8() { @Override public TypeMirror visitType(TypeMirror t, Void p) { @@ -898,7 +898,7 @@ public TypeMirror visitType(TypeMirror t, Void p) { }, null ); - DeclaredType validatorType = validatorClass.accept( new TypeKindVisitor6() { + DeclaredType validatorType = validatorClass.accept( new TypeKindVisitor8() { @Override public DeclaredType visitDeclared(DeclaredType t, Void p) { return t; @@ -925,7 +925,7 @@ public DeclaredType visitDeclared(DeclaredType t, Void p) { else { List values = annotationApiHelper.getAnnotationArrayValue( supportedTargetDecl, "value" ); for ( AnnotationValue val : values ) { - AnnotationProcessorValidationTarget target = val.accept( new SimpleAnnotationValueVisitor6() { + AnnotationProcessorValidationTarget target = val.accept( new SimpleAnnotationValueVisitor8() { @Override public AnnotationProcessorValidationTarget visitEnumConstant(VariableElement c, Void p) { return AnnotationProcessorValidationTarget.valueOf( c.getSimpleName().toString() ); @@ -944,7 +944,7 @@ public AnnotationProcessorValidationTarget visitEnumConstant(VariableElement c, private TypeMirror getConstraintValidatorSuperType(AnnotationValue oneValidatorClassReference) { TypeMirror type = oneValidatorClassReference.accept( - new SimpleAnnotationValueVisitor6() { + new SimpleAnnotationValueVisitor8() { @Override public TypeMirror visitType(TypeMirror t, Void p) { @@ -1009,7 +1009,7 @@ private List getValidatorClassesFromConstraintMetaAnn AnnotationValue validatedBy = annotationApiHelper.getAnnotationValue( constraintMetaAnnotation, "validatedBy" ); return validatedBy.accept( - new SimpleAnnotationValueVisitor6, Void>() { + new SimpleAnnotationValueVisitor8, Void>() { @Override public List visitArray(List values, Void p) { From 7d79a7f26b704bbc8b7eaa68ebcf3e963674d036 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 8 Jun 2018 11:58:45 +0200 Subject: [PATCH 045/393] HV-1628 Be more careful about the locale we use --- .../ap/internal/util/Configuration.java | 23 +++++++++++-------- .../ap/internal/util/MessagerAdapter.java | 6 +++-- .../TypeConstraintMappingContextImpl.java | 3 ++- .../validator/internal/util/Contracts.java | 5 ++-- .../performance/statistical/TestEntity.java | 6 ++++- .../testutil/ConstraintViolationAssert.java | 6 +++-- .../validator/testutil/DescriptorAssert.java | 8 ++++--- 7 files changed, 36 insertions(+), 21 deletions(-) diff --git a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/Configuration.java b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/Configuration.java index f13c3c6ffc..feae0d53f8 100644 --- a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/Configuration.java +++ b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/Configuration.java @@ -6,8 +6,9 @@ */ package org.hibernate.validator.ap.internal.util; -import java.text.MessageFormat; +import java.util.Locale; import java.util.Map; + import javax.annotation.processing.Messager; import javax.tools.Diagnostic.Kind; @@ -97,11 +98,12 @@ private Kind getDiagnosticKindOption(Map options, Messager messa } catch (IllegalArgumentException e) { messager.printMessage( - Kind.WARNING, MessageFormat.format( - "The given value {0} is no valid diagnostic kind. {1} will be used.", - diagnosticKindFromOptions, - DEFAULT_DIAGNOSTIC_KIND - ) + Kind.WARNING, String.format( + Locale.ROOT, + "The given value %1$s is no valid diagnostic kind. %2$s will be used.", + diagnosticKindFromOptions, + DEFAULT_DIAGNOSTIC_KIND + ) ); } } @@ -118,10 +120,11 @@ private boolean getVerboseOption(Map options, Messager messager) if ( theValue ) { messager.printMessage( - Kind.NOTE, MessageFormat.format( - "Verbose reporting is activated. Some processing information will be displayed using diagnostic kind {0}.", - Kind.NOTE - ) + Kind.NOTE, String.format( + Locale.ROOT, + "Verbose reporting is activated. Some processing information will be displayed using diagnostic kind %1$s.", + Kind.NOTE + ) ); } diff --git a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/MessagerAdapter.java b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/MessagerAdapter.java index 5c6e26b8f0..23a3849d2b 100644 --- a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/MessagerAdapter.java +++ b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/MessagerAdapter.java @@ -8,6 +8,7 @@ import java.text.MessageFormat; import java.util.Collection; +import java.util.Locale; import java.util.ResourceBundle; import javax.annotation.processing.Messager; @@ -45,7 +46,7 @@ public MessagerAdapter(Messager messager, Kind diagnosticKind) { this.messager = messager; this.diagnosticKind = diagnosticKind; - errorMessages = ResourceBundle.getBundle( "org.hibernate.validator.ap.ValidationProcessorMessages" ); + errorMessages = ResourceBundle.getBundle( "org.hibernate.validator.ap.ValidationProcessorMessages", Locale.getDefault() ); } /** @@ -114,7 +115,8 @@ private void report(ConstraintCheckIssue issue, Kind kind) { String message = errorMessages.getString( issue.getMessageKey() ); if ( issue.getMessageParameters() != null ) { - message = MessageFormat.format( message, issue.getMessageParameters() ); + MessageFormat messageFormat = new MessageFormat( message, Locale.getDefault() ); + message = messageFormat.format( issue.getMessageParameters() ); } messager.printMessage( diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java index a9037848ab..63275fc6aa 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java @@ -18,6 +18,7 @@ import java.security.PrivilegedAction; import java.util.Arrays; import java.util.List; +import java.util.Locale; import java.util.Set; import org.hibernate.validator.cfg.ConstraintDef; @@ -269,7 +270,7 @@ private Member getMember(Class clazz, String property, ElementType elementTyp member = run( GetDeclaredField.action( clazz, property ) ); } else { - String methodName = property.substring( 0, 1 ).toUpperCase() + property.substring( 1 ); + String methodName = property.substring( 0, 1 ).toUpperCase( Locale.ROOT ) + property.substring( 1 ); for ( String prefix : ReflectionHelper.PROPERTY_ACCESSOR_PREFIXES ) { member = run( GetMethod.action( clazz, prefix + methodName ) ); if ( member != null ) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/Contracts.java b/engine/src/main/java/org/hibernate/validator/internal/util/Contracts.java index a5867276a9..dc57395795 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/Contracts.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/Contracts.java @@ -10,6 +10,7 @@ import java.lang.invoke.MethodHandles; import java.util.Collection; +import java.util.Locale; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -69,7 +70,7 @@ public static void assertTrue(boolean condition, String message) { public static void assertTrue(boolean condition, String message, Object... messageParameters) { if ( !condition ) { - throw LOG.getIllegalArgumentException( String.format( message, messageParameters ) ); + throw LOG.getIllegalArgumentException( String.format( Locale.ROOT, message, messageParameters ) ); } } @@ -87,7 +88,7 @@ public static void assertNotEmpty(Collection collection, String message) { public static void assertNotEmpty(Collection collection, String message, Object... messageParameters) { if ( collection.size() == 0 ) { - throw LOG.getIllegalArgumentException( String.format( message, messageParameters ) ); + throw LOG.getIllegalArgumentException( String.format( Locale.ROOT, message, messageParameters ) ); } } } diff --git a/performance/src/main/java/org/hibernate/validator/performance/statistical/TestEntity.java b/performance/src/main/java/org/hibernate/validator/performance/statistical/TestEntity.java index 7d484f5bd8..9bca4a9df5 100644 --- a/performance/src/main/java/org/hibernate/validator/performance/statistical/TestEntity.java +++ b/performance/src/main/java/org/hibernate/validator/performance/statistical/TestEntity.java @@ -7,9 +7,13 @@ package org.hibernate.validator.performance.statistical; import java.math.BigDecimal; +import java.time.ZoneId; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.TimeZone; + import javax.validation.Valid; import javax.validation.constraints.AssertFalse; import javax.validation.constraints.AssertTrue; @@ -28,7 +32,7 @@ */ public class TestEntity { public static final int MAX_DEPTH = 10; - private static final Calendar cal = GregorianCalendar.getInstance(); + private static final Calendar cal = GregorianCalendar.getInstance( TimeZone.getTimeZone( ZoneId.of( "GMT" ) ), Locale.ROOT ); public TestEntity(int depth) { if ( depth <= MAX_DEPTH ) { diff --git a/test-utils/src/main/java/org/hibernate/validator/testutil/ConstraintViolationAssert.java b/test-utils/src/main/java/org/hibernate/validator/testutil/ConstraintViolationAssert.java index ae8830cd19..1316865371 100644 --- a/test-utils/src/main/java/org/hibernate/validator/testutil/ConstraintViolationAssert.java +++ b/test-utils/src/main/java/org/hibernate/validator/testutil/ConstraintViolationAssert.java @@ -14,6 +14,7 @@ import java.util.Arrays; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.Set; import java.util.stream.Collectors; @@ -272,7 +273,8 @@ public void containsOnlyViolations(ViolationExpectation... expectedViolations) { referencePropertiesToTest = expectedViolations[0].propertiesToTest; for ( ViolationExpectation expectedViolation : expectedViolations ) { if ( !referencePropertiesToTest.equals( expectedViolation.propertiesToTest ) ) { - throw new IllegalArgumentException( String.format( "Expected violations passed in parameter must test the exact same properties but do not: %1$s != %2$s", + throw new IllegalArgumentException( String.format( Locale.ROOT, + "Expected violations passed in parameter must test the exact same properties but do not: %1$s != %2$s", expectedViolations[0], expectedViolation ) ); } } @@ -309,7 +311,7 @@ public void containsPath(PathExpectation expectedPath) { actualPaths.add( actual ); } - fail( String.format( "Didn't find path <%s> in actual paths <%s>.", expectedPath, actualPaths ) ); + fail( String.format( Locale.ROOT, "Didn't find path <%s> in actual paths <%s>.", expectedPath, actualPaths ) ); } public void containsPaths(PathExpectation... expectedPaths) { diff --git a/test-utils/src/main/java/org/hibernate/validator/testutil/DescriptorAssert.java b/test-utils/src/main/java/org/hibernate/validator/testutil/DescriptorAssert.java index 873b52c7e5..0fc8c8f1e1 100644 --- a/test-utils/src/main/java/org/hibernate/validator/testutil/DescriptorAssert.java +++ b/test-utils/src/main/java/org/hibernate/validator/testutil/DescriptorAssert.java @@ -8,11 +8,13 @@ import static org.testng.Assert.fail; -import org.assertj.core.api.IterableAssert; - +import java.util.Locale; import java.util.Set; + import javax.validation.metadata.GroupConversionDescriptor; +import org.assertj.core.api.IterableAssert; + /** * Provides assertion methods for testing {@link javax.validation.metadata.ElementDescriptor} * implementations and collections thereof. @@ -54,7 +56,7 @@ public void containsConversion(Class from, Class to) { } if ( !foundMatchingConversion ) { - fail( String.format( "<%s> does not contain a conversion from <%s> to <%s>.", actual, from, to ) ); + fail( String.format( Locale.ROOT, "<%s> does not contain a conversion from <%s> to <%s>.", actual, from, to ) ); } } } From 2cf106069525af26d47f4297e1390d1c066c052b Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 8 Jun 2018 11:59:32 +0200 Subject: [PATCH 046/393] HV-1628 Remove calls to the deprecated AccessibleObject#isAccessible() method These calls are useless as we now only call it once per element and the element can't be already marked as accessible. --- .../internal/metadata/aggregated/FieldCascadable.java | 8 +------- .../internal/metadata/aggregated/PropertyMetaData.java | 7 +------ .../metadata/location/FieldConstraintLocation.java | 7 +------ .../metadata/location/GetterConstraintLocation.java | 8 +------- 4 files changed, 4 insertions(+), 26 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java index 59c433f01c..6ca82faea5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java @@ -7,7 +7,6 @@ package org.hibernate.validator.internal.metadata.aggregated; import java.lang.annotation.ElementType; -import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.Type; import java.security.AccessController; @@ -85,14 +84,9 @@ public FieldCascadable build() { } /** - * Returns an accessible version of the given member. Will be the given member itself in case it is accessible, - * otherwise a copy which is set accessible. + * Returns an accessible copy of the given member. */ private Field getAccessible(Field original) { - if ( ( (AccessibleObject) original ).isAccessible() ) { - return original; - } - SecurityManager sm = System.getSecurityManager(); if ( sm != null ) { sm.checkPermission( HibernateValidatorPermission.ACCESS_PRIVATE_MEMBERS ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java index df31d488eb..f616e8e923 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java @@ -323,14 +323,9 @@ else if ( constrainedElement.getKind() == ConstrainedElementKind.METHOD ) { } /** - * Returns an accessible version of the given member. Will be the given member itself in case it is accessible, - * otherwise a copy which is set accessible. + * Returns an accessible copy of the given member. */ private Method getAccessible(Method original) { - if ( original.isAccessible() ) { - return original; - } - SecurityManager sm = System.getSecurityManager(); if ( sm != null ) { sm.checkPermission( HibernateValidatorPermission.ACCESS_PRIVATE_MEMBERS ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java index 5b88190ba6..4e8c21f963 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java @@ -116,14 +116,9 @@ public int hashCode() { } /** - * Returns an accessible version of the given member. Will be the given member itself in case it is accessible, - * otherwise a copy which is set accessible. + * Returns an accessible copy of the given member. */ private static Field getAccessible(Field original) { - if ( original.isAccessible() ) { - return original; - } - SecurityManager sm = System.getSecurityManager(); if ( sm != null ) { sm.checkPermission( HibernateValidatorPermission.ACCESS_PRIVATE_MEMBERS ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java index 3e3aa8fe6a..129772a320 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java @@ -6,7 +6,6 @@ */ package org.hibernate.validator.internal.metadata.location; -import java.lang.reflect.AccessibleObject; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.security.AccessController; @@ -125,14 +124,9 @@ public int hashCode() { } /** - * Returns an accessible version of the given method. Will be the given method itself in case it is accessible, - * otherwise a copy which is set accessible. + * Returns an accessible copy of the given method. */ private static Method getAccessible(Method original) { - if ( ( (AccessibleObject) original ).isAccessible() ) { - return original; - } - SecurityManager sm = System.getSecurityManager(); if ( sm != null ) { sm.checkPermission( HibernateValidatorPermission.ACCESS_PRIVATE_MEMBERS ); From 0880b8b54bacf87be560ffb23b26b1eaa3f01747 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 8 Jun 2018 12:01:03 +0200 Subject: [PATCH 047/393] HV-1628 Remove deprecated call to Class#newInstance() --- .../internal/util/privilegedactions/NewInstance.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/NewInstance.java b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/NewInstance.java index 92404467a9..8951907f44 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/NewInstance.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/NewInstance.java @@ -7,6 +7,7 @@ package org.hibernate.validator.internal.util.privilegedactions; import java.lang.invoke.MethodHandles; +import java.lang.reflect.InvocationTargetException; import java.security.PrivilegedAction; import org.hibernate.validator.internal.util.logging.Log; @@ -37,9 +38,9 @@ private NewInstance(Class clazz, String message) { @Override public T run() { try { - return clazz.newInstance(); + return clazz.getConstructor().newInstance(); } - catch (InstantiationException e) { + catch (InstantiationException | NoSuchMethodException | InvocationTargetException e) { throw LOG.getUnableToInstantiateException( message, clazz, e ); } catch (IllegalAccessException e) { From 759a22fcdd38678a2957440e57f4574da8facd44 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 8 Jun 2018 12:01:34 +0200 Subject: [PATCH 048/393] HV-1628 Add a NewProxyInstance privileged action --- .../util/annotation/AnnotationFactory.java | 33 ++----------- .../privilegedactions/NewProxyInstance.java | 49 +++++++++++++++++++ 2 files changed, 53 insertions(+), 29 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/NewProxyInstance.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/annotation/AnnotationFactory.java b/engine/src/main/java/org/hibernate/validator/internal/util/annotation/AnnotationFactory.java index 9bd6c9270e..973137a018 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/annotation/AnnotationFactory.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/annotation/AnnotationFactory.java @@ -7,16 +7,11 @@ package org.hibernate.validator.internal.util.annotation; import java.lang.annotation.Annotation; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Proxy; import java.security.AccessController; import java.security.PrivilegedAction; -import org.hibernate.validator.internal.util.privilegedactions.ConstructorInstance; import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader; -import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredConstructor; +import org.hibernate.validator.internal.util.privilegedactions.NewProxyInstance; /** * Creates live annotations (actually {@link AnnotationProxy} instances) from {@code AnnotationDescriptor}s. @@ -32,31 +27,11 @@ private AnnotationFactory() { } public static T create(AnnotationDescriptor descriptor) { - @SuppressWarnings("unchecked") - Class proxyClass = (Class) Proxy.getProxyClass( + return run( NewProxyInstance.action( run( GetClassLoader.fromClass( descriptor.getType() ) ), - descriptor.getType() - ); - InvocationHandler handler = new AnnotationProxy( descriptor ); - try { - return getProxyInstance( proxyClass, handler ); - } - catch (RuntimeException e) { - throw e; - } - catch (Exception e) { - throw new RuntimeException( e ); - } - } - - private static T getProxyInstance(Class proxyClass, InvocationHandler handler) throws - SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, - IllegalAccessException, InvocationTargetException { - final Constructor constructor = run( GetDeclaredConstructor.action( - proxyClass, - InvocationHandler.class + descriptor.getType(), + new AnnotationProxy( descriptor ) ) ); - return run( ConstructorInstance.action( constructor, handler ) ); } /** diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/NewProxyInstance.java b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/NewProxyInstance.java new file mode 100644 index 0000000000..46dfbf2bee --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/NewProxyInstance.java @@ -0,0 +1,49 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.util.privilegedactions; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; +import java.security.PrivilegedAction; + +/** + * Execute proxy creation as privileged action. + * + * @author Guillaume Smet + */ +public final class NewProxyInstance implements PrivilegedAction { + + private final ClassLoader classLoader; + private final Class[] interfaces; + private final InvocationHandler invocationHandler; + + public static NewProxyInstance action(ClassLoader classLoader, Class interfaze, InvocationHandler invocationHandler) { + return new NewProxyInstance( classLoader, interfaze, invocationHandler ); + } + + public static NewProxyInstance action(ClassLoader classLoader, Class[] interfaces, InvocationHandler invocationHandler) { + return new NewProxyInstance( classLoader, interfaces, invocationHandler ); + } + + private NewProxyInstance(ClassLoader classLoader, Class[] interfaces, InvocationHandler invocationHandler) { + this.classLoader = classLoader; + this.interfaces = interfaces; + this.invocationHandler = invocationHandler; + } + + private NewProxyInstance(ClassLoader classLoader, Class interfaze, InvocationHandler invocationHandler) { + this.classLoader = classLoader; + this.interfaces = new Class[] { interfaze }; + this.invocationHandler = invocationHandler; + } + + @SuppressWarnings("unchecked") + @Override + public T run() { + return (T) Proxy.newProxyInstance( classLoader, interfaces, invocationHandler ); + } +} From a5a68192c6a8091477a7dfa261b42546407bc2eb Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 8 Jun 2018 12:19:29 +0200 Subject: [PATCH 049/393] HV-1628 Mark the classes using JavaFX as ignored by forbidden-apis --- .../engine/valueextraction/ListPropertyValueExtractor.java | 2 ++ .../engine/valueextraction/MapPropertyKeyExtractor.java | 2 ++ .../engine/valueextraction/MapPropertyValueExtractor.java | 2 ++ .../engine/valueextraction/ObservableValueValueExtractor.java | 3 +++ .../valueextraction/ReadOnlyListPropertyValueExtractor.java | 2 ++ .../valueextraction/ReadOnlyMapPropertyKeyExtractor.java | 2 ++ .../valueextraction/ReadOnlyMapPropertyValueExtractor.java | 2 ++ .../valueextraction/ReadOnlySetPropertyValueExtractor.java | 2 ++ .../engine/valueextraction/SetPropertyValueExtractor.java | 2 ++ 9 files changed, 19 insertions(+) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ListPropertyValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ListPropertyValueExtractor.java index 59b691b8fc..bcccb67566 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ListPropertyValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ListPropertyValueExtractor.java @@ -11,6 +11,7 @@ import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; +import org.hibernate.validator.internal.IgnoreForbiddenApisErrors; import org.hibernate.validator.internal.engine.path.NodeImpl; import javafx.beans.property.ListProperty; @@ -25,6 +26,7 @@ * @author Guillaume Smet */ @SuppressWarnings("restriction") +@IgnoreForbiddenApisErrors(reason = "Usage of JavaFX classes") class ListPropertyValueExtractor implements ValueExtractor> { static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ListPropertyValueExtractor() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapPropertyKeyExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapPropertyKeyExtractor.java index e2b507fae0..bbd5dc7bc4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapPropertyKeyExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapPropertyKeyExtractor.java @@ -11,6 +11,7 @@ import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; +import org.hibernate.validator.internal.IgnoreForbiddenApisErrors; import org.hibernate.validator.internal.engine.path.NodeImpl; import javafx.beans.property.MapProperty; @@ -25,6 +26,7 @@ * @author Guillaume Smet */ @SuppressWarnings("restriction") +@IgnoreForbiddenApisErrors(reason = "Usage of JavaFX classes") class MapPropertyKeyExtractor implements ValueExtractor> { static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new MapPropertyKeyExtractor() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapPropertyValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapPropertyValueExtractor.java index 0db1b74ba4..179ed8e51b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapPropertyValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapPropertyValueExtractor.java @@ -11,6 +11,7 @@ import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; +import org.hibernate.validator.internal.IgnoreForbiddenApisErrors; import org.hibernate.validator.internal.engine.path.NodeImpl; import javafx.beans.property.MapProperty; @@ -25,6 +26,7 @@ * @author Guillaume Smet */ @SuppressWarnings("restriction") +@IgnoreForbiddenApisErrors(reason = "Usage of JavaFX classes") class MapPropertyValueExtractor implements ValueExtractor> { static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new MapPropertyValueExtractor() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ObservableValueValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ObservableValueValueExtractor.java index 986ed2b559..12232824d0 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ObservableValueValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ObservableValueValueExtractor.java @@ -10,6 +10,8 @@ import javax.validation.valueextraction.UnwrapByDefault; import javax.validation.valueextraction.ValueExtractor; +import org.hibernate.validator.internal.IgnoreForbiddenApisErrors; + import javafx.beans.value.ObservableValue; /** @@ -18,6 +20,7 @@ * @author Gunnar Morling */ @SuppressWarnings("restriction") +@IgnoreForbiddenApisErrors(reason = "Usage of JavaFX classes") @UnwrapByDefault class ObservableValueValueExtractor implements ValueExtractor> { diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyListPropertyValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyListPropertyValueExtractor.java index e91f838030..e003c52245 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyListPropertyValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyListPropertyValueExtractor.java @@ -11,6 +11,7 @@ import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; +import org.hibernate.validator.internal.IgnoreForbiddenApisErrors; import org.hibernate.validator.internal.engine.path.NodeImpl; import javafx.beans.property.ReadOnlyListProperty; @@ -25,6 +26,7 @@ * @author Guillaume Smet */ @SuppressWarnings("restriction") +@IgnoreForbiddenApisErrors(reason = "Usage of JavaFX classes") class ReadOnlyListPropertyValueExtractor implements ValueExtractor> { static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ReadOnlyListPropertyValueExtractor() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyMapPropertyKeyExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyMapPropertyKeyExtractor.java index 6632054deb..c98cefd76f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyMapPropertyKeyExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyMapPropertyKeyExtractor.java @@ -11,6 +11,7 @@ import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; +import org.hibernate.validator.internal.IgnoreForbiddenApisErrors; import org.hibernate.validator.internal.engine.path.NodeImpl; import javafx.beans.property.ReadOnlyMapProperty; @@ -25,6 +26,7 @@ * @author Guillaume Smet */ @SuppressWarnings("restriction") +@IgnoreForbiddenApisErrors(reason = "Usage of JavaFX classes") class ReadOnlyMapPropertyKeyExtractor implements ValueExtractor> { static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ReadOnlyMapPropertyKeyExtractor() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyMapPropertyValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyMapPropertyValueExtractor.java index 4217177d4d..e843400dd0 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyMapPropertyValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyMapPropertyValueExtractor.java @@ -11,6 +11,7 @@ import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; +import org.hibernate.validator.internal.IgnoreForbiddenApisErrors; import org.hibernate.validator.internal.engine.path.NodeImpl; import javafx.beans.property.ReadOnlyMapProperty; @@ -25,6 +26,7 @@ * @author Guillaume Smet */ @SuppressWarnings("restriction") +@IgnoreForbiddenApisErrors(reason = "Usage of JavaFX classes") class ReadOnlyMapPropertyValueExtractor implements ValueExtractor> { static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ReadOnlyMapPropertyValueExtractor() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlySetPropertyValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlySetPropertyValueExtractor.java index 1366eebdd0..18635dc017 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlySetPropertyValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlySetPropertyValueExtractor.java @@ -11,6 +11,7 @@ import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; +import org.hibernate.validator.internal.IgnoreForbiddenApisErrors; import org.hibernate.validator.internal.engine.path.NodeImpl; import javafx.beans.property.ReadOnlySetProperty; @@ -25,6 +26,7 @@ * @author Guillaume Smet */ @SuppressWarnings("restriction") +@IgnoreForbiddenApisErrors(reason = "Usage of JavaFX classes") class ReadOnlySetPropertyValueExtractor implements ValueExtractor> { static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ReadOnlySetPropertyValueExtractor() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/SetPropertyValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/SetPropertyValueExtractor.java index e7847ddd0e..bcd0d9b55b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/SetPropertyValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/SetPropertyValueExtractor.java @@ -11,6 +11,7 @@ import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; +import org.hibernate.validator.internal.IgnoreForbiddenApisErrors; import org.hibernate.validator.internal.engine.path.NodeImpl; import javafx.beans.property.SetProperty; @@ -25,6 +26,7 @@ * @author Guillaume Smet */ @SuppressWarnings("restriction") +@IgnoreForbiddenApisErrors(reason = "Usage of JavaFX classes") class SetPropertyValueExtractor implements ValueExtractor> { static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new SetPropertyValueExtractor() ); From 47e91bf1abe69d9d50413ca66e06393c0974757e Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 8 Jun 2018 12:04:40 +0200 Subject: [PATCH 050/393] HV-1628 Stricter forbidden-apis configuration Also target Java 10 for the deprecation target. --- pom.xml | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index e4f4de0de2..21d92ea0f8 100644 --- a/pom.xml +++ b/pom.xml @@ -262,6 +262,8 @@ ${maven.compiler.testTarget} ${maven.compiler.testSource} + 10 + @@ -626,6 +628,7 @@ forbiddenapis ${version.forbiddenapis.plugin} + ${forbiddenapis.jdk.target} false @@ -657,13 +660,11 @@ verify - + jdk-unsafe jdk-deprecated - jdk-system-out + jdk-non-portable + jdk-internal @@ -675,10 +676,6 @@ verify - jdk-deprecated From 1f3d1c6fc6ac67f5162a972112a76e6ae4e97a01 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Sat, 10 Mar 2018 14:29:50 +0100 Subject: [PATCH 051/393] HV-1623 Build abstraction over reflection in ConstraintLocation and related code --- .../cfg/context/ConfiguredConstraint.java | 41 ++-- .../ConstraintMappingContextImplBase.java | 2 +- ...nstructorConstraintMappingContextImpl.java | 7 +- ...erElementConstraintMappingContextImpl.java | 2 +- ...ParameterConstraintMappingContextImpl.java | 4 +- ...xecutableConstraintMappingContextImpl.java | 31 ++- .../MethodConstraintMappingContextImpl.java | 9 +- ...ParameterConstraintMappingContextImpl.java | 15 +- .../PropertyConstraintMappingContextImpl.java | 37 ++-- ...turnValueConstraintMappingContextImpl.java | 14 +- .../TypeConstraintMappingContextImpl.java | 49 +++-- .../engine/ConstraintViolationImpl.java | 7 - .../PropertyValidationContext.java | 10 +- .../metadata/aggregated/BeanMetaDataImpl.java | 7 +- .../aggregated/ExecutableMetaData.java | 49 +++-- .../metadata/aggregated/FieldCascadable.java | 110 ----------- .../metadata/aggregated/MetaDataBuilder.java | 2 +- .../aggregated/ParameterMetaData.java | 14 +- ...ascadable.java => PropertyCascadable.java} | 38 ++-- .../metadata/aggregated/PropertyMetaData.java | 51 +++-- .../rule/MethodConfigurationRule.java | 8 +- ...ethodMustNotAlterParameterConstraints.java | 4 +- ...GroupConversionForCascadedReturnValue.java | 4 +- ...hodsMustNotDefineParameterConstraints.java | 4 +- ...eMarkedOnceAsCascadedPerHierarchyLine.java | 4 +- ...ethodsMustNotBeReturnValueConstrained.java | 7 +- .../core/AnnotationProcessingOptions.java | 10 +- .../core/AnnotationProcessingOptionsImpl.java | 60 +++--- .../descriptor/ConstraintDescriptorImpl.java | 91 +++------ .../location/BeanConstraintLocation.java | 4 +- .../metadata/location/ConstraintLocation.java | 52 ++--- .../CrossParameterConstraintLocation.java | 30 ++- .../location/ParameterConstraintLocation.java | 33 ++-- .../location/PropertyConstraintLocation.java | 88 +++++++++ .../ReturnValueConstraintLocation.java | 33 ++-- .../TypeArgumentConstraintLocation.java | 6 +- .../provider/AnnotationMetaDataProvider.java | 126 ++++++------ .../metadata/raw/ConstrainedExecutable.java | 50 ++--- .../metadata/raw/ConstrainedField.java | 39 ++-- .../metadata/raw/ConstrainedParameter.java | 31 ++- .../internal/properties/Callable.java | 41 ++++ .../internal/properties/Constrainable.java | 31 +++ .../properties/ConstrainableType.java | 16 ++ .../internal/properties/Property.java | 17 ++ .../properties/javabean/JavaBean.java | 37 ++++ .../javabean/JavaBeanExecutable.java | 187 ++++++++++++++++++ .../javabean/JavaBeanField.java} | 86 ++++---- .../javabean/JavaBeanGetter.java} | 97 ++++----- .../properties/javabean/package-info.java | 8 + .../internal/util/ExecutableHelper.java | 5 + .../validator/internal/util/logging/Log.java | 34 ++-- .../formatter/ConstrainableFormatter.java | 39 ++++ .../ConstrainedConstructorStaxBuilder.java | 12 +- .../mapping/ConstrainedFieldStaxBuilder.java | 11 +- .../mapping/ConstrainedGetterStaxBuilder.java | 10 +- .../mapping/ConstrainedMethodStaxBuilder.java | 12 +- .../ConstrainedParameterStaxBuilder.java | 13 +- .../mapping/ConstraintTypeStaxBuilder.java | 4 +- .../mapping/CrossParameterStaxBuilder.java | 8 +- .../xml/mapping/ReturnValueStaxBuilder.java | 17 +- .../test/cfg/ConstraintMappingTest.java | 4 +- .../engine/failfast/FailFastTest.java | 10 +- .../metadata/core/MetaConstraintTest.java | 5 +- .../location/ConstraintLocationTest.java | 5 +- .../AnnotationMetaDataProviderTest.java | 13 +- .../AnnotationMetaDataProviderTestBase.java | 17 +- .../testutil/ConstraintViolationAssert.java | 17 +- 67 files changed, 1091 insertions(+), 848 deletions(-) delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java rename engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/{GetterCascadable.java => PropertyCascadable.java} (60%) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/Callable.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/Constrainable.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/ConstrainableType.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/Property.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBean.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java rename engine/src/main/java/org/hibernate/validator/internal/{metadata/location/FieldConstraintLocation.java => properties/javabean/JavaBeanField.java} (52%) rename engine/src/main/java/org/hibernate/validator/internal/{metadata/location/GetterConstraintLocation.java => properties/javabean/JavaBeanGetter.java} (52%) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/javabean/package-info.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/util/logging/formatter/ConstrainableFormatter.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java index 8f338757fe..3f47510fca 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java @@ -10,10 +10,6 @@ import java.lang.annotation.ElementType; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; -import java.lang.reflect.Executable; -import java.lang.reflect.Field; -import java.lang.reflect.Member; -import java.lang.reflect.Method; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.security.AccessController; @@ -24,7 +20,9 @@ import org.hibernate.validator.cfg.AnnotationDef; import org.hibernate.validator.cfg.ConstraintDef; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.util.ExecutableHelper; +import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.javabean.JavaBeanField; import org.hibernate.validator.internal.util.annotation.AnnotationDescriptor; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.internal.util.logging.Log; @@ -58,42 +56,33 @@ static ConfiguredConstraint forType(ConstraintDef( constraint, ConstraintLocation.forClass( beanType ), ElementType.TYPE ); } - static ConfiguredConstraint forProperty(ConstraintDef constraint, Member member) { - if ( member instanceof Field ) { - return new ConfiguredConstraint<>( - constraint, - ConstraintLocation.forField( (Field) member ), - ElementType.FIELD - ); - } - else { - return new ConfiguredConstraint<>( + static ConfiguredConstraint forProperty(ConstraintDef constraint, Property property) { + return new ConfiguredConstraint<>( constraint, - ConstraintLocation.forGetter( (Method) member ), - ElementType.METHOD - ); - } + ConstraintLocation.forProperty( property ), + property instanceof JavaBeanField ? ElementType.FIELD : ElementType.METHOD + ); } - public static ConfiguredConstraint forParameter(ConstraintDef constraint, Executable executable, int parameterIndex) { + public static ConfiguredConstraint forParameter(ConstraintDef constraint, Callable callable, int parameterIndex) { return new ConfiguredConstraint<>( - constraint, ConstraintLocation.forParameter( executable, parameterIndex ), ExecutableHelper.getElementType( executable ) + constraint, ConstraintLocation.forParameter( callable, parameterIndex ), callable.isConstructor() ? ElementType.CONSTRUCTOR : ElementType.METHOD ); } - public static ConfiguredConstraint forExecutable(ConstraintDef constraint, Executable executable) { + public static ConfiguredConstraint forExecutable(ConstraintDef constraint, Callable callable) { return new ConfiguredConstraint<>( - constraint, ConstraintLocation.forReturnValue( executable ), ExecutableHelper.getElementType( executable ) + constraint, ConstraintLocation.forReturnValue( callable ), callable.isConstructor() ? ElementType.CONSTRUCTOR : ElementType.METHOD ); } - public static ConfiguredConstraint forCrossParameter(ConstraintDef constraint, Executable executable) { + public static ConfiguredConstraint forCrossParameter(ConstraintDef constraint, Callable callable) { return new ConfiguredConstraint<>( - constraint, ConstraintLocation.forCrossParameter( executable ), ExecutableHelper.getElementType( executable ) + constraint, ConstraintLocation.forCrossParameter( callable ), callable.isConstructor() ? ElementType.CONSTRUCTOR : ElementType.METHOD ); } - public static ConfiguredConstraint forTypeArgument(ConstraintDef constraint,ConstraintLocation delegate, TypeVariable typeArgument, Type typeOfAnnotatedElement) { + public static ConfiguredConstraint forTypeArgument(ConstraintDef constraint, ConstraintLocation delegate, TypeVariable typeArgument, Type typeOfAnnotatedElement) { return new ConfiguredConstraint<>( constraint, ConstraintLocation.forTypeArgument( delegate, typeArgument, typeOfAnnotatedElement ), diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintMappingContextImplBase.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintMappingContextImplBase.java index 3eb7a9c92c..ec6257bd05 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintMappingContextImplBase.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintMappingContextImplBase.java @@ -73,7 +73,7 @@ private MetaConstraint asMetaConstraint(ConfiguredCons TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl( constraintHelper, - config.getLocation().getMember(), + config.getLocation().getConstrainable(), config.createAnnotationDescriptor(), config.getElementType(), getConstraintType() diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstructorConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstructorConstraintMappingContextImpl.java index 7f9683a57a..2b71b966a4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstructorConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstructorConstraintMappingContextImpl.java @@ -6,9 +6,8 @@ */ package org.hibernate.validator.internal.cfg.context; -import java.lang.reflect.Constructor; - import org.hibernate.validator.cfg.context.ConstructorConstraintMappingContext; +import org.hibernate.validator.internal.properties.Callable; /** * Constraint mapping creational context representing a constructor. @@ -17,7 +16,7 @@ */ class ConstructorConstraintMappingContextImpl extends ExecutableConstraintMappingContextImpl implements ConstructorConstraintMappingContext { - ConstructorConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, Constructor constructor) { + ConstructorConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, Callable constructor) { super( typeContext, constructor ); } @@ -25,7 +24,7 @@ ConstructorConstraintMappingContextImpl(TypeConstraintMappingContextImpl public ConstructorConstraintMappingContext ignoreAnnotations(boolean ignoreAnnotations) { typeContext.mapping .getAnnotationProcessingOptions() - .ignoreConstraintAnnotationsOnMember( executable, ignoreAnnotations ); + .ignoreConstraintAnnotationsOnMember( callable, ignoreAnnotations ); return this; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java index cf33e40d86..755b09f7ce 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java @@ -237,7 +237,7 @@ private MetaConstraint asMetaConstraint(ConfiguredCons TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl<>( constraintHelper, - config.getLocation().getMember(), + config.getLocation().getConstrainable(), config.createAnnotationDescriptor(), config.getElementType(), getConstraintType() diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/CrossParameterConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/CrossParameterConstraintMappingContextImpl.java index 8cae876274..d1247c09eb 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/CrossParameterConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/CrossParameterConstraintMappingContextImpl.java @@ -32,14 +32,14 @@ final class CrossParameterConstraintMappingContextImpl @Override public CrossParameterConstraintMappingContext constraint(ConstraintDef definition) { - super.addConstraint( ConfiguredConstraint.forCrossParameter( definition, executableContext.getExecutable() ) ); + super.addConstraint( ConfiguredConstraint.forCrossParameter( definition, executableContext.getCallable() ) ); return this; } @Override public CrossParameterConstraintMappingContext ignoreAnnotations(boolean ignoreAnnotations) { mapping.getAnnotationProcessingOptions().ignoreConstraintAnnotationsForCrossParameterConstraint( - executableContext.getExecutable(), ignoreAnnotations + executableContext.getCallable(), ignoreAnnotations ); return this; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ExecutableConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ExecutableConstraintMappingContextImpl.java index 3f2f6d3523..9cb9d826a2 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ExecutableConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ExecutableConstraintMappingContextImpl.java @@ -9,7 +9,6 @@ import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; import java.lang.invoke.MethodHandles; -import java.lang.reflect.Executable; import java.util.Collections; import java.util.List; @@ -24,7 +23,7 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; -import org.hibernate.validator.internal.util.ReflectionHelper; +import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -41,20 +40,20 @@ abstract class ExecutableConstraintMappingContextImpl { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); protected final TypeConstraintMappingContextImpl typeContext; - protected final Executable executable; + protected final Callable callable; private final ParameterConstraintMappingContextImpl[] parameterContexts; private ReturnValueConstraintMappingContextImpl returnValueContext; private CrossParameterConstraintMappingContextImpl crossParameterContext; - protected ExecutableConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, Executable executable) { + protected ExecutableConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, Callable callable) { this.typeContext = typeContext; - this.executable = executable; - this.parameterContexts = new ParameterConstraintMappingContextImpl[executable.getParameterTypes().length]; + this.callable = callable; + this.parameterContexts = new ParameterConstraintMappingContextImpl[callable.getParameterTypes().length]; } public ParameterConstraintMappingContext parameter(int index) { - if ( index < 0 || index >= executable.getParameterTypes().length ) { - throw LOG.getInvalidExecutableParameterIndexException( executable, index ); + if ( index < 0 || index >= callable.getParameterTypes().length ) { + throw LOG.getInvalidExecutableParameterIndexException( callable, index ); } ParameterConstraintMappingContextImpl context = parameterContexts[index]; @@ -62,7 +61,7 @@ public ParameterConstraintMappingContext parameter(int index) { if ( context != null ) { throw LOG.getParameterHasAlreadyBeConfiguredViaProgrammaticApiException( typeContext.getBeanClass(), - executable, + callable, index ); } @@ -76,7 +75,7 @@ public CrossParameterConstraintMappingContext crossParameter() { if ( crossParameterContext != null ) { throw LOG.getCrossParameterElementHasAlreadyBeConfiguredViaProgrammaticApiException( typeContext.getBeanClass(), - executable + callable ); } @@ -88,7 +87,7 @@ public ReturnValueConstraintMappingContext returnValue() { if ( returnValueContext != null ) { throw LOG.getReturnValueHasAlreadyBeConfiguredViaProgrammaticApiException( typeContext.getBeanClass(), - executable + callable ); } @@ -96,8 +95,8 @@ public ReturnValueConstraintMappingContext returnValue() { return returnValueContext; } - public Executable getExecutable() { - return executable; + public Callable getCallable() { + return callable; } public TypeConstraintMappingContextImpl getTypeContext() { @@ -108,7 +107,7 @@ public ConstrainedElement build(ConstraintHelper constraintHelper, TypeResolutio ValueExtractorManager valueExtractorManager) { return new ConstrainedExecutable( ConfigurationSource.API, - executable, + callable, getParameters( constraintHelper, typeResolutionHelper, valueExtractorManager ), crossParameterContext != null ? crossParameterContext.getConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ) : Collections.>emptySet(), returnValueContext != null ? returnValueContext.getConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ) : Collections.>emptySet(), @@ -130,8 +129,8 @@ private List getParameters(ConstraintHelper constraintHelp constrainedParameters.add( new ConstrainedParameter( ConfigurationSource.API, - executable, - ReflectionHelper.typeOf( executable, i ), + callable, + callable.getTypeOfParameter( i ), i ) ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/MethodConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/MethodConstraintMappingContextImpl.java index 6ff256f34a..19e74b27db 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/MethodConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/MethodConstraintMappingContextImpl.java @@ -6,9 +6,8 @@ */ package org.hibernate.validator.internal.cfg.context; -import java.lang.reflect.Method; - import org.hibernate.validator.cfg.context.MethodConstraintMappingContext; +import org.hibernate.validator.internal.properties.Callable; /** * Constraint mapping creational context representing a method. @@ -17,15 +16,15 @@ */ class MethodConstraintMappingContextImpl extends ExecutableConstraintMappingContextImpl implements MethodConstraintMappingContext { - MethodConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, Method method) { - super( typeContext, method ); + MethodConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, Callable callable) { + super( typeContext, callable ); } @Override public MethodConstraintMappingContext ignoreAnnotations(boolean ignoreAnnotations) { typeContext.mapping .getAnnotationProcessingOptions() - .ignoreConstraintAnnotationsOnMember( executable, ignoreAnnotations ); + .ignoreConstraintAnnotationsOnMember( callable, ignoreAnnotations ); return this; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ParameterConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ParameterConstraintMappingContextImpl.java index 5009fc76cd..1f8bc55dc5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ParameterConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ParameterConstraintMappingContextImpl.java @@ -21,7 +21,6 @@ import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; -import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; /** @@ -41,7 +40,7 @@ final class ParameterConstraintMappingContextImpl ParameterConstraintMappingContextImpl(ExecutableConstraintMappingContextImpl executableContext, int parameterIndex) { super( executableContext.getTypeContext().getConstraintMapping(), - executableContext.executable.getGenericParameterTypes()[parameterIndex] + executableContext.callable.getGenericParameterTypes()[parameterIndex] ); this.executableContext = executableContext; @@ -58,7 +57,7 @@ public ParameterConstraintMappingContext constraint(ConstraintDef definiti super.addConstraint( ConfiguredConstraint.forParameter( definition, - executableContext.getExecutable(), + executableContext.getCallable(), parameterIndex ) ); @@ -68,7 +67,7 @@ public ParameterConstraintMappingContext constraint(ConstraintDef definiti @Override public ParameterConstraintMappingContext ignoreAnnotations(boolean ignoreAnnotations) { mapping.getAnnotationProcessingOptions().ignoreConstraintAnnotationsOnParameter( - executableContext.getExecutable(), + executableContext.getCallable(), parameterIndex, ignoreAnnotations ); @@ -105,7 +104,7 @@ public ContainerElementConstraintMappingContext containerElementType() { return super.containerElement( this, executableContext.getTypeContext(), - ConstraintLocation.forParameter( executableContext.getExecutable(), parameterIndex ) + ConstraintLocation.forParameter( executableContext.getCallable(), parameterIndex ) ); } @@ -114,7 +113,7 @@ public ContainerElementConstraintMappingContext containerElementType(int index, return super.containerElement( this, executableContext.getTypeContext(), - ConstraintLocation.forParameter( executableContext.getExecutable(), parameterIndex ), + ConstraintLocation.forParameter( executableContext.getCallable(), parameterIndex ), index, nestedIndexes ); @@ -122,11 +121,11 @@ public ContainerElementConstraintMappingContext containerElementType(int index, public ConstrainedParameter build(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { - Type parameterType = ReflectionHelper.typeOf( executableContext.getExecutable(), parameterIndex ); + Type parameterType = executableContext.getCallable().getTypeOfParameter( parameterIndex ); return new ConstrainedParameter( ConfigurationSource.API, - executableContext.getExecutable(), + executableContext.getCallable(), parameterType, parameterIndex, getConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java index dcb6681ce5..95e51deec5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java @@ -7,10 +7,6 @@ package org.hibernate.validator.internal.cfg.context; import java.lang.annotation.ElementType; -import java.lang.reflect.Executable; -import java.lang.reflect.Field; -import java.lang.reflect.Member; -import java.lang.reflect.Method; import org.hibernate.validator.cfg.ConstraintDef; import org.hibernate.validator.cfg.context.ConstructorConstraintMappingContext; @@ -25,7 +21,9 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; -import org.hibernate.validator.internal.util.ReflectionHelper; +import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.javabean.JavaBeanField; import org.hibernate.validator.internal.util.TypeResolutionHelper; /** @@ -42,19 +40,14 @@ final class PropertyConstraintMappingContextImpl private final TypeConstraintMappingContextImpl typeContext; // either Field or Method - private final Member member; + private final Property property; private final ConstraintLocation location; - PropertyConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, Member member) { - super( typeContext.getConstraintMapping(), ReflectionHelper.typeOf( member ) ); + PropertyConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, Property property) { + super( typeContext.getConstraintMapping(), property.getType() ); this.typeContext = typeContext; - this.member = member; - if ( member instanceof Field ) { - this.location = ConstraintLocation.forField( (Field) member ); - } - else { - this.location = ConstraintLocation.forGetter( (Method) member ); - } + this.property = property; + this.location = ConstraintLocation.forProperty( property ); } @Override @@ -64,17 +57,17 @@ protected PropertyConstraintMappingContextImpl getThis() { @Override public PropertyConstraintMappingContext constraint(ConstraintDef definition) { - if ( member instanceof Field ) { + if ( property instanceof JavaBeanField ) { super.addConstraint( ConfiguredConstraint.forProperty( - definition, member + definition, property ) ); } else { super.addConstraint( ConfiguredConstraint.forExecutable( - definition, (Method) member + definition, property.as( Callable.class ) ) ); } @@ -88,7 +81,7 @@ public PropertyConstraintMappingContext ignoreAnnotations() { @Override public PropertyConstraintMappingContext ignoreAnnotations(boolean ignoreAnnotations) { - mapping.getAnnotationProcessingOptions().ignoreConstraintAnnotationsOnMember( member, ignoreAnnotations ); + mapping.getAnnotationProcessingOptions().ignoreConstraintAnnotationsOnMember( property, ignoreAnnotations ); return this; } @@ -118,10 +111,10 @@ public ContainerElementConstraintMappingContext containerElementType(int index, } ConstrainedElement build(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { - if ( member instanceof Field ) { + if ( property instanceof JavaBeanField ) { return new ConstrainedField( ConfigurationSource.API, - (Field) member, + property, getConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), getTypeArgumentConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), getCascadingMetaDataBuilder() @@ -130,7 +123,7 @@ ConstrainedElement build(ConstraintHelper constraintHelper, TypeResolutionHelper else { return new ConstrainedExecutable( ConfigurationSource.API, - (Executable) member, + property.as( Callable.class ), getConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), getTypeArgumentConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), getCascadingMetaDataBuilder() diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ReturnValueConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ReturnValueConstraintMappingContextImpl.java index df930c5ce6..7b98e80ea1 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ReturnValueConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ReturnValueConstraintMappingContextImpl.java @@ -15,7 +15,6 @@ import org.hibernate.validator.cfg.context.ReturnValueConstraintMappingContext; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.util.ReflectionHelper; /** * Constraint mapping creational context which allows to configure the constraints for one method return value. @@ -31,10 +30,7 @@ final class ReturnValueConstraintMappingContextImpl private final ExecutableConstraintMappingContextImpl executableContext; ReturnValueConstraintMappingContextImpl(ExecutableConstraintMappingContextImpl executableContext) { - super( - executableContext.getTypeContext().getConstraintMapping(), - ReflectionHelper.typeOf( executableContext.getExecutable() ) - ); + super( executableContext.getTypeContext().getConstraintMapping(), executableContext.getCallable().getType() ); this.executableContext = executableContext; } @@ -45,14 +41,14 @@ protected ReturnValueConstraintMappingContext getThis() { @Override public ReturnValueConstraintMappingContext constraint(ConstraintDef definition) { - super.addConstraint( ConfiguredConstraint.forExecutable( definition, executableContext.getExecutable() ) ); + super.addConstraint( ConfiguredConstraint.forExecutable( definition, executableContext.getCallable() ) ); return this; } @Override public ReturnValueConstraintMappingContext ignoreAnnotations(boolean ignoreAnnotations) { mapping.getAnnotationProcessingOptions().ignoreConstraintAnnotationsForReturnValue( - executableContext.getExecutable(), ignoreAnnotations + executableContext.getCallable(), ignoreAnnotations ); return this; } @@ -80,7 +76,7 @@ public ConstructorConstraintMappingContext constructor(Class... parameterType @Override public ContainerElementConstraintMappingContext containerElementType() { return super.containerElement( - this, executableContext.getTypeContext(), ConstraintLocation.forReturnValue( executableContext.getExecutable() ) + this, executableContext.getTypeContext(), ConstraintLocation.forReturnValue( executableContext.getCallable() ) ); } @@ -89,7 +85,7 @@ public ContainerElementConstraintMappingContext containerElementType(int index, return super.containerElement( this, executableContext.getTypeContext(), - ConstraintLocation.forReturnValue( executableContext.getExecutable() ), + ConstraintLocation.forReturnValue( executableContext.getCallable() ), index, nestedIndexes ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java index 63275fc6aa..7bc3b920ac 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java @@ -12,7 +12,7 @@ import java.lang.annotation.ElementType; import java.lang.invoke.MethodHandles; import java.lang.reflect.Constructor; -import java.lang.reflect.Member; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; @@ -33,6 +33,12 @@ import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedType; +import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.properties.Constrainable; +import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; +import org.hibernate.validator.internal.properties.javabean.JavaBeanField; +import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ReflectionHelper; @@ -64,7 +70,7 @@ public final class TypeConstraintMappingContextImpl extends ConstraintMapping private final Set executableContexts = newHashSet(); private final Set propertyContexts = newHashSet(); - private final Set configuredMembers = newHashSet(); + private final Set configuredMembers = newHashSet(); private List> defaultGroupSequence; private Class> defaultGroupSequenceProviderClass; @@ -116,7 +122,7 @@ public PropertyConstraintMappingContext property(String property, ElementType el Contracts.assertNotNull( elementType, "The element type must not be null." ); Contracts.assertNotEmpty( property, MESSAGES.propertyNameMustNotBeEmpty() ); - Member member = getMember( + Property member = getProperty( beanClass, property, elementType ); @@ -148,15 +154,17 @@ public MethodConstraintMappingContext method(String name, Class... parameterT throw LOG.getBeanDoesNotContainMethodException( beanClass, name, parameterTypes ); } - if ( configuredMembers.contains( method ) ) { - throw LOG.getMethodHasAlreadyBeConfiguredViaProgrammaticApiException( + Callable callable = JavaBeanExecutable.of( method ); + + if ( configuredMembers.contains( callable ) ) { + throw LOG.getMethodHasAlreadyBeenConfiguredViaProgrammaticApiException( beanClass, ExecutableHelper.getExecutableAsString( name, parameterTypes ) ); } - MethodConstraintMappingContextImpl context = new MethodConstraintMappingContextImpl( this, method ); - configuredMembers.add( method ); + MethodConstraintMappingContextImpl context = new MethodConstraintMappingContextImpl( this, callable ); + configuredMembers.add( callable ); executableContexts.add( context ); return context; @@ -173,7 +181,9 @@ public ConstructorConstraintMappingContext constructor(Class... parameterType ); } - if ( configuredMembers.contains( constructor ) ) { + Callable callable = JavaBeanExecutable.of( constructor ); + + if ( configuredMembers.contains( callable ) ) { throw LOG.getConstructorHasAlreadyBeConfiguredViaProgrammaticApiException( beanClass, ExecutableHelper.getExecutableAsString( beanClass.getSimpleName(), parameterTypes ) @@ -182,9 +192,9 @@ public ConstructorConstraintMappingContext constructor(Class... parameterType ConstructorConstraintMappingContextImpl context = new ConstructorConstraintMappingContextImpl( this, - constructor + callable ); - configuredMembers.add( constructor ); + configuredMembers.add( callable ); executableContexts.add( context ); return context; @@ -246,15 +256,15 @@ protected ConstraintType getConstraintType() { } /** - * Returns the member with the given name and type. + * Returns the property with the given name and type. * - * @param clazz The class from which to retrieve the member. Cannot be {@code null}. + * @param clazz The class from which to retrieve the property. Cannot be {@code null}. * @param property The property name without "is", "get" or "has". Cannot be {@code null} or empty. * @param elementType The element type. Either {@code ElementType.FIELD} or {@code ElementType METHOD}. * - * @return the member which matching the name and type or {@code null} if no such member exists. + * @return the property which matches the name and type or {@code null} if no such property exists. */ - private Member getMember(Class clazz, String property, ElementType elementType) { + private Property getProperty(Class clazz, String property, ElementType elementType) { Contracts.assertNotNull( clazz, MESSAGES.classCannotBeNull() ); if ( property == null || property.length() == 0 ) { @@ -265,20 +275,21 @@ private Member getMember(Class clazz, String property, ElementType elementTyp throw LOG.getElementTypeHasToBeFieldOrMethodException(); } - Member member = null; if ( ElementType.FIELD.equals( elementType ) ) { - member = run( GetDeclaredField.action( clazz, property ) ); + Field field = run( GetDeclaredField.action( clazz, property ) ); + return field == null ? null : new JavaBeanField( field ); } else { + Method method = null; String methodName = property.substring( 0, 1 ).toUpperCase( Locale.ROOT ) + property.substring( 1 ); for ( String prefix : ReflectionHelper.PROPERTY_ACCESSOR_PREFIXES ) { - member = run( GetMethod.action( clazz, prefix + methodName ) ); - if ( member != null ) { + method = run( GetMethod.action( clazz, prefix + methodName ) ); + if ( method != null ) { break; } } + return method == null ? null : new JavaBeanGetter( method ); } - return member; } /** diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ConstraintViolationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ConstraintViolationImpl.java index eecdd5fbbd..59e3ee04c9 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ConstraintViolationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ConstraintViolationImpl.java @@ -39,7 +39,6 @@ public class ConstraintViolationImpl implements HibernateConstraintViolation< private final Map messageParameters; private final Map expressionVariables; private final Class rootBeanClass; - private final ElementType elementType; private final Object[] executableParameters; private final Object executableReturnValue; private final Object dynamicPayload; @@ -161,7 +160,6 @@ private ConstraintViolationImpl(String messageTemplate, this.leafBeanInstance = leafBeanInstance; this.constraintDescriptor = constraintDescriptor; this.rootBeanClass = rootBeanClass; - this.elementType = elementType; this.executableParameters = executableParameters; this.executableReturnValue = executableReturnValue; this.dynamicPayload = dynamicPayload; @@ -296,10 +294,6 @@ public boolean equals(Object o) { if ( constraintDescriptor != null ? !constraintDescriptor.equals( that.constraintDescriptor ) : that.constraintDescriptor != null ) { return false; } - if ( elementType != null ? !elementType.equals( that.elementType ) : that.elementType != null ) { - return false; - } - return true; } @@ -331,7 +325,6 @@ private int createHashCode() { result = 31 * result + System.identityHashCode( value ); result = 31 * result + ( constraintDescriptor != null ? constraintDescriptor.hashCode() : 0 ); result = 31 * result + ( messageTemplate != null ? messageTemplate.hashCode() : 0 ); - result = 31 * result + ( elementType != null ? elementType.hashCode() : 0 ); return result; } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java index 1a2a1d8a1f..04e37dfecb 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java @@ -23,8 +23,7 @@ import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.metadata.location.FieldConstraintLocation; -import org.hibernate.validator.internal.metadata.location.GetterConstraintLocation; +import org.hibernate.validator.internal.metadata.location.PropertyConstraintLocation; import org.hibernate.validator.internal.metadata.location.TypeArgumentConstraintLocation; /** @@ -72,11 +71,8 @@ private String getPropertyName(ConstraintLocation location) { location = ( (TypeArgumentConstraintLocation) location ).getOuterDelegate(); } - if ( location instanceof FieldConstraintLocation ) { - return ( (FieldConstraintLocation) location ).getPropertyName(); - } - else if ( location instanceof GetterConstraintLocation ) { - return ( (GetterConstraintLocation) location ).getPropertyName(); + if ( location instanceof PropertyConstraintLocation ) { + return ( (PropertyConstraintLocation) location ).getPropertyName(); } return null; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java index dedbfd2128..3dfe4cbf63 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java @@ -12,8 +12,6 @@ import java.lang.annotation.ElementType; import java.lang.invoke.MethodHandles; import java.lang.reflect.Executable; -import java.lang.reflect.Member; -import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; @@ -48,6 +46,7 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; import org.hibernate.validator.internal.metadata.raw.ConstrainedType; +import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; @@ -735,11 +734,11 @@ public BuilderDelegate( case CONSTRUCTOR: case METHOD: ConstrainedExecutable constrainedExecutable = (ConstrainedExecutable) constrainedElement; - Member member = constrainedExecutable.getExecutable(); + Callable callable = constrainedExecutable.getCallable(); // HV-890 Not adding meta-data for private super-type methods to the method meta-data of this bean; // It is not needed and it may conflict with sub-type methods of the same signature - if ( !Modifier.isPrivate( member.getModifiers() ) || beanClass == member.getDeclaringClass() ) { + if ( !callable.isPrivate() || beanClass == callable.getDeclaringClass() ) { methodBuilder = new ExecutableMetaData.Builder( beanClass, constrainedExecutable, diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java index 46d1aa7050..d8c2df456c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java @@ -10,9 +10,6 @@ import static org.hibernate.validator.internal.util.CollectionHelper.newHashMap; import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; -import java.lang.reflect.Constructor; -import java.lang.reflect.Executable; -import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.Arrays; import java.util.Collections; @@ -33,10 +30,10 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; +import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; -import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.stereotypes.Immutable; @@ -260,7 +257,7 @@ public static class Builder extends MetaDataBuilder { */ private final ConstrainedElement.ConstrainedElementKind kind; private final Set constrainedExecutables = newHashSet(); - private Executable executable; + private Callable callable; private final boolean isGetterMethod; private final Set> crossParameterConstraints = newHashSet(); private final Set rules; @@ -293,7 +290,7 @@ public Builder( this.executableHelper = executableHelper; this.parameterNameProvider = parameterNameProvider; this.kind = constrainedExecutable.getKind(); - this.executable = constrainedExecutable.getExecutable(); + this.callable = constrainedExecutable.getCallable(); this.rules = methodValidationConfiguration.getConfiguredRuleSet(); this.isGetterMethod = constrainedExecutable.isGetterMethod(); @@ -306,27 +303,27 @@ public boolean accepts(ConstrainedElement constrainedElement) { return false; } - Executable candidate = ( (ConstrainedExecutable) constrainedElement ).getExecutable(); + Callable candidate = ( (ConstrainedExecutable) constrainedElement ).getCallable(); //are the locations equal (created by different builders) or //does one of the executables override the other one? - return isResolvedToSameMethodInHierarchy( executable, candidate ); + return isResolvedToSameMethodInHierarchy( callable, candidate ); } - private boolean isResolvedToSameMethodInHierarchy(Executable first, Executable other) { - if ( first instanceof Constructor || other instanceof Constructor ) { + private boolean isResolvedToSameMethodInHierarchy(Callable first, Callable other) { + if ( first.isConstructor() || other.isConstructor() ) { return first.equals( other ); } - return executableHelper.isResolvedToSameMethodInHierarchy( getBeanClass(), (Method) first, (Method) other ); + return first.isResolvedToSameMethodInHierarchy( executableHelper, getBeanClass(), other ); } - private boolean overrides(Executable first, Executable other) { - if ( first instanceof Constructor || other instanceof Constructor ) { + private boolean overrides(Callable first, Callable other) { + if ( first.isConstructor() || other.isConstructor() ) { return false; } - return executableHelper.overrides( (Method) first, (Method) other ); + return executableHelper.overrides( first, other ); } @Override @@ -334,7 +331,7 @@ public final void add(ConstrainedElement constrainedElement) { super.add( constrainedElement ); ConstrainedExecutable constrainedExecutable = (ConstrainedExecutable) constrainedElement; - signatures.add( ExecutableHelper.getSignature( constrainedExecutable.getExecutable() ) ); + signatures.add( constrainedExecutable.getCallable().getSignature() ); constrainedExecutables.add( constrainedExecutable ); isConstrained = isConstrained || constrainedExecutable.isConstrained(); @@ -350,11 +347,11 @@ public final void add(ConstrainedElement constrainedElement) { // keep the "lowest" executable in hierarchy to make sure any type parameters declared on super-types (and // used in overridden methods) are resolved for the specific sub-type we are interested in - if ( executable != null && overrides( - constrainedExecutable.getExecutable(), - executable + if ( callable != null && overrides( + constrainedExecutable.getCallable(), + callable ) ) { - executable = constrainedExecutable.getExecutable(); + callable = constrainedExecutable.getCallable(); } } @@ -365,7 +362,7 @@ public final void add(ConstrainedElement constrainedElement) { * @param executable The executable to merge. */ private void addToExecutablesByDeclaringType(ConstrainedExecutable executable) { - Class beanClass = executable.getExecutable().getDeclaringClass(); + Class beanClass = executable.getCallable().getDeclaringClass(); ConstrainedExecutable mergedExecutable = executablesByDeclaringType.get( beanClass ); if ( mergedExecutable != null ) { @@ -383,17 +380,17 @@ public ExecutableMetaData build() { assertCorrectnessOfConfiguration(); return new ExecutableMetaData( - kind == ConstrainedElement.ConstrainedElementKind.CONSTRUCTOR ? executable.getDeclaringClass().getSimpleName() : executable.getName(), - ReflectionHelper.typeOf( executable ), - executable.getParameterTypes(), + kind == ConstrainedElement.ConstrainedElementKind.CONSTRUCTOR ? callable.getDeclaringClass().getSimpleName() : callable.getName(), + callable.getType(), + callable.getParameterTypes(), kind == ConstrainedElement.ConstrainedElementKind.CONSTRUCTOR ? ElementKind.CONSTRUCTOR : ElementKind.METHOD, - kind == ConstrainedElement.ConstrainedElementKind.CONSTRUCTOR ? Collections.singleton( ExecutableHelper.getSignature( executable ) ) : + kind == ConstrainedElement.ConstrainedElementKind.CONSTRUCTOR ? Collections.singleton( callable.getSignature() ) : CollectionHelper.toImmutableSet( signatures ), adaptOriginsAndImplicitGroups( getDirectConstraints() ), adaptOriginsAndImplicitGroups( getContainerElementConstraints() ), findParameterMetaData(), adaptOriginsAndImplicitGroups( crossParameterConstraints ), - cascadingMetaDataBuilder.build( valueExtractorManager, executable ), + cascadingMetaDataBuilder.build( valueExtractorManager, callable ), isConstrained, isGetterMethod ); @@ -416,7 +413,7 @@ private List findParameterMetaData() { for ( ConstrainedParameter oneParameter : oneExecutable.getAllParameterMetaData() ) { parameterBuilders.add( new ParameterMetaData.Builder( - executable.getDeclaringClass(), + callable.getDeclaringClass(), oneParameter, constraintHelper, typeResolutionHelper, diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java deleted file mode 100644 index 6ca82faea5..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.metadata.aggregated; - -import java.lang.annotation.ElementType; -import java.lang.reflect.Field; -import java.lang.reflect.Type; -import java.security.AccessController; -import java.security.PrivilegedAction; - -import org.hibernate.validator.HibernateValidatorPermission; -import org.hibernate.validator.internal.engine.path.PathImpl; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.facets.Cascadable; -import org.hibernate.validator.internal.util.ReflectionHelper; -import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredField; - -/** - * A {@link Cascadable} backed by a field of a Java bean. - * - * @author Gunnar Morling - */ -public class FieldCascadable implements Cascadable { - - private final Field field; - private final Type cascadableType; - private final CascadingMetaData cascadingMetaData; - - FieldCascadable(Field field, CascadingMetaData cascadingMetaData) { - this.field = field; - this.cascadableType = ReflectionHelper.typeOf( field ); - this.cascadingMetaData = cascadingMetaData; - } - - @Override - public ElementType getElementType() { - return ElementType.FIELD; - } - - @Override - public Type getCascadableType() { - return cascadableType; - } - - @Override - public Object getValue(Object parent) { - return ReflectionHelper.getValue( field, parent ); - } - - @Override - public void appendTo(PathImpl path) { - path.addPropertyNode( field.getName() ); - } - - @Override - public CascadingMetaData getCascadingMetaData() { - return cascadingMetaData; - } - - public static class Builder implements Cascadable.Builder { - - private final ValueExtractorManager valueExtractorManager; - private final Field field; - private CascadingMetaDataBuilder cascadingMetaDataBuilder; - - public Builder(ValueExtractorManager valueExtractorManager, Field field, CascadingMetaDataBuilder cascadingMetaDataBuilder) { - this.valueExtractorManager = valueExtractorManager; - this.field = field; - this.cascadingMetaDataBuilder = cascadingMetaDataBuilder; - } - - @Override - public void mergeCascadingMetaData(CascadingMetaDataBuilder cascadingMetaData) { - this.cascadingMetaDataBuilder = this.cascadingMetaDataBuilder.merge( cascadingMetaData ); - } - - @Override - public FieldCascadable build() { - return new FieldCascadable( getAccessible( field ), cascadingMetaDataBuilder.build( valueExtractorManager, field ) ); - } - - /** - * Returns an accessible copy of the given member. - */ - private Field getAccessible(Field original) { - SecurityManager sm = System.getSecurityManager(); - if ( sm != null ) { - sm.checkPermission( HibernateValidatorPermission.ACCESS_PRIVATE_MEMBERS ); - } - - Class clazz = original.getDeclaringClass(); - - return run( GetDeclaredField.andMakeAccessible( clazz, original.getName() ) ); - } - - /** - * Runs the given privileged action, using a privileged block if required. - *

- * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary - * privileged actions within HV's protection domain. - */ - private T run(PrivilegedAction action) { - return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); - } - } -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/MetaDataBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/MetaDataBuilder.java index 92e7c077be..66e756da06 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/MetaDataBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/MetaDataBuilder.java @@ -129,7 +129,7 @@ private MetaConstraint adaptOriginAndImplicitGroup(Met ConstraintDescriptorImpl descriptor = new ConstraintDescriptorImpl<>( constraintHelper, - constraint.getLocation().getMember(), + constraint.getLocation().getConstrainable(), constraint.getDescriptor().getAnnotationDescriptor(), constraint.getElementType(), constraintClass.isInterface() ? constraintClass : null, diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ParameterMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ParameterMetaData.java index d175c6e548..c40e659fb1 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ParameterMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ParameterMetaData.java @@ -7,7 +7,6 @@ package org.hibernate.validator.internal.metadata.aggregated; import java.lang.annotation.ElementType; -import java.lang.reflect.Executable; import java.lang.reflect.Type; import java.util.List; import java.util.Set; @@ -24,6 +23,7 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; +import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.TypeResolutionHelper; @@ -112,7 +112,7 @@ public static class Builder extends MetaDataBuilder { private final ExecutableParameterNameProvider parameterNameProvider; private final Type parameterType; private final int parameterIndex; - private Executable executableForNameRetrieval; + private Callable callableForNameRetrieval; private CascadingMetaDataBuilder cascadingMetaDataBuilder; public Builder(Class beanClass, @@ -156,9 +156,9 @@ public void add(ConstrainedElement constrainedElement) { // use this parent class parameter name instead of the more specific one. // Worse case, we are consistent, best case parameters from parents are more meaningful. // See HV-887 and the associated unit test - if ( executableForNameRetrieval == null || - newConstrainedParameter.getExecutable().getDeclaringClass().isAssignableFrom( executableForNameRetrieval.getDeclaringClass() ) ) { - executableForNameRetrieval = newConstrainedParameter.getExecutable(); + if ( callableForNameRetrieval == null || + newConstrainedParameter.getCallable().getDeclaringClass().isAssignableFrom( callableForNameRetrieval.getDeclaringClass() ) ) { + callableForNameRetrieval = newConstrainedParameter.getCallable(); } } @@ -166,11 +166,11 @@ public void add(ConstrainedElement constrainedElement) { public ParameterMetaData build() { return new ParameterMetaData( parameterIndex, - parameterNameProvider.getParameterNames( executableForNameRetrieval ).get( parameterIndex ), + callableForNameRetrieval.getParameterName( parameterNameProvider, parameterIndex ), parameterType, adaptOriginsAndImplicitGroups( getDirectConstraints() ), adaptOriginsAndImplicitGroups( getContainerElementConstraints() ), - cascadingMetaDataBuilder.build( valueExtractorManager, executableForNameRetrieval ) + cascadingMetaDataBuilder.build( valueExtractorManager, callableForNameRetrieval ) ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyCascadable.java similarity index 60% rename from engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java rename to engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyCascadable.java index 72854cfa39..7afa0fd018 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyCascadable.java @@ -7,36 +7,37 @@ package org.hibernate.validator.internal.metadata.aggregated; import java.lang.annotation.ElementType; -import java.lang.reflect.Method; import java.lang.reflect.Type; import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.facets.Cascadable; -import org.hibernate.validator.internal.util.ReflectionHelper; +import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.javabean.JavaBeanField; /** - * A {@link Cascadable} backed by a property getter of a Java bean. + * A {@link Cascadable} backed by a field of a Java bean. * * @author Gunnar Morling + * @author Marko Bekhta */ -public class GetterCascadable implements Cascadable { +public class PropertyCascadable implements Cascadable { - private final Method method; - private final String propertyName; + private final Property property; private final Type cascadableType; private final CascadingMetaData cascadingMetaData; + private final ElementType elementType; - GetterCascadable(Method method, CascadingMetaData cascadingMetaData) { - this.method = method; - this.propertyName = ReflectionHelper.getPropertyName( method ); - this.cascadableType = ReflectionHelper.typeOf( method ); + PropertyCascadable(Property property, CascadingMetaData cascadingMetaData) { + this.property = property; + this.cascadableType = property.getType(); this.cascadingMetaData = cascadingMetaData; + this.elementType = property instanceof JavaBeanField ? ElementType.FIELD : ElementType.METHOD; } @Override public ElementType getElementType() { - return ElementType.METHOD; + return elementType; } @Override @@ -46,12 +47,12 @@ public Type getCascadableType() { @Override public Object getValue(Object parent) { - return ReflectionHelper.getValue( method, parent ); + return property.getValueFrom( parent ); } @Override public void appendTo(PathImpl path) { - path.addPropertyNode( propertyName ); + path.addPropertyNode( property.getPropertyName() ); } @Override @@ -62,13 +63,12 @@ public CascadingMetaData getCascadingMetaData() { public static class Builder implements Cascadable.Builder { private final ValueExtractorManager valueExtractorManager; - private final Method method; + private final Property property; private CascadingMetaDataBuilder cascadingMetaDataBuilder; - // Note: the method passed here has to be accessible: the caller is responsible for that - public Builder(ValueExtractorManager valueExtractorManager, Method method, CascadingMetaDataBuilder cascadingMetaDataBuilder) { + public Builder(ValueExtractorManager valueExtractorManager, Property property, CascadingMetaDataBuilder cascadingMetaDataBuilder) { this.valueExtractorManager = valueExtractorManager; - this.method = method; + this.property = property; this.cascadingMetaDataBuilder = cascadingMetaDataBuilder; } @@ -78,8 +78,8 @@ public void mergeCascadingMetaData(CascadingMetaDataBuilder cascadingMetaData) { } @Override - public GetterCascadable build() { - return new GetterCascadable( method, cascadingMetaDataBuilder.build( valueExtractorManager, method ) ); + public PropertyCascadable build() { + return new PropertyCascadable( property, cascadingMetaDataBuilder.build( valueExtractorManager, property ) ); } } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java index f616e8e923..7282c947f7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java @@ -6,8 +6,6 @@ */ package org.hibernate.validator.internal.metadata.aggregated; -import java.lang.reflect.Field; -import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.security.AccessController; @@ -33,15 +31,17 @@ import org.hibernate.validator.internal.metadata.descriptor.PropertyDescriptorImpl; import org.hibernate.validator.internal.metadata.facets.Cascadable; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.metadata.location.GetterConstraintLocation; +import org.hibernate.validator.internal.metadata.location.PropertyConstraintLocation; import org.hibernate.validator.internal.metadata.location.TypeArgumentConstraintLocation; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; import org.hibernate.validator.internal.metadata.raw.ConstrainedType; +import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.properties.Constrainable; +import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.util.CollectionHelper; -import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethod; import org.hibernate.validator.internal.util.stereotypes.Immutable; @@ -157,18 +157,17 @@ public static class Builder extends MetaDataBuilder { ); private final String propertyName; - private final Map cascadableBuilders = new HashMap<>(); + private final Map cascadableBuilders = new HashMap<>(); private final Type propertyType; private boolean cascadingProperty = false; - private Method getterAccessibleMethod; - public Builder(Class beanClass, ConstrainedField constrainedField, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, + public Builder(Class beanClass, ConstrainedField constrainedProperty, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { super( beanClass, constraintHelper, typeResolutionHelper, valueExtractorManager ); - this.propertyName = constrainedField.getField().getName(); - this.propertyType = ReflectionHelper.typeOf( constrainedField.getField() ); - add( constrainedField ); + this.propertyName = constrainedProperty.getProperty().getName(); + this.propertyType = constrainedProperty.getProperty().getType(); + add( constrainedProperty ); } public Builder(Class beanClass, ConstrainedType constrainedType, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, @@ -184,8 +183,8 @@ public Builder(Class beanClass, ConstrainedExecutable constrainedMethod, Cons ValueExtractorManager valueExtractorManager) { super( beanClass, constraintHelper, typeResolutionHelper, valueExtractorManager ); - this.propertyName = ReflectionHelper.getPropertyName( constrainedMethod.getExecutable() ); - this.propertyType = ReflectionHelper.typeOf( constrainedMethod.getExecutable() ); + this.propertyName = constrainedMethod.getCallable().as( Property.class ).getPropertyName(); + this.propertyType = constrainedMethod.getCallable().getType(); add( constrainedMethod ); } @@ -205,12 +204,6 @@ public boolean accepts(ConstrainedElement constrainedElement) { @Override public final void add(ConstrainedElement constrainedElement) { - // if we are in the case of a getter and if we have constraints (either on the annotated object itself or on - // a container element) or cascaded validation, we want to create an accessible version of the getter only once. - if ( constrainedElement.getKind() == ConstrainedElementKind.METHOD && constrainedElement.isConstrained() ) { - getterAccessibleMethod = getAccessible( (Method) ( (ConstrainedExecutable) constrainedElement ).getExecutable() ); - } - super.add( constrainedElement ); cascadingProperty = cascadingProperty || constrainedElement.getCascadingMetaDataBuilder().isCascading(); @@ -218,23 +211,23 @@ public final void add(ConstrainedElement constrainedElement) { if ( constrainedElement.getCascadingMetaDataBuilder().isMarkedForCascadingOnAnnotatedObjectOrContainerElements() || constrainedElement.getCascadingMetaDataBuilder().hasGroupConversionsOnAnnotatedObjectOrContainerElements() ) { if ( constrainedElement.getKind() == ConstrainedElementKind.FIELD ) { - Field field = ( (ConstrainedField) constrainedElement ).getField(); - Cascadable.Builder builder = cascadableBuilders.get( field ); + Property property = ( (ConstrainedField) constrainedElement ).getProperty(); + Cascadable.Builder builder = cascadableBuilders.get( property ); if ( builder == null ) { - builder = new FieldCascadable.Builder( valueExtractorManager, field, constrainedElement.getCascadingMetaDataBuilder() ); - cascadableBuilders.put( field, builder ); + builder = new PropertyCascadable.Builder( valueExtractorManager, property, constrainedElement.getCascadingMetaDataBuilder() ); + cascadableBuilders.put( property, builder ); } else { builder.mergeCascadingMetaData( constrainedElement.getCascadingMetaDataBuilder() ); } } else if ( constrainedElement.getKind() == ConstrainedElementKind.METHOD ) { - Method method = (Method) ( (ConstrainedExecutable) constrainedElement ).getExecutable(); + Callable method = ( (ConstrainedExecutable) constrainedElement ).getCallable(); Cascadable.Builder builder = cascadableBuilders.get( method ); if ( builder == null ) { - builder = new GetterCascadable.Builder( valueExtractorManager, getterAccessibleMethod, constrainedElement.getCascadingMetaDataBuilder() ); + builder = new PropertyCascadable.Builder( valueExtractorManager, method.as( Property.class ), constrainedElement.getCascadingMetaDataBuilder() ); cascadableBuilders.put( method, builder ); } else { @@ -250,7 +243,7 @@ protected Set> adaptConstraints(ConstrainedElement constrained return constraints; } - ConstraintLocation getterConstraintLocation = ConstraintLocation.forGetter( getterAccessibleMethod ); + ConstraintLocation getterConstraintLocation = ConstraintLocation.forProperty( ( (ConstrainedExecutable) constrainedElement ).getCallable().as( Property.class ) ); // convert return value locations into getter locations for usage within this meta-data return constraints.stream() @@ -264,7 +257,7 @@ private MetaConstraint withGetterLocation(ConstraintLocation getterConstraint // fast track if it's a regular constraint if ( !(constraint.getLocation() instanceof TypeArgumentConstraintLocation) ) { // Change the constraint location to a GetterConstraintLocation if it is not already one - if ( constraint.getLocation() instanceof GetterConstraintLocation ) { + if ( constraint.getLocation() instanceof PropertyConstraintLocation ) { converted = constraint.getLocation(); } else { @@ -291,7 +284,7 @@ private MetaConstraint withGetterLocation(ConstraintLocation getterConstraint for ( ConstraintLocation location : locationStack ) { if ( !(location instanceof TypeArgumentConstraintLocation) ) { // Change the constraint location to a GetterConstraintLocation if it is not already one - if ( location instanceof GetterConstraintLocation ) { + if ( location instanceof PropertyConstraintLocation ) { converted = location; } else { @@ -313,10 +306,10 @@ private MetaConstraint withGetterLocation(ConstraintLocation getterConstraint private String getPropertyName(ConstrainedElement constrainedElement) { if ( constrainedElement.getKind() == ConstrainedElementKind.FIELD ) { - return ReflectionHelper.getPropertyName( ( (ConstrainedField) constrainedElement ).getField() ); + return ( (ConstrainedField) constrainedElement ).getProperty().getPropertyName(); } else if ( constrainedElement.getKind() == ConstrainedElementKind.METHOD ) { - return ReflectionHelper.getPropertyName( ( (ConstrainedExecutable) constrainedElement ).getExecutable() ); + return ( (ConstrainedExecutable) constrainedElement ).getCallable().as( Property.class ).getPropertyName(); } return null; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/MethodConfigurationRule.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/MethodConfigurationRule.java index c7d1831283..7b4eeffd7e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/MethodConfigurationRule.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/MethodConfigurationRule.java @@ -54,8 +54,8 @@ protected boolean isStrictSubType(Class clazz, Class otherClazz) { * {@code otherExecutable}, {@code false} otherwise */ protected boolean isDefinedOnSubType(ConstrainedExecutable executable, ConstrainedExecutable otherExecutable) { - Class clazz = executable.getExecutable().getDeclaringClass(); - Class otherClazz = otherExecutable.getExecutable().getDeclaringClass(); + Class clazz = executable.getCallable().getDeclaringClass(); + Class otherClazz = otherExecutable.getCallable().getDeclaringClass(); return isStrictSubType( clazz, otherClazz ); } @@ -71,8 +71,8 @@ protected boolean isDefinedOnSubType(ConstrainedExecutable executable, Constrain * {@code otherExecutable}, {@code false} otherwise */ protected boolean isDefinedOnParallelType(ConstrainedExecutable executable, ConstrainedExecutable otherExecutable) { - Class clazz = executable.getExecutable().getDeclaringClass(); - Class otherClazz = otherExecutable.getExecutable().getDeclaringClass(); + Class clazz = executable.getCallable().getDeclaringClass(); + Class otherClazz = otherExecutable.getCallable().getDeclaringClass(); return !( clazz.isAssignableFrom( otherClazz ) || otherClazz.isAssignableFrom( clazz ) ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/OverridingMethodMustNotAlterParameterConstraints.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/OverridingMethodMustNotAlterParameterConstraints.java index 2e402c25bb..2b88e5e953 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/OverridingMethodMustNotAlterParameterConstraints.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/OverridingMethodMustNotAlterParameterConstraints.java @@ -22,8 +22,8 @@ public void apply(ConstrainedExecutable method, ConstrainedExecutable otherMetho otherMethod.hasParameterConstraints() && !method.isEquallyParameterConstrained( otherMethod ) ) { throw LOG.getParameterConfigurationAlteredInSubTypeException( - method.getExecutable(), - otherMethod.getExecutable() + method.getCallable(), + otherMethod.getCallable() ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/ParallelMethodsMustNotDefineGroupConversionForCascadedReturnValue.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/ParallelMethodsMustNotDefineGroupConversionForCascadedReturnValue.java index 4546d1278e..69cc7debfb 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/ParallelMethodsMustNotDefineGroupConversionForCascadedReturnValue.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/ParallelMethodsMustNotDefineGroupConversionForCascadedReturnValue.java @@ -25,8 +25,8 @@ public void apply(ConstrainedExecutable method, ConstrainedExecutable otherMetho if ( isDefinedOnParallelType( method, otherMethod ) && isCascaded && hasGroupConversions ) { throw LOG.getMethodsFromParallelTypesMustNotDefineGroupConversionsForCascadedReturnValueException( - method.getExecutable(), - otherMethod.getExecutable() + method.getCallable(), + otherMethod.getCallable() ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/ParallelMethodsMustNotDefineParameterConstraints.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/ParallelMethodsMustNotDefineParameterConstraints.java index 2023e3ab2d..12abf849b4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/ParallelMethodsMustNotDefineParameterConstraints.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/ParallelMethodsMustNotDefineParameterConstraints.java @@ -21,8 +21,8 @@ public void apply(ConstrainedExecutable method, ConstrainedExecutable otherMetho if ( isDefinedOnParallelType( method, otherMethod ) && ( method.hasParameterConstraints() || otherMethod.hasParameterConstraints() ) ) { throw LOG.getParameterConstraintsDefinedInMethodsFromParallelTypesException( - method.getExecutable(), - otherMethod.getExecutable() + method.getCallable(), + otherMethod.getCallable() ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/ReturnValueMayOnlyBeMarkedOnceAsCascadedPerHierarchyLine.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/ReturnValueMayOnlyBeMarkedOnceAsCascadedPerHierarchyLine.java index 7bac3875e9..f29b70cc94 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/ReturnValueMayOnlyBeMarkedOnceAsCascadedPerHierarchyLine.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/ReturnValueMayOnlyBeMarkedOnceAsCascadedPerHierarchyLine.java @@ -22,8 +22,8 @@ public void apply(ConstrainedExecutable method, ConstrainedExecutable otherMetho otherMethod.getCascadingMetaDataBuilder().isMarkedForCascadingOnAnnotatedObjectOrContainerElements() && ( isDefinedOnSubType( method, otherMethod ) || isDefinedOnSubType( otherMethod, method ) ) ) { throw LOG.getMethodReturnValueMustNotBeMarkedMoreThanOnceForCascadedValidationException( - method.getExecutable(), - otherMethod.getExecutable() + method.getCallable(), + otherMethod.getCallable() ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/VoidMethodsMustNotBeReturnValueConstrained.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/VoidMethodsMustNotBeReturnValueConstrained.java index 3344bd0515..15600a1876 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/VoidMethodsMustNotBeReturnValueConstrained.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/rule/VoidMethodsMustNotBeReturnValueConstrained.java @@ -6,8 +6,6 @@ */ package org.hibernate.validator.internal.metadata.aggregated.rule; -import java.lang.reflect.Method; - import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; /** @@ -20,11 +18,10 @@ public class VoidMethodsMustNotBeReturnValueConstrained extends MethodConfigurat @Override public void apply(ConstrainedExecutable executable, ConstrainedExecutable otherExecutable) { - if ( ( executable.getExecutable() instanceof Method ) && - ( (Method) executable.getExecutable() ).getReturnType() == void.class && + if ( !executable.getCallable().hasReturnValue() && ( !executable.getConstraints().isEmpty() || executable.getCascadingMetaDataBuilder().isMarkedForCascadingOnAnnotatedObjectOrContainerElements() ) ) { - throw LOG.getVoidMethodsMustNotBeConstrainedException( executable.getExecutable() ); + throw LOG.getVoidMethodsMustNotBeConstrainedException( executable.getCallable() ); } } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/AnnotationProcessingOptions.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/AnnotationProcessingOptions.java index 5e80ed6b4b..dfbc674ff8 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/AnnotationProcessingOptions.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/AnnotationProcessingOptions.java @@ -6,7 +6,7 @@ */ package org.hibernate.validator.internal.metadata.core; -import java.lang.reflect.Member; +import org.hibernate.validator.internal.properties.Constrainable; /** * An {@code AnnotationProcessingOptions} instance keeps track of annotations which should be ignored as configuration source. @@ -18,13 +18,13 @@ public interface AnnotationProcessingOptions { boolean areClassLevelConstraintsIgnoredFor(Class clazz); - boolean areMemberConstraintsIgnoredFor(Member member); + boolean areMemberConstraintsIgnoredFor(Constrainable constrainable); - boolean areReturnValueConstraintsIgnoredFor(Member member); + boolean areReturnValueConstraintsIgnoredFor(Constrainable constrainable); - boolean areCrossParameterConstraintsIgnoredFor(Member member); + boolean areCrossParameterConstraintsIgnoredFor(Constrainable constrainable); - boolean areParameterConstraintsIgnoredFor(Member member, int index); + boolean areParameterConstraintsIgnoredFor(Constrainable constrainable, int index); void merge(AnnotationProcessingOptions annotationProcessingOptions); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/AnnotationProcessingOptionsImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/AnnotationProcessingOptionsImpl.java index 11bc7d6ccf..b0746a0bdd 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/AnnotationProcessingOptionsImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/AnnotationProcessingOptionsImpl.java @@ -6,15 +6,15 @@ */ package org.hibernate.validator.internal.metadata.core; +import static org.hibernate.validator.internal.util.CollectionHelper.newHashMap; + import java.lang.invoke.MethodHandles; -import java.lang.reflect.Member; import java.util.Map; +import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; -import static org.hibernate.validator.internal.util.CollectionHelper.newHashMap; - /** * An {@code AnnotationProcessingOptions} instance keeps track of annotations which should be ignored as configuration source. * The main validation source for Bean Validation is annotation and alternate configuration sources use this class @@ -40,17 +40,17 @@ public class AnnotationProcessingOptionsImpl implements AnnotationProcessingOpti /** * Keeps track of explicitly excluded members (fields and properties). */ - private final Map annotationIgnoredForMembers = newHashMap(); + private final Map annotationIgnoredForMembers = newHashMap(); /** * Keeps track of explicitly excluded return value constraints for methods/constructors. */ - private final Map annotationIgnoresForReturnValues = newHashMap(); + private final Map annotationIgnoresForReturnValues = newHashMap(); /** * Keeps track of explicitly excluded cross parameter constraints for methods/constructors. */ - private final Map annotationIgnoresForCrossParameter = newHashMap(); + private final Map annotationIgnoresForCrossParameter = newHashMap(); /** * Keeps track whether the 'ignore-annotations' flag is set on a method/constructor parameter @@ -58,10 +58,10 @@ public class AnnotationProcessingOptionsImpl implements AnnotationProcessingOpti private final Map annotationIgnoresForMethodParameter = newHashMap(); @Override - public boolean areMemberConstraintsIgnoredFor(Member member) { - Class clazz = member.getDeclaringClass(); - if ( annotationIgnoredForMembers.containsKey( member ) ) { - return annotationIgnoredForMembers.get( member ); + public boolean areMemberConstraintsIgnoredFor(Constrainable constrainable) { + Class clazz = constrainable.getDeclaringClass(); + if ( annotationIgnoredForMembers.containsKey( constrainable ) ) { + return annotationIgnoredForMembers.get( constrainable ); } else { return areAllConstraintAnnotationsIgnoredFor( clazz ); @@ -69,33 +69,33 @@ public boolean areMemberConstraintsIgnoredFor(Member member) { } @Override - public boolean areReturnValueConstraintsIgnoredFor(Member member) { - if ( annotationIgnoresForReturnValues.containsKey( member ) ) { - return annotationIgnoresForReturnValues.get( member ); + public boolean areReturnValueConstraintsIgnoredFor(Constrainable constrainable) { + if ( annotationIgnoresForReturnValues.containsKey( constrainable ) ) { + return annotationIgnoresForReturnValues.get( constrainable ); } else { - return areMemberConstraintsIgnoredFor( member ); + return areMemberConstraintsIgnoredFor( constrainable ); } } @Override - public boolean areCrossParameterConstraintsIgnoredFor(Member member) { - if ( annotationIgnoresForCrossParameter.containsKey( member ) ) { - return annotationIgnoresForCrossParameter.get( member ); + public boolean areCrossParameterConstraintsIgnoredFor(Constrainable constrainable) { + if ( annotationIgnoresForCrossParameter.containsKey( constrainable ) ) { + return annotationIgnoresForCrossParameter.get( constrainable ); } else { - return areMemberConstraintsIgnoredFor( member ); + return areMemberConstraintsIgnoredFor( constrainable ); } } @Override - public boolean areParameterConstraintsIgnoredFor(Member member, int index) { - ExecutableParameterKey key = new ExecutableParameterKey( member, index ); + public boolean areParameterConstraintsIgnoredFor(Constrainable constrainable, int index) { + ExecutableParameterKey key = new ExecutableParameterKey( constrainable, index ); if ( annotationIgnoresForMethodParameter.containsKey( key ) ) { return annotationIgnoresForMethodParameter.get( key ); } else { - return areMemberConstraintsIgnoredFor( member ); + return areMemberConstraintsIgnoredFor( constrainable ); } } @@ -138,19 +138,19 @@ public void ignoreAnnotationConstraintForClass(Class clazz, Boolean b) { } } - public void ignoreConstraintAnnotationsOnMember(Member member, Boolean b) { + public void ignoreConstraintAnnotationsOnMember(Constrainable member, Boolean b) { annotationIgnoredForMembers.put( member, b ); } - public void ignoreConstraintAnnotationsForReturnValue(Member member, Boolean b) { + public void ignoreConstraintAnnotationsForReturnValue(Constrainable member, Boolean b) { annotationIgnoresForReturnValues.put( member, b ); } - public void ignoreConstraintAnnotationsForCrossParameterConstraint(Member member, Boolean b) { + public void ignoreConstraintAnnotationsForCrossParameterConstraint(Constrainable member, Boolean b) { annotationIgnoresForCrossParameter.put( member, b ); } - public void ignoreConstraintAnnotationsOnParameter(Member member, int index, Boolean b) { + public void ignoreConstraintAnnotationsOnParameter(Constrainable member, int index, Boolean b) { ExecutableParameterKey key = new ExecutableParameterKey( member, index ); annotationIgnoresForMethodParameter.put( key, b ); } @@ -164,11 +164,11 @@ private boolean areAllConstraintAnnotationsIgnoredFor(Class clazz) { } public class ExecutableParameterKey { - private final Member member; + private final Constrainable constrainable; private final int index; - public ExecutableParameterKey(Member member, int index) { - this.member = member; + public ExecutableParameterKey(Constrainable constrainable, int index) { + this.constrainable = constrainable; this.index = index; } @@ -186,7 +186,7 @@ public boolean equals(Object o) { if ( index != that.index ) { return false; } - if ( member != null ? !member.equals( that.member ) : that.member != null ) { + if ( constrainable != null ? !constrainable.equals( that.constrainable ) : that.constrainable != null ) { return false; } @@ -195,7 +195,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - int result = member != null ? member.hashCode() : 0; + int result = constrainable != null ? constrainable.hashCode() : 0; result = 31 * result + index; return result; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ConstraintDescriptorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ConstraintDescriptorImpl.java index 094c6e54b2..edecfb516c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ConstraintDescriptorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ConstraintDescriptorImpl.java @@ -17,10 +17,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.lang.invoke.MethodHandles; -import java.lang.reflect.Constructor; -import java.lang.reflect.Executable; -import java.lang.reflect.Field; -import java.lang.reflect.Member; import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; @@ -49,6 +45,9 @@ import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorDescriptor; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.ConstraintOrigin; +import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.properties.Constrainable; +import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.StringHelper; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; @@ -164,7 +163,7 @@ public class ConstraintDescriptorImpl implements Constrain private final int hashCode; public ConstraintDescriptorImpl(ConstraintHelper constraintHelper, - Member member, + Constrainable constrainable, ConstraintAnnotationDescriptor annotationDescriptor, ElementType type, Class implicitGroup, @@ -182,7 +181,7 @@ public ConstraintDescriptorImpl(ConstraintHelper constraintHelper, this.groups = buildGroupSet( annotationDescriptor, implicitGroup ); this.payloads = buildPayloadSet( annotationDescriptor ); - this.valueUnwrapping = determineValueUnwrapping( this.payloads, member, annotationDescriptor.getType() ); + this.valueUnwrapping = determineValueUnwrapping( this.payloads, constrainable, annotationDescriptor.getType() ); this.validationAppliesTo = determineValidationAppliesTo( annotationDescriptor ); @@ -206,13 +205,13 @@ public ConstraintDescriptorImpl(ConstraintHelper constraintHelper, this.constraintType = determineConstraintType( annotationDescriptor.getType(), - member, + constrainable, type, !genericValidatorDescriptors.isEmpty(), !crossParameterValidatorDescriptors.isEmpty(), externalConstraintType ); - this.composingConstraints = parseComposingConstraints( constraintHelper, member, constraintType ); + this.composingConstraints = parseComposingConstraints( constraintHelper, constrainable, constraintType ); this.compositionType = parseCompositionType( constraintHelper ); validateComposingConstraintTypes(); @@ -227,18 +226,18 @@ public ConstraintDescriptorImpl(ConstraintHelper constraintHelper, } public ConstraintDescriptorImpl(ConstraintHelper constraintHelper, - Member member, + Constrainable constrainable, ConstraintAnnotationDescriptor annotationDescriptor, ElementType type) { - this( constraintHelper, member, annotationDescriptor, type, null, ConstraintOrigin.DEFINED_LOCALLY, null ); + this( constraintHelper, constrainable, annotationDescriptor, type, null, ConstraintOrigin.DEFINED_LOCALLY, null ); } public ConstraintDescriptorImpl(ConstraintHelper constraintHelper, - Member member, + Constrainable constrainable, ConstraintAnnotationDescriptor annotationDescriptor, ElementType type, ConstraintType constraintType) { - this( constraintHelper, member, annotationDescriptor, type, null, ConstraintOrigin.DEFINED_LOCALLY, constraintType ); + this( constraintHelper, constrainable, annotationDescriptor, type, null, ConstraintOrigin.DEFINED_LOCALLY, constraintType ); } public ConstraintAnnotationDescriptor getAnnotationDescriptor() { @@ -389,7 +388,7 @@ public String toString() { * specify the target explicitly). * * - * @param member The annotated member + * @param constrainable The annotated member * @param elementType The type of the annotated element * @param hasGenericValidators Whether the constraint has at least one generic validator or * not @@ -400,7 +399,7 @@ public String toString() { * @return The type of this constraint */ private ConstraintType determineConstraintType(Class constraintAnnotationType, - Member member, + Constrainable constrainable, ElementType elementType, boolean hasGenericValidators, boolean hasCrossParameterValidator, @@ -453,9 +452,10 @@ else if ( constraintAnnotationType.isAnnotationPresent( SupportedValidationTarge } //try to derive from existence of parameters/return value - else { - boolean hasParameters = hasParameters( member ); - boolean hasReturnValue = hasReturnValue( member ); + //hence look only if it is a callable + else if ( constrainable instanceof Callable ) { + boolean hasParameters = constrainable.as( Callable.class ).hasParameters(); + boolean hasReturnValue = constrainable.as( Callable.class ).hasReturnValue(); if ( !hasParameters && hasReturnValue ) { constraintType = ConstraintType.GENERIC; @@ -472,16 +472,16 @@ else if ( hasParameters && !hasReturnValue ) { } if ( constraintType == ConstraintType.CROSS_PARAMETER ) { - validateCrossParameterConstraintType( member, hasCrossParameterValidator ); + validateCrossParameterConstraintType( constrainable, hasCrossParameterValidator ); } return constraintType; } - private static ValidateUnwrappedValue determineValueUnwrapping(Set> payloads, Member member, Class annotationType) { + private static ValidateUnwrappedValue determineValueUnwrapping(Set> payloads, Constrainable constrainable, Class annotationType) { if ( payloads.contains( Unwrapping.Unwrap.class ) ) { if ( payloads.contains( Unwrapping.Skip.class ) ) { - throw LOG.getInvalidUnwrappingConfigurationForConstraintException( member, annotationType ); + throw LOG.getInvalidUnwrappingConfigurationForConstraintException( constrainable, annotationType ); } return ValidateUnwrappedValue.UNWRAP; @@ -498,20 +498,20 @@ private static ConstraintTarget determineValidationAppliesTo(ConstraintAnnotatio return annotationDescriptor.getValidationAppliesTo(); } - private void validateCrossParameterConstraintType(Member member, boolean hasCrossParameterValidator) { + private void validateCrossParameterConstraintType(Constrainable constrainable, boolean hasCrossParameterValidator) { if ( !hasCrossParameterValidator ) { throw LOG.getCrossParameterConstraintHasNoValidatorException( annotationDescriptor.getType() ); } - else if ( member == null ) { + else if ( constrainable == null ) { throw LOG.getCrossParameterConstraintOnClassException( annotationDescriptor.getType() ); } - else if ( member instanceof Field ) { - throw LOG.getCrossParameterConstraintOnFieldException( annotationDescriptor.getType(), member ); + else if ( constrainable instanceof Property ) { + throw LOG.getCrossParameterConstraintOnFieldException( annotationDescriptor.getType(), constrainable ); } - else if ( !hasParameters( member ) ) { + else if ( !constrainable.as( Callable.class ).hasParameters() ) { throw LOG.getCrossParameterConstraintOnMethodWithoutParametersException( annotationDescriptor.getType(), - (Executable) member + constrainable ); } } @@ -533,35 +533,6 @@ private void validateComposingConstraintTypes() { } } - private boolean hasParameters(Member member) { - boolean hasParameters = false; - if ( member instanceof Constructor ) { - Constructor constructor = (Constructor) member; - hasParameters = constructor.getParameterTypes().length > 0; - } - else if ( member instanceof Method ) { - Method method = (Method) member; - hasParameters = method.getParameterTypes().length > 0; - } - return hasParameters; - } - - private boolean hasReturnValue(Member member) { - boolean hasReturnValue; - if ( member instanceof Constructor ) { - hasReturnValue = true; - } - else if ( member instanceof Method ) { - Method method = (Method) member; - hasReturnValue = method.getGenericReturnType() != void.class; - } - else { - // field or type - hasReturnValue = false; - } - return hasReturnValue; - } - private boolean isExecutable(ElementType elementType) { return elementType == ElementType.METHOD || elementType == ElementType.CONSTRUCTOR; } @@ -648,7 +619,7 @@ private void ensureAttributeIsOverridable(Method m, OverridesAttribute overrides } } - private Set> parseComposingConstraints(ConstraintHelper constraintHelper, Member member, + private Set> parseComposingConstraints(ConstraintHelper constraintHelper, Constrainable constrainable, ConstraintType constraintType) { Set> composingConstraintsSet = newHashSet(); Map> overrideParameters = parseOverrideParameters(); @@ -669,7 +640,7 @@ private Set> parseComposingConstraints(ConstraintHel ConstraintDescriptorImpl descriptor = createComposingConstraintDescriptor( constraintHelper, - member, + constrainable, overrideParameters, OVERRIDES_PARAMETER_DEFAULT_INDEX, declaredAnnotation, @@ -691,7 +662,7 @@ else if ( constraintHelper.isMultiValueConstraint( declaredAnnotationType ) ) { ConstraintDescriptorImpl descriptor = createComposingConstraintDescriptor( constraintHelper, - member, + constrainable, overrideParameters, index, constraintAnnotation, @@ -727,7 +698,7 @@ private CompositionType parseCompositionType(ConstraintHelper constraintHelper) private ConstraintDescriptorImpl createComposingConstraintDescriptor( ConstraintHelper constraintHelper, - Member member, + Constrainable constrainable, Map> overrideParameters, int index, U constraintAnnotation, @@ -773,7 +744,7 @@ annotationType, run( GetAnnotationAttributes.action( constraintAnnotation ) ) } return new ConstraintDescriptorImpl<>( - constraintHelper, member, annotationDescriptorBuilder.build(), elementType, null, definedOn, constraintType + constraintHelper, constrainable, annotationDescriptorBuilder.build(), elementType, null, definedOn, constraintType ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/BeanConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/BeanConstraintLocation.java index e8a573f27b..d6d8f3a0ab 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/BeanConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/BeanConstraintLocation.java @@ -6,10 +6,10 @@ */ package org.hibernate.validator.internal.metadata.location; -import java.lang.reflect.Member; import java.lang.reflect.Type; import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.TypeHelper; @@ -47,7 +47,7 @@ public Class getDeclaringClass() { } @Override - public Member getMember() { + public Constrainable getConstrainable() { return null; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java index 1277f85051..a5626998c5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java @@ -6,14 +6,13 @@ */ package org.hibernate.validator.internal.metadata.location; -import java.lang.reflect.Executable; -import java.lang.reflect.Field; -import java.lang.reflect.Member; -import java.lang.reflect.Method; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.properties.Constrainable; +import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; /** @@ -39,49 +38,24 @@ static ConstraintLocation forClass(Class declaringClass) { return new BeanConstraintLocation( declaringClass ); } - static ConstraintLocation forField(Field field) { - return new FieldConstraintLocation( field ); - } - - /** - * Create a new {@link GetterConstraintLocation} for the given getter method. - * - * @param getter The getter method being constrained - * @return A new GetterConstraintLocation - */ - static ConstraintLocation forGetter(Method getter) { - return new GetterConstraintLocation( getter.getDeclaringClass(), getter ); - } - - /** - * Create a new {@link GetterConstraintLocation} for the given declaring class and getter method. - *

- * This provides an alternative to {@link ConstraintLocation#forGetter(Method)} where the given declaring class is usually a sub-class of the - * actual class on which the getter method is declared. This is provided to support XML mapping configurations used to specify constraints on - * subclasses for inherited getter methods. - * - * @param declaringClass The class on which the constraint is defined. - * @param getter The getter method being constrained. - * @return A new GetterConstraintLocation - */ - static ConstraintLocation forGetter(Class declaringClass, Method getter ) { - return new GetterConstraintLocation( declaringClass, getter ); + static ConstraintLocation forProperty(Property property) { + return new PropertyConstraintLocation( property ); } static ConstraintLocation forTypeArgument(ConstraintLocation delegate, TypeVariable typeParameter, Type typeOfAnnotatedElement) { return new TypeArgumentConstraintLocation( delegate, typeParameter, typeOfAnnotatedElement ); } - static ConstraintLocation forReturnValue(Executable executable) { - return new ReturnValueConstraintLocation( executable ); + static ConstraintLocation forReturnValue(Callable callable) { + return new ReturnValueConstraintLocation( callable ); } - static ConstraintLocation forCrossParameter(Executable executable) { - return new CrossParameterConstraintLocation( executable ); + static ConstraintLocation forCrossParameter(Callable callable) { + return new CrossParameterConstraintLocation( callable ); } - static ConstraintLocation forParameter(Executable executable, int index) { - return new ParameterConstraintLocation( executable, index ); + static ConstraintLocation forParameter(Callable callable, int index) { + return new ParameterConstraintLocation( callable, index ); } /** @@ -94,7 +68,7 @@ static ConstraintLocation forParameter(Executable executable, int index) { * * @return the member represented by this location. Will be {@code null} when this location represents a type. */ - Member getMember(); + Constrainable getConstrainable(); /** * Returns the type to be used when resolving constraint validators for constraints at this location. Note that this @@ -112,7 +86,7 @@ static ConstraintLocation forParameter(Executable executable, int index) { /** * Obtains the value of this location from the parent. The type of the passed parent depends on the location type, - * e.g. a bean would be passed for a {@link FieldConstraintLocation} or {@link GetterConstraintLocation} but an + * e.g. a bean would be passed for a {@link PropertyConstraintLocation} but an * object array for a {@link ParameterConstraintLocation}. */ Object getValue(Object parent); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java index 0c127fbb0f..549ab73e1e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java @@ -6,11 +6,11 @@ */ package org.hibernate.validator.internal.metadata.location; -import java.lang.reflect.Executable; -import java.lang.reflect.Member; import java.lang.reflect.Type; import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; /** @@ -21,20 +21,20 @@ */ class CrossParameterConstraintLocation implements ConstraintLocation { - private final Executable executable; + private final Callable callable; - CrossParameterConstraintLocation(Executable executable) { - this.executable = executable; + CrossParameterConstraintLocation(Callable executable) { + this.callable = executable; } @Override public Class getDeclaringClass() { - return executable.getDeclaringClass(); + return callable.getDeclaringClass(); } @Override - public Member getMember() { - return executable; + public Constrainable getConstrainable() { + return callable; } @Override @@ -54,15 +54,12 @@ public Object getValue(Object parent) { @Override public String toString() { - return "CrossParameterConstraintLocation [executable=" + executable + "]"; + return "CrossParameterConstraintLocation [callable=" + callable + "]"; } @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ( ( executable == null ) ? 0 : executable.hashCode() ); - return result; + return callable.hashCode(); } @Override @@ -77,12 +74,7 @@ public boolean equals(Object obj) { return false; } CrossParameterConstraintLocation other = (CrossParameterConstraintLocation) obj; - if ( executable == null ) { - if ( other.executable != null ) { - return false; - } - } - else if ( !executable.equals( other.executable ) ) { + if ( !callable.equals( other.callable ) ) { return false; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java index 8c816b2299..c51b9308aa 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java @@ -6,11 +6,11 @@ */ package org.hibernate.validator.internal.metadata.location; -import java.lang.reflect.Executable; -import java.lang.reflect.Member; import java.lang.reflect.Type; import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.ReflectionHelper; @@ -22,24 +22,24 @@ */ public class ParameterConstraintLocation implements ConstraintLocation { - private final Executable executable; + private final Callable callable; private final int index; private final Type typeForValidatorResolution; - ParameterConstraintLocation(Executable executable, int index) { - this.executable = executable; + public ParameterConstraintLocation(Callable callable, int index) { + this.callable = callable; this.index = index; - this.typeForValidatorResolution = ReflectionHelper.boxedType( ReflectionHelper.typeOf( executable, index ) ); + this.typeForValidatorResolution = ReflectionHelper.boxedType( callable.getTypeOfParameter( index ) ); } @Override public Class getDeclaringClass() { - return executable.getDeclaringClass(); + return callable.getDeclaringClass(); } @Override - public Member getMember() { - return executable; + public Constrainable getConstrainable() { + return callable; } @Override @@ -53,8 +53,7 @@ public int getIndex() { @Override public void appendTo(ExecutableParameterNameProvider parameterNameProvider, PathImpl path) { - String name = parameterNameProvider.getParameterNames( executable ).get( index ); - path.addParameterNode( name, index ); + path.addParameterNode( callable.getParameterName( parameterNameProvider, index ), index ); } @Override @@ -64,15 +63,14 @@ public Object getValue(Object parent) { @Override public String toString() { - return "ParameterConstraintLocation [executable=" + executable + ", index=" + index - + ", typeForValidatorResolution=" + typeForValidatorResolution + "]"; + return "ParameterConstraintLocation [executable=" + callable + ", index=" + index + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ( ( executable == null ) ? 0 : executable.hashCode() ); + result = prime * result + callable.hashCode(); result = prime * result + index; return result; } @@ -89,12 +87,7 @@ public boolean equals(Object obj) { return false; } ParameterConstraintLocation other = (ParameterConstraintLocation) obj; - if ( executable == null ) { - if ( other.executable != null ) { - return false; - } - } - else if ( !executable.equals( other.executable ) ) { + if ( !callable.equals( other.callable ) ) { return false; } if ( index != other.index ) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java new file mode 100644 index 0000000000..78b9ccc4b0 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java @@ -0,0 +1,88 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.metadata.location; + +import java.lang.reflect.Type; + +import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.properties.Constrainable; +import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; + +/** + * Property constraint location. + * + * @author Marko Bekhta + */ +public class PropertyConstraintLocation implements ConstraintLocation { + + /** + * The member the constraint was defined on. + */ + private final Property property; + + PropertyConstraintLocation(Property property) { + this.property = property; + } + + @Override + public Class getDeclaringClass() { + return property.getDeclaringClass(); + } + + @Override + public Constrainable getConstrainable() { + return property; + } + + public String getPropertyName() { + return property.getPropertyName(); + } + + @Override + public Type getTypeForValidatorResolution() { + return property.getTypeForValidatorResolution(); + } + + @Override + public void appendTo(ExecutableParameterNameProvider parameterNameProvider, PathImpl path) { + path.addPropertyNode( property.getPropertyName() ); + } + + @Override + public Object getValue(Object parent) { + return property.getValueFrom( parent ); + } + + @Override + public String toString() { + return "PropertyConstraintLocation [property=" + property + "]"; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + PropertyConstraintLocation that = (PropertyConstraintLocation) o; + + if ( !property.equals( that.property ) ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return property.hashCode(); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java index b6ac18e2ca..30c66c5889 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java @@ -6,43 +6,41 @@ */ package org.hibernate.validator.internal.metadata.location; -import java.lang.reflect.Executable; -import java.lang.reflect.Member; import java.lang.reflect.Type; import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; -import org.hibernate.validator.internal.util.ReflectionHelper; /** * Executable return value constraint location. * * @author Hardy Ferentschik * @author Gunnar Morling + * @author Marko Bekhta */ class ReturnValueConstraintLocation implements ConstraintLocation { - private final Executable executable; - private final Type typeForValidatorResolution; + private final Callable callable; - ReturnValueConstraintLocation(Executable executable) { - this.executable = executable; - this.typeForValidatorResolution = ReflectionHelper.boxedType( ReflectionHelper.typeOf( executable ) ); + ReturnValueConstraintLocation(Callable callable) { + this.callable = callable; } @Override public Class getDeclaringClass() { - return executable.getDeclaringClass(); + return callable.getDeclaringClass(); } @Override - public Member getMember() { - return executable; + public Constrainable getConstrainable() { + return callable; } @Override public Type getTypeForValidatorResolution() { - return typeForValidatorResolution; + return callable.getTypeForValidatorResolution(); } @Override @@ -57,14 +55,14 @@ public Object getValue(Object parent) { @Override public String toString() { - return "ReturnValueConstraintLocation [executable=" + executable + "]"; + return "ReturnValueConstraintLocation [executable=" + callable + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ( ( executable == null ) ? 0 : executable.hashCode() ); + result = prime * result + callable.hashCode(); return result; } @@ -80,12 +78,7 @@ public boolean equals(Object obj) { return false; } ReturnValueConstraintLocation other = (ReturnValueConstraintLocation) obj; - if ( executable == null ) { - if ( other.executable != null ) { - return false; - } - } - else if ( !executable.equals( other.executable ) ) { + if ( !callable.equals( other.callable ) ) { return false; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/TypeArgumentConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/TypeArgumentConstraintLocation.java index 989d8a2c76..d470c8c8bd 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/TypeArgumentConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/TypeArgumentConstraintLocation.java @@ -6,11 +6,11 @@ */ package org.hibernate.validator.internal.metadata.location; -import java.lang.reflect.Member; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.StringHelper; @@ -52,8 +52,8 @@ public Class getDeclaringClass() { } @Override - public Member getMember() { - return delegate.getMember(); + public Constrainable getConstrainable() { + return delegate.getConstrainable(); } public TypeVariable getTypeParameter() { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java index 1b387b8e13..12aeaa9e06 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java @@ -63,8 +63,12 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedField; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; import org.hibernate.validator.internal.metadata.raw.ConstrainedType; +import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.properties.Constrainable; +import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; +import org.hibernate.validator.internal.properties.javabean.JavaBeanField; import org.hibernate.validator.internal.util.CollectionHelper; -import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; @@ -214,45 +218,46 @@ private Set getFieldMetaData(Class beanClass) { Set propertyMetaData = newHashSet(); for ( Field field : run( GetDeclaredFields.action( beanClass ) ) ) { + Property property = new JavaBeanField( field ); // HV-172 if ( Modifier.isStatic( field.getModifiers() ) || - annotationProcessingOptions.areMemberConstraintsIgnoredFor( field ) || + annotationProcessingOptions.areMemberConstraintsIgnoredFor( property ) || field.isSynthetic() ) { continue; } - propertyMetaData.add( findPropertyMetaData( field ) ); + propertyMetaData.add( findPropertyMetaData( field, property ) ); } return propertyMetaData; } - private ConstrainedField findPropertyMetaData(Field field) { + private ConstrainedField findPropertyMetaData(Field field, Property property) { Set> constraints = convertToMetaConstraints( - findConstraints( field, ElementType.FIELD ), - field + findConstraints( field, ElementType.FIELD, property ), + property ); CascadingMetaDataBuilder cascadingMetaDataBuilder = findCascadingMetaData( field ); - Set> typeArgumentsConstraints = findTypeAnnotationConstraints( field ); + Set> typeArgumentsConstraints = findTypeAnnotationConstraints( field, property ); return new ConstrainedField( ConfigurationSource.ANNOTATION, - field, + property, constraints, typeArgumentsConstraints, cascadingMetaDataBuilder ); } - private Set> convertToMetaConstraints(List> constraintDescriptors, Field field) { + private Set> convertToMetaConstraints(List> constraintDescriptors, Property property) { if ( constraintDescriptors.isEmpty() ) { return Collections.emptySet(); } Set> constraints = newHashSet(); - ConstraintLocation location = ConstraintLocation.forField( field ); + ConstraintLocation location = ConstraintLocation.forProperty( property ); for ( ConstraintDescriptorImpl constraintDescription : constraintDescriptors ) { constraints.add( MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescription, location ) ); @@ -297,20 +302,23 @@ private Set getMetaData(Executable[] executableElements) * given element. */ private ConstrainedExecutable findExecutableMetaData(Executable executable) { - List parameterConstraints = getParameterMetaData( executable ); + Callable callable = JavaBeanExecutable.of( executable ); + List parameterConstraints = getParameterMetaData( executable, callable ); - Map>> executableConstraints = findConstraints( executable, ExecutableHelper.getElementType( executable ) ) - .stream() - .collect( Collectors.groupingBy( ConstraintDescriptorImpl::getConstraintType ) ); + Map>> executableConstraints = findConstraints( + executable, + callable.isConstructor() ? ElementType.CONSTRUCTOR : ElementType.METHOD, + callable + ).stream().collect( Collectors.groupingBy( ConstraintDescriptorImpl::getConstraintType ) ); Set> crossParameterConstraints; - if ( annotationProcessingOptions.areCrossParameterConstraintsIgnoredFor( executable ) ) { + if ( annotationProcessingOptions.areCrossParameterConstraintsIgnoredFor( callable ) ) { crossParameterConstraints = Collections.emptySet(); } else { crossParameterConstraints = convertToMetaConstraints( executableConstraints.get( ConstraintType.CROSS_PARAMETER ), - executable + callable ); } @@ -318,7 +326,7 @@ private ConstrainedExecutable findExecutableMetaData(Executable executable) { Set> typeArgumentsConstraints; CascadingMetaDataBuilder cascadingMetaDataBuilder; - if ( annotationProcessingOptions.areReturnValueConstraintsIgnoredFor( executable ) ) { + if ( annotationProcessingOptions.areReturnValueConstraintsIgnoredFor( callable ) ) { returnValueConstraints = Collections.emptySet(); typeArgumentsConstraints = Collections.emptySet(); cascadingMetaDataBuilder = CascadingMetaDataBuilder.nonCascading(); @@ -326,17 +334,17 @@ private ConstrainedExecutable findExecutableMetaData(Executable executable) { else { AnnotatedType annotatedReturnType = executable.getAnnotatedReturnType(); - typeArgumentsConstraints = findTypeAnnotationConstraints( executable, annotatedReturnType ); + typeArgumentsConstraints = findTypeAnnotationConstraints( executable, callable, annotatedReturnType ); returnValueConstraints = convertToMetaConstraints( executableConstraints.get( ConstraintType.GENERIC ), - executable + callable ); cascadingMetaDataBuilder = findCascadingMetaData( executable, annotatedReturnType ); } return new ConstrainedExecutable( ConfigurationSource.ANNOTATION, - executable, + callable, parameterConstraints, crossParameterConstraints, returnValueConstraints, @@ -345,15 +353,15 @@ private ConstrainedExecutable findExecutableMetaData(Executable executable) { ); } - private Set> convertToMetaConstraints(List> constraintsDescriptors, Executable executable) { + private Set> convertToMetaConstraints(List> constraintsDescriptors, Callable callable) { if ( constraintsDescriptors == null ) { return Collections.emptySet(); } Set> constraints = newHashSet(); - ConstraintLocation returnValueLocation = ConstraintLocation.forReturnValue( executable ); - ConstraintLocation crossParameterLocation = ConstraintLocation.forCrossParameter( executable ); + ConstraintLocation returnValueLocation = ConstraintLocation.forReturnValue( callable ); + ConstraintLocation crossParameterLocation = ConstraintLocation.forCrossParameter( callable ); for ( ConstraintDescriptorImpl constraintDescriptor : constraintsDescriptors ) { ConstraintLocation location = constraintDescriptor.getConstraintType() == ConstraintType.GENERIC ? returnValueLocation : crossParameterLocation; @@ -369,9 +377,10 @@ private Set> convertToMetaConstraints(List getParameterMetaData(Executable executable) { + private List getParameterMetaData(Executable executable, Callable callable) { if ( executable.getParameterCount() == 0 ) { return Collections.emptyList(); } @@ -393,12 +402,12 @@ private List getParameterMetaData(Executable executable) { Set> parameterConstraints = newHashSet(); - if ( annotationProcessingOptions.areParameterConstraintsIgnoredFor( executable, i ) ) { + if ( annotationProcessingOptions.areParameterConstraintsIgnoredFor( callable, i ) ) { Type type = ReflectionHelper.typeOf( executable, i ); metaData.add( new ConstrainedParameter( ConfigurationSource.ANNOTATION, - executable, + callable, type, i, parameterConstraints, @@ -410,12 +419,12 @@ private List getParameterMetaData(Executable executable) { continue; } - ConstraintLocation location = ConstraintLocation.forParameter( executable, i ); + ConstraintLocation location = ConstraintLocation.forParameter( callable, i ); for ( Annotation parameterAnnotation : parameterAnnotations ) { // collect constraints if this annotation is a constraint annotation List> constraints = findConstraintAnnotations( - executable, parameterAnnotation, ElementType.PARAMETER + callable, parameterAnnotation, ElementType.PARAMETER ); for ( ConstraintDescriptorImpl constraintDescriptorImpl : constraints ) { parameterConstraints.add( @@ -426,13 +435,13 @@ private List getParameterMetaData(Executable executable) { AnnotatedType parameterAnnotatedType = parameter.getAnnotatedType(); - Set> typeArgumentsConstraints = findTypeAnnotationConstraintsForExecutableParameter( executable, i, parameterAnnotatedType ); + Set> typeArgumentsConstraints = findTypeAnnotationConstraintsForExecutableParameter( executable, callable, i, parameterAnnotatedType ); CascadingMetaDataBuilder cascadingMetaData = findCascadingMetaData( executable, parameters, i, parameterAnnotatedType ); metaData.add( new ConstrainedParameter( ConfigurationSource.ANNOTATION, - executable, + callable, ReflectionHelper.typeOf( executable, i ), i, parameterConstraints, @@ -455,10 +464,10 @@ private List getParameterMetaData(Executable executable) { * * @return A list of constraint descriptors for all constraint specified for the given member. */ - private List> findConstraints(Member member, ElementType type) { + private List> findConstraints(Member member, ElementType type, Constrainable constrainable) { List> metaData = newArrayList(); for ( Annotation annotation : ( (AccessibleObject) member ).getDeclaredAnnotations() ) { - metaData.addAll( findConstraintAnnotations( member, annotation, type ) ); + metaData.addAll( findConstraintAnnotations( constrainable, annotation, type ) ); } return metaData; @@ -483,7 +492,7 @@ private List> findClassLevelConstraints(Class bea /** * Examines the given annotation to see whether it is a single- or multi-valued constraint annotation. * - * @param member The member to check for constraints annotations + * @param constrainable The constrainable to check for constraints annotations * @param annotation The annotation to examine * @param type the element type on which the annotation/constraint is placed on * @param the annotation type @@ -491,7 +500,8 @@ private List> findClassLevelConstraints(Class bea * @return A list of constraint descriptors or the empty list in case {@code annotation} is neither a * single nor multi-valued annotation. */ - protected List> findConstraintAnnotations(Member member, + protected List> findConstraintAnnotations( + Constrainable constrainable, A annotation, ElementType type) { @@ -512,7 +522,7 @@ else if ( constraintHelper.isMultiValueConstraint( annotationType ) ) { } return constraints.stream() - .map( c -> buildConstraintDescriptor( member, c, type ) ) + .map( c -> buildConstraintDescriptor( constrainable, c, type ) ) .collect( Collectors.toList() ); } @@ -549,12 +559,12 @@ private Map, Class> getGroupConversions(ConvertGroup groupConversion return groupConversions; } - private ConstraintDescriptorImpl buildConstraintDescriptor(Member member, + private ConstraintDescriptorImpl buildConstraintDescriptor(Constrainable constrainable, A annotation, ElementType type) { return new ConstraintDescriptorImpl<>( constraintHelper, - member, + constrainable, new ConstraintAnnotationDescriptor<>( annotation ), type ); @@ -573,22 +583,22 @@ private T run(PrivilegedAction action) { /** * Finds type arguments constraints for fields. */ - protected Set> findTypeAnnotationConstraints(Field field) { + protected Set> findTypeAnnotationConstraints(Field field, Property property) { return findTypeArgumentsConstraints( - field, - new TypeArgumentFieldLocation( field ), - field.getAnnotatedType() + property, + new TypeArgumentFieldLocation( field ), + field.getAnnotatedType() ); } /** * Finds type arguments constraints for method return values. */ - protected Set> findTypeAnnotationConstraints(Executable executable, AnnotatedType annotatedReturnType) { + protected Set> findTypeAnnotationConstraints(Executable executable, Callable callable, AnnotatedType annotatedReturnType) { return findTypeArgumentsConstraints( - executable, - new TypeArgumentReturnValueLocation( executable ), - annotatedReturnType + callable, + new TypeArgumentReturnValueLocation( executable ), + annotatedReturnType ); } @@ -707,10 +717,10 @@ else if ( annotatedType instanceof AnnotatedParameterizedType ) { * * @return a set of type arguments constraints, or an empty set if no constrained type arguments are found */ - protected Set> findTypeAnnotationConstraintsForExecutableParameter(Executable executable, int i, AnnotatedType parameterAnnotatedType) { + protected Set> findTypeAnnotationConstraintsForExecutableParameter(Executable executable, Callable callable, int i, AnnotatedType parameterAnnotatedType) { try { return findTypeArgumentsConstraints( - executable, + callable, new TypeArgumentExecutableParameterLocation( executable, i ), parameterAnnotatedType ); @@ -721,7 +731,7 @@ protected Set> findTypeAnnotationConstraintsForExecutableParam } } - private Set> findTypeArgumentsConstraints(Member member, TypeArgumentLocation location, AnnotatedType annotatedType) { + private Set> findTypeArgumentsConstraints(Constrainable constrainable, TypeArgumentLocation location, AnnotatedType annotatedType) { // HV-1428 Container element support is disabled for arrays if ( !(annotatedType instanceof AnnotatedParameterizedType) ) { return Collections.emptySet(); @@ -735,9 +745,9 @@ private Set> findTypeArgumentsConstraints(Member member, TypeA Type validatedType = annotatedArrayType.getAnnotatedGenericComponentType().getType(); TypeVariable arrayElementTypeArgument = new ArrayElement( annotatedArrayType ); - typeArgumentConstraints.addAll( findTypeUseConstraints( member, annotatedArrayType, arrayElementTypeArgument, location, validatedType ) ); + typeArgumentConstraints.addAll( findTypeUseConstraints( constrainable, annotatedArrayType, arrayElementTypeArgument, location, validatedType ) ); - typeArgumentConstraints.addAll( findTypeArgumentsConstraints( member, + typeArgumentConstraints.addAll( findTypeArgumentsConstraints( constrainable, new NestedTypeArgumentLocation( location, arrayElementTypeArgument, validatedType ), annotatedArrayType.getAnnotatedGenericComponentType() ) ); } @@ -755,10 +765,10 @@ else if ( annotatedType instanceof AnnotatedParameterizedType ) { // In the latter case a value unwrapping has to occur Type validatedType = annotatedTypeParameter.getType(); - typeArgumentConstraints.addAll( findTypeUseConstraints( member, annotatedTypeParameter, typeVariable, location, validatedType ) ); + typeArgumentConstraints.addAll( findTypeUseConstraints( constrainable, annotatedTypeParameter, typeVariable, location, validatedType ) ); if ( validatedType instanceof ParameterizedType ) { - typeArgumentConstraints.addAll( findTypeArgumentsConstraints( member, + typeArgumentConstraints.addAll( findTypeArgumentsConstraints( constrainable, new NestedTypeArgumentLocation( location, typeVariable, validatedType ), annotatedTypeParameter ) ); } @@ -773,9 +783,9 @@ else if ( annotatedType instanceof AnnotatedParameterizedType ) { /** * Finds type use annotation constraints defined on the type argument. */ - private Set> findTypeUseConstraints(Member member, AnnotatedType typeArgument, TypeVariable typeVariable, TypeArgumentLocation location, Type type) { + private Set> findTypeUseConstraints(Constrainable constrainable, AnnotatedType typeArgument, TypeVariable typeVariable, TypeArgumentLocation location, Type type) { Set> constraints = Arrays.stream( typeArgument.getAnnotations() ) - .flatMap( a -> findConstraintAnnotations( member, a, ElementType.TYPE_USE ).stream() ) + .flatMap( a -> findConstraintAnnotations( constrainable, a, ElementType.TYPE_USE ).stream() ) .map( d -> createTypeArgumentMetaConstraint( d, location, typeVariable, type ) ) .collect( Collectors.toSet() ); @@ -801,7 +811,7 @@ private CascadingMetaDataBuilder getCascadingMetaData(Type type, AnnotatedElemen * The location of a type argument before it is really considered a constraint location. *

* It avoids initializing a constraint location if we did not find any constraints. This is especially useful in - * a Java 9 environment as {@link ConstraintLocation#forProperty(Member) tries to make the {@code Member} accessible + * a Java 9 environment as {@link ConstraintLocation#forProperty(Property)} tries to make the {@code Member} accessible * which might not be possible (for instance for {@code java.util} classes). */ private interface TypeArgumentLocation { @@ -820,7 +830,7 @@ private TypeArgumentExecutableParameterLocation(Executable executable, int index @Override public ConstraintLocation toConstraintLocation() { - return ConstraintLocation.forParameter( executable, index ); + return ConstraintLocation.forParameter( JavaBeanExecutable.of( executable ), index ); } } @@ -833,7 +843,7 @@ private TypeArgumentFieldLocation(Field field) { @Override public ConstraintLocation toConstraintLocation() { - return ConstraintLocation.forField( field ); + return ConstraintLocation.forProperty( new JavaBeanField( field ) ); } } @@ -846,7 +856,7 @@ private TypeArgumentReturnValueLocation(Executable executable) { @Override public ConstraintLocation toConstraintLocation() { - return ConstraintLocation.forReturnValue( executable ); + return ConstraintLocation.forReturnValue( JavaBeanExecutable.of( executable ) ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedExecutable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedExecutable.java index 8069e49cd3..f7d6b0c63f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedExecutable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedExecutable.java @@ -10,8 +10,6 @@ import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; import java.lang.invoke.MethodHandles; -import java.lang.reflect.Constructor; -import java.lang.reflect.Executable; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -21,9 +19,9 @@ import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.util.CollectionHelper; -import org.hibernate.validator.internal.util.ReflectionHelper; -import org.hibernate.validator.internal.util.StringHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.util.stereotypes.Immutable; @@ -40,7 +38,7 @@ public class ConstrainedExecutable extends AbstractConstrainedElement { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - private final Executable executable; + private final Callable callable; /** * Constrained-related meta data for this executable's parameters. @@ -59,7 +57,7 @@ public class ConstrainedExecutable extends AbstractConstrainedElement { * Creates a new executable meta data object for a parameter-less executable. * * @param source The source of meta data. - * @param executable The represented executable. + * @param callable The represented executable. * @param returnValueConstraints Type arguments constraints, if any. * @param typeArgumentConstraints The type argument constraints on the return value of the represented executable, * if any. @@ -67,13 +65,13 @@ public class ConstrainedExecutable extends AbstractConstrainedElement { */ public ConstrainedExecutable( ConfigurationSource source, - Executable executable, + Callable callable, Set> returnValueConstraints, Set> typeArgumentConstraints, CascadingMetaDataBuilder cascadingMetaDataBuilder) { this( source, - executable, + callable, Collections.emptyList(), Collections.>emptySet(), returnValueConstraints, @@ -86,7 +84,7 @@ public ConstrainedExecutable( * Creates a new executable meta data object. * * @param source The source of meta data. - * @param executable The represented executable. + * @param callable The represented executable. * @param parameterMetaData A list with parameter meta data. The length must correspond with the number of * parameters of the represented executable. So this list may be empty (in case of a parameterless executable), but * never {@code null}. @@ -98,7 +96,7 @@ public ConstrainedExecutable( */ public ConstrainedExecutable( ConfigurationSource source, - Executable executable, + Callable callable, List parameterMetaData, Set> crossParameterConstraints, Set> returnValueConstraints, @@ -106,18 +104,18 @@ public ConstrainedExecutable( CascadingMetaDataBuilder cascadingMetaDataBuilder) { super( source, - ( executable instanceof Constructor ) ? ConstrainedElementKind.CONSTRUCTOR : ConstrainedElementKind.METHOD, + callable.isConstructor() ? ConstrainedElementKind.CONSTRUCTOR : ConstrainedElementKind.METHOD, returnValueConstraints, typeArgumentConstraints, cascadingMetaDataBuilder ); - this.executable = executable; + this.callable = callable; - if ( parameterMetaData.size() != executable.getParameterTypes().length ) { + if ( parameterMetaData.size() != callable.getParameterTypes().length ) { throw LOG.getInvalidLengthOfParameterMetaDataListException( - executable, - executable.getParameterTypes().length, + callable, + callable.getParameterTypes().length, parameterMetaData.size() ); } @@ -125,7 +123,7 @@ public ConstrainedExecutable( this.crossParameterConstraints = CollectionHelper.toImmutableSet( crossParameterConstraints ); this.parameterMetaData = CollectionHelper.toImmutableList( parameterMetaData ); this.hasParameterConstraints = hasParameterConstraints( parameterMetaData ) || !crossParameterConstraints.isEmpty(); - this.isGetterMethod = ReflectionHelper.isGetterMethod( executable ); + this.isGetterMethod = callable instanceof Property; } /** @@ -142,7 +140,7 @@ public ConstrainedExecutable( public ConstrainedParameter getParameterMetaData(int parameterIndex) { if ( parameterIndex < 0 || parameterIndex > parameterMetaData.size() - 1 ) { throw LOG.getInvalidExecutableParameterIndexException( - executable, + callable, parameterIndex ); } @@ -202,13 +200,13 @@ public boolean isGetterMethod() { return isGetterMethod; } - public Executable getExecutable() { - return executable; + public Callable getCallable() { + return callable; } @Override public String toString() { - return "ConstrainedExecutable [executable=" + StringHelper.toShortString( executable ) + return "ConstrainedExecutable [executable=" + callable + ", parameterMetaData=" + parameterMetaData + ", hasParameterConstraints=" + hasParameterConstraints + "]"; } @@ -284,7 +282,7 @@ public ConstrainedExecutable merge(ConstrainedExecutable other) { return new ConstrainedExecutable( mergedSource, - executable, + callable, mergedParameterMetaData, mergedCrossParameterConstraints, mergedReturnValueConstraints, @@ -307,8 +305,7 @@ private Set> getDescriptors(Iterable> public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result - + ( ( executable == null ) ? 0 : executable.hashCode() ); + result = prime * result + callable.hashCode(); return result; } @@ -324,12 +321,7 @@ public boolean equals(Object obj) { return false; } ConstrainedExecutable other = (ConstrainedExecutable) obj; - if ( executable == null ) { - if ( other.executable != null ) { - return false; - } - } - else if ( !executable.equals( other.executable ) ) { + if ( !callable.equals( other.callable ) ) { return false; } return true; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedField.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedField.java index cc889ae089..e9f996c89f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedField.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedField.java @@ -6,12 +6,11 @@ */ package org.hibernate.validator.internal.metadata.raw; -import java.lang.reflect.Field; import java.util.Set; import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; import org.hibernate.validator.internal.metadata.core.MetaConstraint; -import org.hibernate.validator.internal.util.StringHelper; +import org.hibernate.validator.internal.properties.Property; /** * Represents a field of a Java type and all its associated meta-data relevant @@ -19,45 +18,45 @@ * * @author Gunnar Morling * @author Guillaume Smet + * @author Marko Bekhta */ public class ConstrainedField extends AbstractConstrainedElement { - private final Field field; + private final Property property; /** * Creates a new field meta data object. * * @param source The source of meta data. - * @param field The represented field. + * @param property The represented field. * @param constraints The constraints of the represented field, if any. * @param typeArgumentConstraints Type arguments constraints, if any. * @param cascadingMetaDataBuilder The cascaded validation metadata for this element and its container elements. */ public ConstrainedField(ConfigurationSource source, - Field field, - Set> constraints, - Set> typeArgumentConstraints, - CascadingMetaDataBuilder cascadingMetaDataBuilder) { + Property property, + Set> constraints, + Set> typeArgumentConstraints, + CascadingMetaDataBuilder cascadingMetaDataBuilder) { super( source, ConstrainedElementKind.FIELD, constraints, typeArgumentConstraints, cascadingMetaDataBuilder ); - this.field = field; - } + this.property = property; - public Field getField() { - return field; } + public Property getProperty() { + return property; + } @Override public String toString() { - return "ConstrainedField [field=" + StringHelper.toShortString( field ) + "]"; + return "ConstrainedField [property=" + property.getName() + "]"; } @Override public int hashCode() { - final int prime = 31; int result = super.hashCode(); - result = prime * result + ( ( field == null ) ? 0 : field.hashCode() ); + result = 31 * result + this.property.hashCode(); return result; } @@ -73,14 +72,6 @@ public boolean equals(Object obj) { return false; } ConstrainedField other = (ConstrainedField) obj; - if ( field == null ) { - if ( other.field != null ) { - return false; - } - } - else if ( !field.equals( other.field ) ) { - return false; - } - return true; + return this.property.equals( other.property ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedParameter.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedParameter.java index d8d161d764..dab9ac417c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedParameter.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedParameter.java @@ -8,7 +8,6 @@ import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; -import java.lang.reflect.Executable; import java.lang.reflect.Type; import java.util.Collections; import java.util.HashSet; @@ -16,6 +15,7 @@ import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.properties.Callable; /** * Contains constraint-related meta-data for one method parameter. @@ -25,17 +25,17 @@ */ public class ConstrainedParameter extends AbstractConstrainedElement { - private final Executable executable; + private final Callable callable; private final Type type; private final int index; public ConstrainedParameter(ConfigurationSource source, - Executable executable, + Callable callable, Type type, int index) { this( source, - executable, + callable, type, index, Collections.>emptySet(), @@ -48,7 +48,7 @@ public ConstrainedParameter(ConfigurationSource source, * Creates a new parameter meta data object. * * @param source The source of meta data. - * @param executable The executable of the represented method parameter. + * @param callable The executable of the represented method parameter. * @param type the parameter type * @param index the index of the parameter * @param constraints The constraints of the represented method parameter, if @@ -57,7 +57,7 @@ public ConstrainedParameter(ConfigurationSource source, * @param cascadingMetaDataBuilder The cascaded validation metadata for this element and its container elements. */ public ConstrainedParameter(ConfigurationSource source, - Executable executable, + Callable callable, Type type, int index, Set> constraints, @@ -71,7 +71,7 @@ public ConstrainedParameter(ConfigurationSource source, cascadingMetaDataBuilder ); - this.executable = executable; + this.callable = callable; this.type = type; this.index = index; } @@ -80,8 +80,8 @@ public Type getType() { return type; } - public Executable getExecutable() { - return executable; + public Callable getCallable() { + return callable; } public int getIndex() { @@ -109,7 +109,7 @@ public ConstrainedParameter merge(ConstrainedParameter other) { return new ConstrainedParameter( mergedSource, - executable, + callable, type, index, mergedConstraints, @@ -130,7 +130,7 @@ public String toString() { String constraintsAsString = sb.length() > 0 ? sb.substring( 0, sb.length() - 2 ) : sb.toString(); - return "ParameterMetaData [executable=" + executable + ", index=" + index + "], constraints=[" + return "ParameterMetaData [callable=" + callable + ", index=" + index + "], constraints=[" + constraintsAsString + "]"; } @@ -139,7 +139,7 @@ public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + index; - result = prime * result + ( ( executable == null ) ? 0 : executable.hashCode() ); + result = prime * result + callable.hashCode(); return result; } @@ -158,12 +158,7 @@ public boolean equals(Object obj) { if ( index != other.index ) { return false; } - if ( executable == null ) { - if ( other.executable != null ) { - return false; - } - } - else if ( !executable.equals( other.executable ) ) { + else if ( !callable.equals( other.callable ) ) { return false; } return true; diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/Callable.java b/engine/src/main/java/org/hibernate/validator/internal/properties/Callable.java new file mode 100644 index 0000000000..b25586c4b1 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/Callable.java @@ -0,0 +1,41 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.properties; + +import java.lang.reflect.Type; + +import org.hibernate.validator.internal.util.ExecutableHelper; +import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; + +/** + * @author Marko Bekhta + */ +public interface Callable extends Constrainable { + + boolean hasReturnValue(); + + boolean hasParameters(); + + Class[] getParameterTypes(); + + Type[] getGenericParameterTypes(); + + String getParameterName(ExecutableParameterNameProvider parameterNameProvider, int parameterIndex); + + boolean isPrivate(); + + boolean isConstructor(); + + String getSignature(); + + Type getTypeOfParameter(int parameterIndex); + + boolean overrides(ExecutableHelper executableHelper, Callable superTypeMethod); + + boolean isResolvedToSameMethodInHierarchy(ExecutableHelper executableHelper, Class mainSubType, Callable superTypeMethod); + +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/Constrainable.java b/engine/src/main/java/org/hibernate/validator/internal/properties/Constrainable.java new file mode 100644 index 0000000000..871ef7f911 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/Constrainable.java @@ -0,0 +1,31 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.properties; + +import java.lang.reflect.Type; + +/** + * An element on which it is possible to define constraints (e.g. a JavaBean property, a JavaBean method, a JSON + * property). + * + * @author Marko Bekhta + */ +public interface Constrainable { + + String getName(); + + Class getDeclaringClass(); + + Type getTypeForValidatorResolution(); + + Type getType(); + + @SuppressWarnings("unchecked") + default T as(Class clazz) { + return ( (T) this ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/ConstrainableType.java b/engine/src/main/java/org/hibernate/validator/internal/properties/ConstrainableType.java new file mode 100644 index 0000000000..9f0f0b3a00 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/ConstrainableType.java @@ -0,0 +1,16 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.properties; + +/** + * A type that can be constrained. Will represent a Java class for a JavaBean or a named type for JSON. + * + * @author Marko Bekhta + */ +public interface ConstrainableType { + +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/Property.java b/engine/src/main/java/org/hibernate/validator/internal/properties/Property.java new file mode 100644 index 0000000000..f6f1d4c288 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/Property.java @@ -0,0 +1,17 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.properties; + +/** + * @author Marko Bekhta + */ +public interface Property extends Constrainable { + + Object getValueFrom(Object bean); + + String getPropertyName(); +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBean.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBean.java new file mode 100644 index 0000000000..ff9dd436dc --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBean.java @@ -0,0 +1,37 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.properties.javabean; + +import java.util.Arrays; +import java.util.stream.Stream; + +import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.ConstrainableType; +import org.hibernate.validator.internal.util.ReflectionHelper; + +/** + * @author Marko Bekhta + */ +public class JavaBean implements ConstrainableType { + + private final Class clazz; + + public JavaBean(Class clazz) { + this.clazz = clazz; + } + + public Stream getFieldProperties() { + return Arrays.stream( clazz.getDeclaredFields() ) + .map( JavaBeanField::new ); + } + + public Stream getGetterProperties() { + return Arrays.stream( clazz.getDeclaredMethods() ) + .filter( ReflectionHelper::isGetterMethod ) + .map( JavaBeanGetter::new ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java new file mode 100644 index 0000000000..afe1e9211a --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java @@ -0,0 +1,187 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.properties.javabean; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; + +import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.util.ExecutableHelper; +import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; +import org.hibernate.validator.internal.util.ReflectionHelper; +import org.hibernate.validator.internal.util.TypeHelper; + +/** + * @author Marko Bekhta + */ +public class JavaBeanExecutable implements Callable { + + protected final Executable executable; + private final Type typeForValidatorResolution; + private final String name; + private final boolean hasParameters; + private final boolean hasReturnValue; + private final Type type; + + JavaBeanExecutable(Executable executable) { + this.executable = executable; + this.name = executable.getName(); + this.type = ReflectionHelper.typeOf( executable ); + this.typeForValidatorResolution = ReflectionHelper.boxedType( type ); + this.hasParameters = executable.getParameterTypes().length > 0; + this.hasReturnValue = hasReturnValue( executable ); + } + + public static JavaBeanExecutable of(Executable executable) { + if ( ReflectionHelper.isGetterMethod( executable ) ) { + return new JavaBeanGetter( (Method) executable ); + } + else { + return new JavaBeanExecutable( executable ); + } + } + + @Override + public boolean hasReturnValue() { + return hasReturnValue; + } + + @Override + public boolean hasParameters() { + return hasParameters; + } + + @Override + public String getName() { + return name; + } + + @Override + public Class getDeclaringClass() { + return executable.getDeclaringClass(); + } + + @Override + public Type getTypeForValidatorResolution() { + return typeForValidatorResolution; + } + + @Override + public Type getType() { + return type; + } + + @Override + public Class[] getParameterTypes() { + return executable.getParameterTypes(); + } + + @Override + public Type[] getGenericParameterTypes() { + return executable.getGenericParameterTypes(); + } + + @Override + public String getParameterName(ExecutableParameterNameProvider parameterNameProvider, int parameterIndex) { + return parameterNameProvider.getParameterNames( executable ).get( parameterIndex ); + } + + @Override + public boolean isPrivate() { + return Modifier.isPrivate( executable.getModifiers() ); + } + + @Override + public boolean isConstructor() { + return executable instanceof Constructor; + } + + @Override + public String getSignature() { + return ExecutableHelper.getSignature( executable ); + } + + @Override + public Type getTypeOfParameter(int parameterIndex) { + Type[] genericParameterTypes = executable.getGenericParameterTypes(); + + // getGenericParameterTypes() doesn't return synthetic parameters; in this case fall back to getParameterTypes() + if ( parameterIndex >= genericParameterTypes.length ) { + genericParameterTypes = executable.getParameterTypes(); + } + + Type type = genericParameterTypes[parameterIndex]; + + if ( type instanceof TypeVariable ) { + type = TypeHelper.getErasedType( type ); + } + return type; + } + + @Override + public boolean overrides(ExecutableHelper executableHelper, Callable superTypeMethod) { + return executableHelper.overrides( ( (Method) this.executable ), ( (Method) ( (JavaBeanExecutable) superTypeMethod ).executable ) ); + } + + @Override + public boolean isResolvedToSameMethodInHierarchy(ExecutableHelper executableHelper, Class mainSubType, Callable superTypeMethod) { + return executableHelper.isResolvedToSameMethodInHierarchy( mainSubType, ( (Method) this.executable ), ( (Method) ( (JavaBeanExecutable) superTypeMethod ).executable ) ); + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || this.getClass() != o.getClass() ) { + return false; + } + + JavaBeanExecutable that = (JavaBeanExecutable) o; + + if ( this.hasParameters != that.hasParameters ) { + return false; + } + if ( this.hasReturnValue != that.hasReturnValue ) { + return false; + } + if ( !this.executable.equals( that.executable ) ) { + return false; + } + if ( !this.typeForValidatorResolution.equals( that.typeForValidatorResolution ) ) { + return false; + } + if ( !this.name.equals( that.name ) ) { + return false; + } + return this.type.equals( that.type ); + } + + @Override + public int hashCode() { + int result = this.executable.hashCode(); + result = 31 * result + this.typeForValidatorResolution.hashCode(); + result = 31 * result + this.name.hashCode(); + result = 31 * result + ( this.hasParameters ? 1 : 0 ); + result = 31 * result + ( this.hasReturnValue ? 1 : 0 ); + result = 31 * result + this.type.hashCode(); + return result; + } + + private boolean hasReturnValue(Executable executable) { + if ( executable instanceof Constructor ) { + return true; + } + else { + return ( (Method) executable ).getGenericReturnType() != void.class; + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java similarity index 52% rename from engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java rename to engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java index 4e8c21f963..8ea4eb2067 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java @@ -4,52 +4,38 @@ * License: Apache License, Version 2.0 * See the license.txt file in the root directory or . */ -package org.hibernate.validator.internal.metadata.location; +package org.hibernate.validator.internal.properties.javabean; import java.lang.reflect.Field; -import java.lang.reflect.Member; import java.lang.reflect.Type; import java.security.AccessController; import java.security.PrivilegedAction; import org.hibernate.validator.HibernateValidatorPermission; -import org.hibernate.validator.internal.engine.path.PathImpl; -import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; +import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.util.ReflectionHelper; -import org.hibernate.validator.internal.util.StringHelper; import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredField; /** - * Field constraint location. - * - * @author Hardy Ferentschik - * @author Gunnar Morling + * @author Marko Bekhta */ -public class FieldConstraintLocation implements ConstraintLocation { +public class JavaBeanField implements Property { - /** - * The member the constraint was defined on. - */ private final Field field; - - private final Field accessibleField; - - /** - * The property name associated with the member. - */ - private final String propertyName; - - /** - * The type to be used for validator resolution for constraints at this location. - */ + private final String name; private final Type typeForValidatorResolution; + private final Type type; + public JavaBeanField(Field field) { + this.field = getAccessible( field ); + this.name = field.getName(); + this.type = ReflectionHelper.typeOf( field ); + this.typeForValidatorResolution = ReflectionHelper.boxedType( this.type ); + } - FieldConstraintLocation(Field field) { - this.field = field; - this.accessibleField = getAccessible( field ); - this.propertyName = ReflectionHelper.getPropertyName( field ); - this.typeForValidatorResolution = ReflectionHelper.boxedType( ReflectionHelper.typeOf( field ) ); + @Override + public String getName() { + return name; } @Override @@ -58,12 +44,8 @@ public Class getDeclaringClass() { } @Override - public Member getMember() { - return field; - } - - public String getPropertyName() { - return propertyName; + public Type getType() { + return type; } @Override @@ -72,19 +54,13 @@ public Type getTypeForValidatorResolution() { } @Override - public void appendTo(ExecutableParameterNameProvider parameterNameProvider, PathImpl path) { - path.addPropertyNode( propertyName ); + public Object getValueFrom(Object bean) { + return ReflectionHelper.getValue( field, bean ); } @Override - public Object getValue(Object parent) { - return ReflectionHelper.getValue( accessibleField, parent ); - } - - @Override - public String toString() { - return "FieldConstraintLocation [member=" + StringHelper.toShortString( field ) + ", typeForValidatorResolution=" - + StringHelper.toShortString( typeForValidatorResolution ) + "]"; + public String getPropertyName() { + return getName(); } @Override @@ -92,26 +68,30 @@ public boolean equals(Object o) { if ( this == o ) { return true; } - if ( o == null || getClass() != o.getClass() ) { + if ( o == null || this.getClass() != o.getClass() ) { return false; } - FieldConstraintLocation that = (FieldConstraintLocation) o; + JavaBeanField that = (JavaBeanField) o; - if ( field != null ? !field.equals( that.field ) : that.field != null ) { + if ( !this.field.equals( that.field ) ) { return false; } - if ( !typeForValidatorResolution.equals( that.typeForValidatorResolution ) ) { + if ( !this.name.equals( that.name ) ) { return false; } - - return true; + if ( !this.typeForValidatorResolution.equals( that.typeForValidatorResolution ) ) { + return false; + } + return this.type.equals( that.type ); } @Override public int hashCode() { - int result = field != null ? field.hashCode() : 0; - result = 31 * result + typeForValidatorResolution.hashCode(); + int result = this.field.hashCode(); + result = 31 * result + this.name.hashCode(); + result = 31 * result + this.typeForValidatorResolution.hashCode(); + result = 31 * result + this.type.hashCode(); return result; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java similarity index 52% rename from engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java rename to engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java index 129772a320..113aca02a5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java @@ -4,7 +4,7 @@ * License: Apache License, Version 2.0 * See the license.txt file in the root directory or . */ -package org.hibernate.validator.internal.metadata.location; +package org.hibernate.validator.internal.properties.javabean; import java.lang.reflect.Method; import java.lang.reflect.Type; @@ -12,36 +12,19 @@ import java.security.PrivilegedAction; import org.hibernate.validator.HibernateValidatorPermission; -import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.ReflectionHelper; -import org.hibernate.validator.internal.util.StringHelper; import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethod; /** - * Getter method constraint location. - * - * @author Hardy Ferentschik - * @author Gunnar Morling + * @author Marko Bekhta */ -public class GetterConstraintLocation implements ConstraintLocation { - - /** - * The method the constraint was defined on. - */ - private final Method method; +public class JavaBeanGetter extends JavaBeanExecutable implements Property { - private final Method accessibleMethod; - - /** - * The property name associated with the method. - */ - private final String propertyName; + private static final Class[] PARAMETER_TYPES = new Class[0]; - /** - * The type to be used for validator resolution for constraints at this location. - */ - private final Type typeForValidatorResolution; + private final String name; /** * The class of the method for which the constraint was defined. @@ -51,48 +34,58 @@ public class GetterConstraintLocation implements ConstraintLocation { */ private final Class declaringClass; + public JavaBeanGetter(Method method) { + super( getAccessible( method ) ); + this.name = ReflectionHelper.getPropertyName( method ); + this.declaringClass = method.getDeclaringClass(); + } - GetterConstraintLocation( Class declaringClass, Method method ) { - this.method = method; - this.accessibleMethod = getAccessible( method ); - this.propertyName = ReflectionHelper.getPropertyName( method ); - this.typeForValidatorResolution = ReflectionHelper.boxedType( ReflectionHelper.typeOf( method ) ); + public JavaBeanGetter(Class declaringClass, Method method) { + super( getAccessible( method ) ); + this.name = ReflectionHelper.getPropertyName( method ); this.declaringClass = declaringClass; } @Override - public Class getDeclaringClass() { - return declaringClass; + public Object getValueFrom(Object bean) { + return ReflectionHelper.getValue( (Method) executable, bean ); } @Override - public Method getMember() { - return method; + public String getPropertyName() { + return name; } - public String getPropertyName() { - return propertyName; + @Override + public boolean hasReturnValue() { + // getters should always have a return value + return true; } @Override - public Type getTypeForValidatorResolution() { - return typeForValidatorResolution; + public boolean hasParameters() { + // getters should never have parameters + return false; } @Override - public void appendTo(ExecutableParameterNameProvider parameterNameProvider, PathImpl path) { - path.addPropertyNode( propertyName ); + public Class[] getParameterTypes() { + return PARAMETER_TYPES; } @Override - public Object getValue(Object parent) { - return ReflectionHelper.getValue( accessibleMethod, parent ); + public Type[] getGenericParameterTypes() { + return PARAMETER_TYPES; } @Override - public String toString() { - return "GetterConstraintLocation [method=" + StringHelper.toShortString( method ) + ", typeForValidatorResolution=" - + StringHelper.toShortString( typeForValidatorResolution ) + "]"; + public String getParameterName(ExecutableParameterNameProvider parameterNameProvider, int parameterIndex) { + throw new IllegalStateException( "Getters cannot have parameters" ); + } + + @Override + public Class getDeclaringClass() { + return declaringClass; } @Override @@ -100,26 +93,22 @@ public boolean equals(Object o) { if ( this == o ) { return true; } - if ( o == null || getClass() != o.getClass() ) { + if ( o == null || this.getClass() != o.getClass() ) { return false; } - - GetterConstraintLocation that = (GetterConstraintLocation) o; - - if ( method != null ? !method.equals( that.method ) : that.method != null ) { - return false; - } - if ( !typeForValidatorResolution.equals( that.typeForValidatorResolution ) ) { + if ( !super.equals( o ) ) { return false; } - return true; + JavaBeanGetter that = (JavaBeanGetter) o; + + return this.name.equals( that.name ); } @Override public int hashCode() { - int result = method.hashCode(); - result = 31 * result + typeForValidatorResolution.hashCode(); + int result = super.hashCode(); + result = 31 * result + this.name.hashCode(); return result; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/package-info.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/package-info.java new file mode 100644 index 0000000000..410921fdeb --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/package-info.java @@ -0,0 +1,8 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ + +package org.hibernate.validator.internal.properties.javabean; diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/ExecutableHelper.java b/engine/src/main/java/org/hibernate/validator/internal/util/ExecutableHelper.java index 0ae6378a5a..cd5e1247a6 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/ExecutableHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/ExecutableHelper.java @@ -17,6 +17,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.util.classhierarchy.Filters; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -46,6 +47,10 @@ public ExecutableHelper(TypeResolutionHelper typeResolutionHelper) { this.typeResolver = typeResolutionHelper.getTypeResolver(); } + public boolean overrides(Callable subTypeMethod, Callable superTypeMethod) { + return subTypeMethod.overrides( this, superTypeMethod ); + } + /** * Checks, whether {@code subTypeMethod} overrides {@code superTypeMethod}. * diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index d0cba30970..41bd6883f3 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -48,10 +48,13 @@ import org.hibernate.validator.internal.engine.messageinterpolation.parser.MessageDescriptorFormatException; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.util.logging.formatter.ArrayOfClassesObjectFormatter; import org.hibernate.validator.internal.util.logging.formatter.ClassObjectFormatter; import org.hibernate.validator.internal.util.logging.formatter.CollectionOfClassesObjectFormatter; import org.hibernate.validator.internal.util.logging.formatter.CollectionOfObjectsToStringFormatter; +import org.hibernate.validator.internal.util.logging.formatter.ConstrainableFormatter; import org.hibernate.validator.internal.util.logging.formatter.DurationFormatter; import org.hibernate.validator.internal.util.logging.formatter.ExecutableFormatter; import org.hibernate.validator.internal.util.logging.formatter.ObjectArrayFormatter; @@ -248,14 +251,13 @@ GroupDefinitionException getUnableToExpandDefaultGroupListException(@FormatWith( GroupDefinitionException getWrongDefaultGroupSequenceProviderTypeException(@FormatWith(ClassObjectFormatter.class) Class beanClass); @Message(id = 56, value = "Method or constructor %1$s doesn't have a parameter with index %2$d.") - IllegalArgumentException getInvalidExecutableParameterIndexException(@FormatWith(ExecutableFormatter.class) Executable executable, int index); + IllegalArgumentException getInvalidExecutableParameterIndexException(@FormatWith(ConstrainableFormatter.class) Callable callable, int index); @Message(id = 59, value = "Unable to retrieve annotation parameter value.") ValidationException getUnableToRetrieveAnnotationParameterValueException(@Cause Exception e); - @Message(id = 62, - value = "Method or constructor %1$s has %2$s parameters, but the passed list of parameter meta data has a size of %3$s.") - IllegalArgumentException getInvalidLengthOfParameterMetaDataListException(@FormatWith(ExecutableFormatter.class) Executable executable, int nbParameters, int listSize); + @Message(id = 62, value = "Method or constructor %1$s has %2$s parameters, but the passed list of parameter meta data has a size of %3$s.") + IllegalArgumentException getInvalidLengthOfParameterMetaDataListException(@FormatWith(ConstrainableFormatter.class) Callable callable, int nbParameters, int listSize); @Message(id = 63, value = "Unable to instantiate %s.") ValidationException getUnableToInstantiateException(@FormatWith(ClassObjectFormatter.class) Class clazz, @Cause Exception e); @@ -461,11 +463,11 @@ ConstraintDeclarationException getMultipleGroupConversionsForSameSourceException @Message(id = 131, value = "A method return value must not be marked for cascaded validation more than once in a class hierarchy, but the following two methods are marked as such: %s, %s.") - ConstraintDeclarationException getMethodReturnValueMustNotBeMarkedMoreThanOnceForCascadedValidationException(@FormatWith(ExecutableFormatter.class) Executable executable1, @FormatWith(ExecutableFormatter.class) Executable executable2); + ConstraintDeclarationException getMethodReturnValueMustNotBeMarkedMoreThanOnceForCascadedValidationException(Callable callable1, Callable callable2); @Message(id = 132, value = "Void methods must not be constrained or marked for cascaded validation, but method %s is.") - ConstraintDeclarationException getVoidMethodsMustNotBeConstrainedException(@FormatWith(ExecutableFormatter.class) Executable executable); + ConstraintDeclarationException getVoidMethodsMustNotBeConstrainedException(@FormatWith(ConstrainableFormatter.class) Callable callable); @Message(id = 133, value = "%1$s does not contain a constructor with the parameter types %2$s.") ValidationException getBeanDoesNotContainConstructorException(@FormatWith(ClassObjectFormatter.class) Class beanClass, @@ -500,7 +502,7 @@ ConstraintDeclarationException getImplicitConstraintTargetInAmbiguousConfigurati @Message(id = 142, value = "Cross parameter constraint %1$s is illegally placed on a parameterless method or constructor '%2$s'.") ConstraintDeclarationException getCrossParameterConstraintOnMethodWithoutParametersException( - @FormatWith(ClassObjectFormatter.class) Class constraint, @FormatWith(ExecutableFormatter.class) Executable executable); + @FormatWith(ClassObjectFormatter.class) Class constraint, @FormatWith(ConstrainableFormatter.class) Constrainable executable); @Message(id = 143, value = "Cross parameter constraint %1$s is illegally placed on class level.") @@ -509,7 +511,7 @@ ConstraintDeclarationException getCrossParameterConstraintOnMethodWithoutParamet @Message(id = 144, value = "Cross parameter constraint %1$s is illegally placed on field '%2$s'.") ConstraintDeclarationException getCrossParameterConstraintOnFieldException(@FormatWith(ClassObjectFormatter.class) Class constraint, - Member field); + @FormatWith(ConstrainableFormatter.class) Constrainable field); @Message(id = 146, value = "No parameter nodes may be added since path %s doesn't refer to a cross-parameter constraint.") @@ -535,11 +537,11 @@ UnexpectedTypeException getMultipleValidatorsForSameTypeException(@FormatWith(Cl @Message(id = 151, value = "A method overriding another method must not redefine the parameter constraint configuration, but method %2$s redefines the configuration of %1$s.") - ConstraintDeclarationException getParameterConfigurationAlteredInSubTypeException(@FormatWith(ExecutableFormatter.class) Executable superMethod, @FormatWith(ExecutableFormatter.class) Executable subMethod); + ConstraintDeclarationException getParameterConfigurationAlteredInSubTypeException(@FormatWith(ConstrainableFormatter.class) Callable superMethod, @FormatWith(ConstrainableFormatter.class) Callable subMethod); @Message(id = 152, value = "Two methods defined in parallel types must not declare parameter constraints, if they are overridden by the same method, but methods %s and %s both define parameter constraints.") - ConstraintDeclarationException getParameterConstraintsDefinedInMethodsFromParallelTypesException(@FormatWith(ExecutableFormatter.class) Executable method1, @FormatWith(ExecutableFormatter.class) Executable method2); + ConstraintDeclarationException getParameterConstraintsDefinedInMethodsFromParallelTypesException(@FormatWith(ConstrainableFormatter.class) Callable method1, @FormatWith(ConstrainableFormatter.class) Callable method2); @Message(id = 153, value = "The constraint %1$s used ConstraintTarget#%2$s but is not specified on a method or constructor.") @@ -581,7 +583,7 @@ ConstraintDefinitionException getValidatorForCrossParameterConstraintMustEitherV @Message(id = 161, value = "Two methods defined in parallel types must not define group conversions for a cascaded method return value, if they are overridden by the same method, but methods %s and %s both define parameter constraints.") - ConstraintDeclarationException getMethodsFromParallelTypesMustNotDefineGroupConversionsForCascadedReturnValueException(@FormatWith(ExecutableFormatter.class) Executable method1, @FormatWith(ExecutableFormatter.class) Executable method2); + ConstraintDeclarationException getMethodsFromParallelTypesMustNotDefineGroupConversionsForCascadedReturnValueException(@FormatWith(ConstrainableFormatter.class) Callable method1, @FormatWith(ConstrainableFormatter.class) Callable method2); @Message(id = 162, value = "The validated type %1$s does not specify the constructor/method: %2$s") @@ -625,15 +627,15 @@ ConstraintDefinitionException getValidatorForCrossParameterConstraintMustEitherV @Message(id = 173, value = "Method %2$s of type %1$s is configured more than once via the programmatic constraint declaration API.") - ValidationException getMethodHasAlreadyBeConfiguredViaProgrammaticApiException(@FormatWith(ClassObjectFormatter.class) Class beanClass, String method); + ValidationException getMethodHasAlreadyBeenConfiguredViaProgrammaticApiException(@FormatWith(ClassObjectFormatter.class) Class beanClass, String method); @Message(id = 174, value = "Parameter %3$s of method or constructor %2$s of type %1$s is configured more than once via the programmatic constraint declaration API.") - ValidationException getParameterHasAlreadyBeConfiguredViaProgrammaticApiException(@FormatWith(ClassObjectFormatter.class) Class beanClass, @FormatWith(ExecutableFormatter.class) Executable executable, int parameterIndex); + ValidationException getParameterHasAlreadyBeConfiguredViaProgrammaticApiException(@FormatWith(ClassObjectFormatter.class) Class beanClass, @FormatWith(ConstrainableFormatter.class) Callable callable, int parameterIndex); @Message(id = 175, value = "The return value of method or constructor %2$s of type %1$s is configured more than once via the programmatic constraint declaration API.") - ValidationException getReturnValueHasAlreadyBeConfiguredViaProgrammaticApiException(@FormatWith(ClassObjectFormatter.class) Class beanClass, @FormatWith(ExecutableFormatter.class) Executable executable); + ValidationException getReturnValueHasAlreadyBeConfiguredViaProgrammaticApiException(@FormatWith(ClassObjectFormatter.class) Class beanClass, @FormatWith(ConstrainableFormatter.class) Callable callable); @Message(id = 176, value = "Constructor %2$s of type %1$s is configured more than once via the programmatic constraint declaration API.") @@ -641,7 +643,7 @@ ConstraintDefinitionException getValidatorForCrossParameterConstraintMustEitherV @Message(id = 177, value = "Cross-parameter constraints for the method or constructor %2$s of type %1$s are declared more than once via the programmatic constraint declaration API.") - ValidationException getCrossParameterElementHasAlreadyBeConfiguredViaProgrammaticApiException(@FormatWith(ClassObjectFormatter.class) Class beanClass, @FormatWith(ExecutableFormatter.class) Executable executable); + ValidationException getCrossParameterElementHasAlreadyBeConfiguredViaProgrammaticApiException(@FormatWith(ClassObjectFormatter.class) Class beanClass, @FormatWith(ConstrainableFormatter.class) Callable callable); @Message(id = 178, value = "Multiplier cannot be negative: %d.") IllegalArgumentException getMultiplierCannotBeNegativeException(int multiplier); @@ -714,7 +716,7 @@ ConstraintDeclarationException getInconsistentValueUnwrappingConfigurationBetwee ValueExtractorDefinitionException getValueExtractorDeclaresExtractedValueMultipleTimesException(@FormatWith(ClassObjectFormatter.class) Class extractorType); @Message(id = 205, value = "Invalid unwrapping configuration for constraint %2$s on %1$s. You can only define one of 'Unwrapping.Skip' or 'Unwrapping.Unwrap'.") - ConstraintDeclarationException getInvalidUnwrappingConfigurationForConstraintException(Member member, @FormatWith(ClassObjectFormatter.class) Class constraint); + ConstraintDeclarationException getInvalidUnwrappingConfigurationForConstraintException(@FormatWith(ConstrainableFormatter.class) Constrainable constrainable, @FormatWith(ClassObjectFormatter.class) Class constraint); @Message(id = 206, value = "Unable to instantiate value extractor class %s.") ValidationException getUnableToInstantiateValueExtractorClassException(String valueExtractorClassName, @Cause ValidationException e); diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/formatter/ConstrainableFormatter.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/formatter/ConstrainableFormatter.java new file mode 100644 index 0000000000..d5f8ea6f1a --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/formatter/ConstrainableFormatter.java @@ -0,0 +1,39 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.util.logging.formatter; + +import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.properties.Constrainable; +import org.hibernate.validator.internal.util.ExecutableHelper; + +/** + * Used with JBoss Logging to display executables in log messages. + * + * @author Marko Bekhta + */ +public class ConstrainableFormatter { + + private final String stringRepresentation; + + public ConstrainableFormatter(Constrainable constrainable) { + String name = constrainable.getName(); + if ( constrainable instanceof Callable ) { + name = constrainable.getDeclaringClass().getSimpleName() + "#" + name; + Class[] parameterTypes = ( (Callable) constrainable ).getParameterTypes(); + + this.stringRepresentation = ExecutableHelper.getExecutableAsString( name, parameterTypes ); + } + else { + this.stringRepresentation = name; + } + } + + @Override + public String toString() { + return stringRepresentation; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java index d29312b7b8..1807e03322 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java @@ -26,6 +26,7 @@ import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; +import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; @@ -84,6 +85,7 @@ ConstrainedExecutable build(Class beanClass, List> alreadyProc parameterTypes ); } + JavaBeanExecutable executable = JavaBeanExecutable.of( constructor ); if ( alreadyProcessedConstructors.contains( constructor ) ) { throw LOG.getConstructorIsDefinedTwiceInMappingXmlForBeanException( constructor, beanClass ); @@ -95,7 +97,7 @@ ConstrainedExecutable build(Class beanClass, List> alreadyProc // ignore annotations if ( ignoreAnnotations.isPresent() ) { annotationProcessingOptions.ignoreConstraintAnnotationsOnMember( - constructor, + executable, ignoreAnnotations.get() ); } @@ -103,21 +105,21 @@ ConstrainedExecutable build(Class beanClass, List> alreadyProc List constrainedParameters = CollectionHelper.newArrayList( constrainedParameterStaxBuilders.size() ); for ( int index = 0; index < constrainedParameterStaxBuilders.size(); index++ ) { ConstrainedParameterStaxBuilder builder = constrainedParameterStaxBuilders.get( index ); - constrainedParameters.add( builder.build( constructor, index ) ); + constrainedParameters.add( builder.build( executable, index ) ); } Set> crossParameterConstraints = getCrossParameterStaxBuilder() - .map( builder -> builder.build( constructor ) ).orElse( Collections.emptySet() ); + .map( builder -> builder.build( executable ) ).orElse( Collections.emptySet() ); // parse the return value Set> returnValueConstraints = new HashSet<>(); Set> returnValueTypeArgumentConstraints = new HashSet<>(); - CascadingMetaDataBuilder cascadingMetaDataBuilder = getReturnValueStaxBuilder().map( builder -> builder.build( constructor, returnValueConstraints, returnValueTypeArgumentConstraints ) ) + CascadingMetaDataBuilder cascadingMetaDataBuilder = getReturnValueStaxBuilder().map( builder -> builder.build( executable, returnValueConstraints, returnValueTypeArgumentConstraints ) ) .orElse( CascadingMetaDataBuilder.nonCascading() ); return new ConstrainedExecutable( ConfigurationSource.XML, - constructor, + executable, constrainedParameters, crossParameterConstraints, returnValueConstraints, diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java index 8b2a8a97be..5244d464e7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java @@ -24,6 +24,7 @@ import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; +import org.hibernate.validator.internal.properties.javabean.JavaBeanField; import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; @@ -69,17 +70,19 @@ ConstrainedField build(Class beanClass, List alreadyProcessedFieldNam alreadyProcessedFieldNames.add( mainAttributeValue ); } Field field = findField( beanClass, mainAttributeValue ); - ConstraintLocation constraintLocation = ConstraintLocation.forField( field ); + JavaBeanField property = new JavaBeanField( field ); + ConstraintLocation constraintLocation = ConstraintLocation.forProperty( property ); + Set> metaConstraints = constraintTypeStaxBuilders.stream() .map( builder -> builder.build( constraintLocation, java.lang.annotation.ElementType.FIELD, null ) ) .collect( Collectors.toSet() ); ContainerElementTypeConfiguration containerElementTypeConfiguration = getContainerElementTypeConfiguration( - ReflectionHelper.typeOf( field ), constraintLocation ); + property.getType(), constraintLocation ); ConstrainedField constrainedField = new ConstrainedField( ConfigurationSource.XML, - field, + property, metaConstraints, containerElementTypeConfiguration.getMetaConstraints(), getCascadingMetaData( containerElementTypeConfiguration.getTypeParametersCascadingMetaData(), ReflectionHelper.typeOf( field ) ) @@ -88,7 +91,7 @@ ConstrainedField build(Class beanClass, List alreadyProcessedFieldNam // ignore annotations if ( ignoreAnnotations.isPresent() ) { annotationProcessingOptions.ignoreConstraintAnnotationsOnMember( - field, + property, ignoreAnnotations.get() ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java index ba1b607ffd..b809befab9 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java @@ -26,6 +26,9 @@ import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; +import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; @@ -71,7 +74,8 @@ ConstrainedExecutable build(Class beanClass, List alreadyProcessedGet alreadyProcessedGetterNames.add( mainAttributeValue ); } Method getter = findGetter( beanClass, mainAttributeValue ); - ConstraintLocation constraintLocation = ConstraintLocation.forGetter( beanClass, getter ); + Property property = new JavaBeanGetter( beanClass, getter ); + ConstraintLocation constraintLocation = ConstraintLocation.forProperty( property ); Set> metaConstraints = constraintTypeStaxBuilders.stream() .map( builder -> builder.build( constraintLocation, java.lang.annotation.ElementType.METHOD, null ) ) @@ -82,7 +86,7 @@ ConstrainedExecutable build(Class beanClass, List alreadyProcessedGet ConstrainedExecutable constrainedGetter = new ConstrainedExecutable( ConfigurationSource.XML, - getter, + property.as( Callable.class ), Collections.emptyList(), Collections.>emptySet(), metaConstraints, @@ -93,7 +97,7 @@ ConstrainedExecutable build(Class beanClass, List alreadyProcessedGet // ignore annotations if ( ignoreAnnotations.isPresent() ) { annotationProcessingOptions.ignoreConstraintAnnotationsOnMember( - getter, + property, ignoreAnnotations.get() ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java index ede789a730..f1876750c4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java @@ -26,6 +26,7 @@ import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; +import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; @@ -96,11 +97,12 @@ ConstrainedExecutable build(Class beanClass, List alreadyProcessedMet else { alreadyProcessedMethods.add( method ); } + JavaBeanExecutable executable = JavaBeanExecutable.of( method ); // ignore annotations if ( ignoreAnnotations.isPresent() ) { annotationProcessingOptions.ignoreConstraintAnnotationsOnMember( - method, + executable, ignoreAnnotations.get() ); } @@ -108,21 +110,21 @@ ConstrainedExecutable build(Class beanClass, List alreadyProcessedMet List constrainedParameters = CollectionHelper.newArrayList( constrainedParameterStaxBuilders.size() ); for ( int index = 0; index < constrainedParameterStaxBuilders.size(); index++ ) { ConstrainedParameterStaxBuilder builder = constrainedParameterStaxBuilders.get( index ); - constrainedParameters.add( builder.build( method, index ) ); + constrainedParameters.add( builder.build( executable, index ) ); } Set> crossParameterConstraints = getCrossParameterStaxBuilder() - .map( builder -> builder.build( method ) ).orElse( Collections.emptySet() ); + .map( builder -> builder.build( executable ) ).orElse( Collections.emptySet() ); // parse the return value Set> returnValueConstraints = new HashSet<>(); Set> returnValueTypeArgumentConstraints = new HashSet<>(); - CascadingMetaDataBuilder cascadingMetaDataBuilder = getReturnValueStaxBuilder().map( builder -> builder.build( method, returnValueConstraints, returnValueTypeArgumentConstraints ) ) + CascadingMetaDataBuilder cascadingMetaDataBuilder = getReturnValueStaxBuilder().map( builder -> builder.build( executable, returnValueConstraints, returnValueTypeArgumentConstraints ) ) .orElse( CascadingMetaDataBuilder.nonCascading() ); return new ConstrainedExecutable( ConfigurationSource.XML, - method, + executable, constrainedParameters, crossParameterConstraints, returnValueConstraints, diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java index cf5a77d690..5344231f1c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java @@ -7,7 +7,6 @@ package org.hibernate.validator.internal.xml.mapping; import java.lang.invoke.MethodHandles; -import java.lang.reflect.Executable; import java.lang.reflect.Type; import java.util.Optional; import java.util.Set; @@ -23,7 +22,7 @@ import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; -import org.hibernate.validator.internal.util.ReflectionHelper; +import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -68,10 +67,10 @@ public Class getParameterType(Class beanClass) { } } - ConstrainedParameter build(Executable executable, int index) { + ConstrainedParameter build(Callable callable, int index) { - ConstraintLocation constraintLocation = ConstraintLocation.forParameter( executable, index ); - Type type = ReflectionHelper.typeOf( executable, index ); + ConstraintLocation constraintLocation = ConstraintLocation.forParameter( callable, index ); + Type type = callable.getTypeOfParameter( index ); Set> metaConstraints = constraintTypeStaxBuilders.stream() .map( builder -> builder.build( constraintLocation, java.lang.annotation.ElementType.PARAMETER, null ) ) @@ -82,7 +81,7 @@ ConstrainedParameter build(Executable executable, int index) { // ignore annotations if ( ignoreAnnotations.isPresent() ) { annotationProcessingOptions.ignoreConstraintAnnotationsOnParameter( - executable, + callable, index, ignoreAnnotations.get() ); @@ -90,7 +89,7 @@ ConstrainedParameter build(Executable executable, int index) { ConstrainedParameter constrainedParameter = new ConstrainedParameter( ConfigurationSource.XML, - executable, + callable, type, index, metaConstraints, diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintTypeStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintTypeStaxBuilder.java index 862a1226ad..3292210ac0 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintTypeStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintTypeStaxBuilder.java @@ -148,8 +148,8 @@ MetaConstraint build(ConstraintLocation constraintLoca // we set initially ConstraintOrigin.DEFINED_LOCALLY for all xml configured constraints // later we will make copies of this constraint descriptor when needed and adjust the ConstraintOrigin - ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl( - constraintHelper, constraintLocation.getMember(), annotationDescriptor, type, constraintType + ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl<>( + constraintHelper, constraintLocation.getConstrainable(), annotationDescriptor, type, constraintType ); return MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor, constraintLocation ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java index 30397e1009..ce40f9625f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java @@ -6,7 +6,6 @@ */ package org.hibernate.validator.internal.xml.mapping; -import java.lang.reflect.Executable; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -24,6 +23,7 @@ import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.xml.AbstractStaxBuilder; @@ -83,9 +83,9 @@ private ConstraintTypeStaxBuilder getNewConstraintTypeStaxBuilder() { return new ConstraintTypeStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder ); } - Set> build(Executable executable) { + Set> build(Callable callable) { - ConstraintLocation constraintLocation = ConstraintLocation.forCrossParameter( executable ); + ConstraintLocation constraintLocation = ConstraintLocation.forCrossParameter( callable ); Set> crossParameterConstraints = constraintTypeStaxBuilders.stream() .map( builder -> builder.build( constraintLocation, java.lang.annotation.ElementType.METHOD, ConstraintType.CROSS_PARAMETER ) ) @@ -94,7 +94,7 @@ Set> build(Executable executable) { // ignore annotations if ( ignoreAnnotations.isPresent() ) { annotationProcessingOptions.ignoreConstraintAnnotationsForCrossParameterConstraint( - executable, + callable, ignoreAnnotations.get() ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java index 85cae903e2..b9458a5fdf 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java @@ -6,7 +6,7 @@ */ package org.hibernate.validator.internal.xml.mapping; -import java.lang.reflect.Executable; +import java.lang.annotation.ElementType; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -20,8 +20,7 @@ import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.util.ExecutableHelper; -import org.hibernate.validator.internal.util.ReflectionHelper; +import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.xml.mapping.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; @@ -51,27 +50,27 @@ protected String getAcceptableQName() { } CascadingMetaDataBuilder build( - Executable executable, + Callable callable, Set> returnValueConstraints, Set> returnValueTypeArgumentConstraints) { - ConstraintLocation constraintLocation = ConstraintLocation.forReturnValue( executable ); + ConstraintLocation constraintLocation = ConstraintLocation.forReturnValue( callable ); returnValueConstraints.addAll( constraintTypeStaxBuilders.stream() - .map( builder -> builder.build( constraintLocation, ExecutableHelper.getElementType( executable ), ConstraintDescriptorImpl.ConstraintType.GENERIC ) ) + .map( builder -> builder.build( constraintLocation, callable.isConstructor() ? ElementType.CONSTRUCTOR : ElementType.METHOD, ConstraintDescriptorImpl.ConstraintType.GENERIC ) ) .collect( Collectors.toSet() ) ); - ContainerElementTypeConfiguration containerElementTypeConfiguration = getContainerElementTypeConfiguration( ReflectionHelper.typeOf( executable ), constraintLocation ); + ContainerElementTypeConfiguration containerElementTypeConfiguration = getContainerElementTypeConfiguration( callable.getType(), constraintLocation ); returnValueTypeArgumentConstraints.addAll( containerElementTypeConfiguration.getMetaConstraints() ); // ignore annotations if ( ignoreAnnotations.isPresent() ) { annotationProcessingOptions.ignoreConstraintAnnotationsForReturnValue( - executable, + callable, ignoreAnnotations.get() ); } - return getCascadingMetaData( containerElementTypeConfiguration.getTypeParametersCascadingMetaData(), ReflectionHelper.typeOf( executable ) ); + return getCascadingMetaData( containerElementTypeConfiguration.getTypeParametersCascadingMetaData(), callable.getType() ); } } diff --git a/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java b/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java index d0fc924caa..ae7fd8a3f5 100644 --- a/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java @@ -556,7 +556,7 @@ private BeanConfiguration getBeanConfiguration(Class type) { private ConstrainedField getConstrainedField(BeanConfiguration beanConfiguration, String fieldName) { for ( ConstrainedElement constrainedElement : beanConfiguration.getConstrainedElements() ) { if ( constrainedElement.getKind() == ConstrainedElementKind.FIELD && - ( (ConstrainedField) constrainedElement ).getField().getName().equals( fieldName ) ) { + ( (ConstrainedField) constrainedElement ).getProperty().getPropertyName().equals( fieldName ) ) { return (ConstrainedField) constrainedElement; } } @@ -567,7 +567,7 @@ private ConstrainedField getConstrainedField(BeanConfiguration beanConfigurat private ConstrainedExecutable getConstrainedExecutable(BeanConfiguration beanConfiguration, String executableName) { for ( ConstrainedElement constrainedElement : beanConfiguration.getConstrainedElements() ) { if ( constrainedElement.getKind() == ConstrainedElementKind.METHOD && - ( (ConstrainedExecutable) constrainedElement ).getExecutable().getName().equals( executableName ) ) { + ( (ConstrainedExecutable) constrainedElement ).getCallable().getName().equals( executableName ) ) { return (ConstrainedExecutable) constrainedElement; } } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/failfast/FailFastTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/failfast/FailFastTest.java index 1098e29f1f..29721e713f 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/failfast/FailFastTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/failfast/FailFastTest.java @@ -162,8 +162,9 @@ public void testFailFastMethodValidationSetOnValidatorFactory() { fail(); } catch (ConstraintViolationException e) { - assertThat( e.getConstraintViolations() ).containsOnlyViolations( - violationOf( NotBlank.class ) + assertThat( e.getConstraintViolations() ).containsOneOfViolations( + violationOf( NotBlank.class ), + violationOf( Min.class ) ); } } @@ -212,8 +213,9 @@ public void testFailFastMethodValidationSetWithProperty() { fail(); } catch (ConstraintViolationException e) { - assertThat( e.getConstraintViolations() ).containsOnlyViolations( - violationOf( NotBlank.class ) + assertThat( e.getConstraintViolations() ).containsOneOfViolations( + violationOf( NotBlank.class ), + violationOf( Min.class ) ); } } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java index 29cfcc5550..16fc4e3062 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java @@ -20,6 +20,7 @@ import org.hibernate.validator.internal.metadata.core.MetaConstraints; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.testutil.TestForIssue; @@ -49,14 +50,14 @@ public void setUp() throws Exception { @TestForIssue(jiraKey = "HV-930") public void two_meta_constraints_for_the_same_constraint_should_be_equal() throws Exception { ConstraintDescriptorImpl constraintDescriptor1 = new ConstraintDescriptorImpl<>( - constraintHelper, barMethod, constraintAnnotationDescriptor, METHOD + constraintHelper, JavaBeanExecutable.of( barMethod ), constraintAnnotationDescriptor, METHOD ); ConstraintLocation location1 = ConstraintLocation.forClass( Foo.class ); MetaConstraint metaConstraint1 = MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor1, location1 ); ConstraintDescriptorImpl constraintDescriptor2 = new ConstraintDescriptorImpl<>( - constraintHelper, barMethod, constraintAnnotationDescriptor, METHOD + constraintHelper, JavaBeanExecutable.of( barMethod ), constraintAnnotationDescriptor, METHOD ); ConstraintLocation location2 = ConstraintLocation.forClass( Foo.class ); MetaConstraint metaConstraint2 = MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor2, location2 ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/location/ConstraintLocationTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/location/ConstraintLocationTest.java index 8e424bbd4a..acf7934c4b 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/location/ConstraintLocationTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/location/ConstraintLocationTest.java @@ -11,6 +11,7 @@ import java.lang.reflect.Method; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; import org.hibernate.validator.testutil.TestForIssue; import org.testng.annotations.Test; @@ -32,8 +33,8 @@ public void two_constraint_locations_for_the_same_type_should_be_equal() { @TestForIssue(jiraKey = "HV-930") public void two_constraint_locations_for_the_same_member_should_be_equal() throws Exception { Method getter = Foo.class.getMethod( "getBar" ); - ConstraintLocation location1 = ConstraintLocation.forGetter( getter ); - ConstraintLocation location2 = ConstraintLocation.forGetter( getter ); + ConstraintLocation location1 = ConstraintLocation.forProperty( new JavaBeanGetter( getter ) ); + ConstraintLocation location2 = ConstraintLocation.forProperty( new JavaBeanGetter( getter ) ); assertEquals( location1, location2, "Two constraint locations for the same type should be equal" ); } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java index 9953a487f8..95d3561fd9 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java @@ -40,6 +40,7 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; import org.hibernate.validator.internal.metadata.raw.ConstrainedType; +import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.testutil.TestForIssue; import org.joda.time.DateMidnight; @@ -101,11 +102,13 @@ public void testGetCrossParameterMetaData() throws Exception { assertThat( createEvent.getConstraints() ).as( "No return value constraints expected" ).isEmpty(); assertThat( createEvent.getCrossParameterConstraints() ).hasSize( 1 ); - assertThat( createEvent.getExecutable() ).isEqualTo( - Calendar.class.getMethod( - "createEvent", - DateMidnight.class, - DateMidnight.class + assertThat( createEvent.getCallable() ).isEqualTo( + JavaBeanExecutable.of( + Calendar.class.getMethod( + "createEvent", + DateMidnight.class, + DateMidnight.class + ) ) ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTestBase.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTestBase.java index fca67eae25..7a9e68def8 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTestBase.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTestBase.java @@ -16,6 +16,9 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; import org.hibernate.validator.internal.metadata.raw.ConstrainedType; +import org.hibernate.validator.internal.properties.Constrainable; +import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; +import org.hibernate.validator.internal.properties.javabean.JavaBeanField; /** * @author Gunnar Morling @@ -59,14 +62,22 @@ protected ConstrainedType findConstrainedType(BeanConfiguration beanConfi protected ConstrainedElement findConstrainedElement(BeanConfiguration beanConfiguration, Member member) { + Constrainable constrainable; + if ( member instanceof Field ) { + constrainable = new JavaBeanField( (Field) member ); + } + else { + constrainable = JavaBeanExecutable.of( (Executable) member ); + } + for ( ConstrainedElement constrainedElement : beanConfiguration.getConstrainedElements() ) { if ( member instanceof Executable && constrainedElement instanceof ConstrainedExecutable ) { - if ( member.equals( ( (ConstrainedExecutable) constrainedElement ).getExecutable() ) ) { + if ( constrainable.equals( ( (ConstrainedExecutable) constrainedElement ).getCallable() ) ) { return constrainedElement; } } - else if ( member instanceof Field && constrainedElement instanceof ConstrainedField ) { - if ( member.equals( ( (ConstrainedField) constrainedElement ).getField() ) ) { + else if ( constrainedElement instanceof ConstrainedField ) { + if ( constrainable.equals( ( (ConstrainedField) constrainedElement ).getProperty() ) ) { return constrainedElement; } } diff --git a/test-utils/src/main/java/org/hibernate/validator/testutil/ConstraintViolationAssert.java b/test-utils/src/main/java/org/hibernate/validator/testutil/ConstraintViolationAssert.java index 1316865371..cf234f1bc7 100644 --- a/test-utils/src/main/java/org/hibernate/validator/testutil/ConstraintViolationAssert.java +++ b/test-utils/src/main/java/org/hibernate/validator/testutil/ConstraintViolationAssert.java @@ -263,6 +263,21 @@ public ConstraintViolationSetAssert describedAs(String description, Object... ar public void containsOnlyViolations(ViolationExpectation... expectedViolations) { isNotNull(); + List actualViolations = getActualViolationExpectations( expectedViolations ); + + Assertions.assertThat( actualViolations ).containsExactlyInAnyOrder( expectedViolations ); + } + + public void containsOneOfViolations(ViolationExpectation... expectedViolations) { + isNotNull(); + + List actualViolations = getActualViolationExpectations( expectedViolations ); + + Assertions.assertThat( actualViolations ).hasSize( 1 ); + Assertions.assertThat( expectedViolations ).contains( actualViolations.get( 0 ) ); + } + + private List getActualViolationExpectations(ViolationExpectation[] expectedViolations) { List actualViolations = new ArrayList<>(); ViolationExpectationPropertiesToTest referencePropertiesToTest; @@ -284,7 +299,7 @@ public void containsOnlyViolations(ViolationExpectation... expectedViolations) { actualViolations.add( new ViolationExpectation( violation, referencePropertiesToTest ) ); } - Assertions.assertThat( actualViolations ).containsExactlyInAnyOrder( expectedViolations ); + return actualViolations; } public void containsOnlyPaths(PathExpectation... paths) { From b44547d2ce315c7a7eb2e1c4150a7d9185d82396 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Thu, 7 Jun 2018 12:13:35 +0200 Subject: [PATCH 052/393] HV-1623 Reintroduce field and getter constraint locations --- .../cfg/context/ConfiguredConstraint.java | 5 ++++- .../PropertyConstraintMappingContextImpl.java | 5 ++++- .../metadata/aggregated/PropertyMetaData.java | 9 ++++---- .../metadata/location/ConstraintLocation.java | 11 +++++++--- .../FieldPropertyConstraintLocation.java | 21 ++++++++++++++++++ .../GetterPropertyConstraintLocation.java | 21 ++++++++++++++++++ .../location/PropertyConstraintLocation.java | 15 ++++++------- .../provider/AnnotationMetaDataProvider.java | 22 +++++++++---------- .../mapping/ConstrainedFieldStaxBuilder.java | 10 ++++----- .../mapping/ConstrainedGetterStaxBuilder.java | 10 ++++----- .../location/ConstraintLocationTest.java | 4 ++-- 11 files changed, 92 insertions(+), 41 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldPropertyConstraintLocation.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterPropertyConstraintLocation.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java index 3f47510fca..c2f07e008a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java @@ -23,6 +23,7 @@ import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; +import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; import org.hibernate.validator.internal.util.annotation.AnnotationDescriptor; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.internal.util.logging.Log; @@ -59,7 +60,9 @@ static ConfiguredConstraint forType(ConstraintDef ConfiguredConstraint forProperty(ConstraintDef constraint, Property property) { return new ConfiguredConstraint<>( constraint, - ConstraintLocation.forProperty( property ), + property instanceof JavaBeanField + ? ConstraintLocation.forField( property.as( JavaBeanField.class ) ) + : ConstraintLocation.forGetter( property.as( JavaBeanGetter.class ) ), property instanceof JavaBeanField ? ElementType.FIELD : ElementType.METHOD ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java index 95e51deec5..10fe537c9f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java @@ -24,6 +24,7 @@ import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; +import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; import org.hibernate.validator.internal.util.TypeResolutionHelper; /** @@ -47,7 +48,9 @@ final class PropertyConstraintMappingContextImpl super( typeContext.getConstraintMapping(), property.getType() ); this.typeContext = typeContext; this.property = property; - this.location = ConstraintLocation.forProperty( property ); + this.location = property instanceof JavaBeanField + ? ConstraintLocation.forField( property.as( JavaBeanField.class ) ) + : ConstraintLocation.forGetter( property.as( JavaBeanGetter.class ) ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java index 7282c947f7..9568a38dbd 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java @@ -31,7 +31,7 @@ import org.hibernate.validator.internal.metadata.descriptor.PropertyDescriptorImpl; import org.hibernate.validator.internal.metadata.facets.Cascadable; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.metadata.location.PropertyConstraintLocation; +import org.hibernate.validator.internal.metadata.location.GetterPropertyConstraintLocation; import org.hibernate.validator.internal.metadata.location.TypeArgumentConstraintLocation; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; @@ -41,6 +41,7 @@ import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethod; @@ -243,7 +244,7 @@ protected Set> adaptConstraints(ConstrainedElement constrained return constraints; } - ConstraintLocation getterConstraintLocation = ConstraintLocation.forProperty( ( (ConstrainedExecutable) constrainedElement ).getCallable().as( Property.class ) ); + ConstraintLocation getterConstraintLocation = ConstraintLocation.forGetter( ( (ConstrainedExecutable) constrainedElement ).getCallable().as( JavaBeanGetter.class ) ); // convert return value locations into getter locations for usage within this meta-data return constraints.stream() @@ -257,7 +258,7 @@ private MetaConstraint withGetterLocation(ConstraintLocation getterConstraint // fast track if it's a regular constraint if ( !(constraint.getLocation() instanceof TypeArgumentConstraintLocation) ) { // Change the constraint location to a GetterConstraintLocation if it is not already one - if ( constraint.getLocation() instanceof PropertyConstraintLocation ) { + if ( constraint.getLocation() instanceof GetterPropertyConstraintLocation ) { converted = constraint.getLocation(); } else { @@ -284,7 +285,7 @@ private MetaConstraint withGetterLocation(ConstraintLocation getterConstraint for ( ConstraintLocation location : locationStack ) { if ( !(location instanceof TypeArgumentConstraintLocation) ) { // Change the constraint location to a GetterConstraintLocation if it is not already one - if ( location instanceof PropertyConstraintLocation ) { + if ( location instanceof GetterPropertyConstraintLocation ) { converted = location; } else { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java index a5626998c5..54aafdbd5a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java @@ -12,7 +12,8 @@ import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Constrainable; -import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.javabean.JavaBeanField; +import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; /** @@ -38,8 +39,12 @@ static ConstraintLocation forClass(Class declaringClass) { return new BeanConstraintLocation( declaringClass ); } - static ConstraintLocation forProperty(Property property) { - return new PropertyConstraintLocation( property ); + static ConstraintLocation forField(JavaBeanField field) { + return new FieldPropertyConstraintLocation( field ); + } + + static ConstraintLocation forGetter(JavaBeanGetter getter) { + return new GetterPropertyConstraintLocation( getter ); } static ConstraintLocation forTypeArgument(ConstraintLocation delegate, TypeVariable typeParameter, Type typeOfAnnotatedElement) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldPropertyConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldPropertyConstraintLocation.java new file mode 100644 index 0000000000..2cdb6840cc --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldPropertyConstraintLocation.java @@ -0,0 +1,21 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.metadata.location; + +import org.hibernate.validator.internal.properties.javabean.JavaBeanField; + +/** + * Field property constraint location. + * + * @author Marko Bekhta + */ +public class FieldPropertyConstraintLocation extends PropertyConstraintLocation { + + FieldPropertyConstraintLocation(JavaBeanField javaBeanGetter) { + super( javaBeanGetter ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterPropertyConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterPropertyConstraintLocation.java new file mode 100644 index 0000000000..2d450be8bf --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterPropertyConstraintLocation.java @@ -0,0 +1,21 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.metadata.location; + +import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; + +/** + * Getter property constraint location. + * + * @author Marko Bekhta + */ +public class GetterPropertyConstraintLocation extends PropertyConstraintLocation { + + GetterPropertyConstraintLocation(JavaBeanGetter javaBeanGetter) { + super( javaBeanGetter ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java index 78b9ccc4b0..b64181c185 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java @@ -9,23 +9,22 @@ import java.lang.reflect.Type; import org.hibernate.validator.internal.engine.path.PathImpl; -import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; /** - * Property constraint location. + * An abstract property constraint location. * * @author Marko Bekhta */ -public class PropertyConstraintLocation implements ConstraintLocation { +public abstract class PropertyConstraintLocation implements ConstraintLocation { /** * The member the constraint was defined on. */ - private final Property property; + private final T property; - PropertyConstraintLocation(Property property) { + PropertyConstraintLocation(T property) { this.property = property; } @@ -35,7 +34,7 @@ public Class getDeclaringClass() { } @Override - public Constrainable getConstrainable() { + public T getConstrainable() { return property; } @@ -60,7 +59,7 @@ public Object getValue(Object parent) { @Override public String toString() { - return "PropertyConstraintLocation [property=" + property + "]"; + return getClass().getSimpleName() + " [property=" + property + "]"; } @Override @@ -72,7 +71,7 @@ public boolean equals(Object o) { return false; } - PropertyConstraintLocation that = (PropertyConstraintLocation) o; + PropertyConstraintLocation that = (PropertyConstraintLocation) o; if ( !property.equals( that.property ) ) { return false; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java index 12aeaa9e06..9f36621a08 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java @@ -218,46 +218,46 @@ private Set getFieldMetaData(Class beanClass) { Set propertyMetaData = newHashSet(); for ( Field field : run( GetDeclaredFields.action( beanClass ) ) ) { - Property property = new JavaBeanField( field ); + JavaBeanField javaBeanField = new JavaBeanField( field ); // HV-172 if ( Modifier.isStatic( field.getModifiers() ) || - annotationProcessingOptions.areMemberConstraintsIgnoredFor( property ) || + annotationProcessingOptions.areMemberConstraintsIgnoredFor( javaBeanField ) || field.isSynthetic() ) { continue; } - propertyMetaData.add( findPropertyMetaData( field, property ) ); + propertyMetaData.add( findPropertyMetaData( field, javaBeanField ) ); } return propertyMetaData; } - private ConstrainedField findPropertyMetaData(Field field, Property property) { + private ConstrainedField findPropertyMetaData(Field field, JavaBeanField javaBeanField) { Set> constraints = convertToMetaConstraints( - findConstraints( field, ElementType.FIELD, property ), - property + findConstraints( field, ElementType.FIELD, javaBeanField ), + javaBeanField ); CascadingMetaDataBuilder cascadingMetaDataBuilder = findCascadingMetaData( field ); - Set> typeArgumentsConstraints = findTypeAnnotationConstraints( field, property ); + Set> typeArgumentsConstraints = findTypeAnnotationConstraints( field, javaBeanField ); return new ConstrainedField( ConfigurationSource.ANNOTATION, - property, + javaBeanField, constraints, typeArgumentsConstraints, cascadingMetaDataBuilder ); } - private Set> convertToMetaConstraints(List> constraintDescriptors, Property property) { + private Set> convertToMetaConstraints(List> constraintDescriptors, JavaBeanField javaBeanField) { if ( constraintDescriptors.isEmpty() ) { return Collections.emptySet(); } Set> constraints = newHashSet(); - ConstraintLocation location = ConstraintLocation.forProperty( property ); + ConstraintLocation location = ConstraintLocation.forField( javaBeanField ); for ( ConstraintDescriptorImpl constraintDescription : constraintDescriptors ) { constraints.add( MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescription, location ) ); @@ -843,7 +843,7 @@ private TypeArgumentFieldLocation(Field field) { @Override public ConstraintLocation toConstraintLocation() { - return ConstraintLocation.forProperty( new JavaBeanField( field ) ); + return ConstraintLocation.forField( new JavaBeanField( field ) ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java index 5244d464e7..1126e715ab 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java @@ -70,19 +70,19 @@ ConstrainedField build(Class beanClass, List alreadyProcessedFieldNam alreadyProcessedFieldNames.add( mainAttributeValue ); } Field field = findField( beanClass, mainAttributeValue ); - JavaBeanField property = new JavaBeanField( field ); - ConstraintLocation constraintLocation = ConstraintLocation.forProperty( property ); + JavaBeanField javaBeanField = new JavaBeanField( field ); + ConstraintLocation constraintLocation = ConstraintLocation.forField( javaBeanField ); Set> metaConstraints = constraintTypeStaxBuilders.stream() .map( builder -> builder.build( constraintLocation, java.lang.annotation.ElementType.FIELD, null ) ) .collect( Collectors.toSet() ); ContainerElementTypeConfiguration containerElementTypeConfiguration = getContainerElementTypeConfiguration( - property.getType(), constraintLocation ); + javaBeanField.getType(), constraintLocation ); ConstrainedField constrainedField = new ConstrainedField( ConfigurationSource.XML, - property, + javaBeanField, metaConstraints, containerElementTypeConfiguration.getMetaConstraints(), getCascadingMetaData( containerElementTypeConfiguration.getTypeParametersCascadingMetaData(), ReflectionHelper.typeOf( field ) ) @@ -91,7 +91,7 @@ ConstrainedField build(Class beanClass, List alreadyProcessedFieldNam // ignore annotations if ( ignoreAnnotations.isPresent() ) { annotationProcessingOptions.ignoreConstraintAnnotationsOnMember( - property, + javaBeanField, ignoreAnnotations.get() ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java index b809befab9..fbe4766597 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java @@ -26,8 +26,6 @@ import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; -import org.hibernate.validator.internal.properties.Callable; -import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; @@ -74,8 +72,8 @@ ConstrainedExecutable build(Class beanClass, List alreadyProcessedGet alreadyProcessedGetterNames.add( mainAttributeValue ); } Method getter = findGetter( beanClass, mainAttributeValue ); - Property property = new JavaBeanGetter( beanClass, getter ); - ConstraintLocation constraintLocation = ConstraintLocation.forProperty( property ); + JavaBeanGetter javaBeanGetter = new JavaBeanGetter( beanClass, getter ); + ConstraintLocation constraintLocation = ConstraintLocation.forGetter( javaBeanGetter ); Set> metaConstraints = constraintTypeStaxBuilders.stream() .map( builder -> builder.build( constraintLocation, java.lang.annotation.ElementType.METHOD, null ) ) @@ -86,7 +84,7 @@ ConstrainedExecutable build(Class beanClass, List alreadyProcessedGet ConstrainedExecutable constrainedGetter = new ConstrainedExecutable( ConfigurationSource.XML, - property.as( Callable.class ), + javaBeanGetter, Collections.emptyList(), Collections.>emptySet(), metaConstraints, @@ -97,7 +95,7 @@ ConstrainedExecutable build(Class beanClass, List alreadyProcessedGet // ignore annotations if ( ignoreAnnotations.isPresent() ) { annotationProcessingOptions.ignoreConstraintAnnotationsOnMember( - property, + javaBeanGetter, ignoreAnnotations.get() ); } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/location/ConstraintLocationTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/location/ConstraintLocationTest.java index acf7934c4b..0bbca776e3 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/location/ConstraintLocationTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/location/ConstraintLocationTest.java @@ -33,8 +33,8 @@ public void two_constraint_locations_for_the_same_type_should_be_equal() { @TestForIssue(jiraKey = "HV-930") public void two_constraint_locations_for_the_same_member_should_be_equal() throws Exception { Method getter = Foo.class.getMethod( "getBar" ); - ConstraintLocation location1 = ConstraintLocation.forProperty( new JavaBeanGetter( getter ) ); - ConstraintLocation location2 = ConstraintLocation.forProperty( new JavaBeanGetter( getter ) ); + ConstraintLocation location1 = ConstraintLocation.forGetter( new JavaBeanGetter( getter ) ); + ConstraintLocation location2 = ConstraintLocation.forGetter( new JavaBeanGetter( getter ) ); assertEquals( location1, location2, "Two constraint locations for the same type should be equal" ); } From 8a80bcd3354730ffdc7f3db591fd498fb67b6d74 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Tue, 5 Jun 2018 23:25:12 +0200 Subject: [PATCH 053/393] HV-1623 Clean ups around cascadable properties in PropertyMetaData --- .../metadata/aggregated/FieldCascadable.java | 43 +++++++++++++++++++ .../metadata/aggregated/GetterCascadable.java | 43 +++++++++++++++++++ .../aggregated/PropertyCascadable.java | 32 ++++++++------ .../metadata/aggregated/PropertyMetaData.java | 34 +++++++-------- 4 files changed, 121 insertions(+), 31 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java new file mode 100644 index 0000000000..37d82ff6da --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java @@ -0,0 +1,43 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.metadata.aggregated; + +import java.lang.annotation.ElementType; + +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.facets.Cascadable; +import org.hibernate.validator.internal.properties.Property; + +/** + * A {@link Cascadable} backed by a field of a Java bean. + * + * @author Gunnar Morling + * @author Marko Bekhta + */ +public class FieldCascadable extends PropertyCascadable { + + FieldCascadable(Property property, CascadingMetaData cascadingMetaData) { + super( property, cascadingMetaData ); + } + + @Override + public ElementType getElementType() { + return ElementType.FIELD; + } + + public static class Builder extends PropertyCascadable.Builder { + + protected Builder(ValueExtractorManager valueExtractorManager, Property property, CascadingMetaDataBuilder cascadingMetaDataBuilder) { + super( valueExtractorManager, property, cascadingMetaDataBuilder ); + } + + @Override + protected Cascadable create(Property property, CascadingMetaData cascadingMetaData) { + return new FieldCascadable( property, cascadingMetaData ); + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java new file mode 100644 index 0000000000..fbb379ab2e --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java @@ -0,0 +1,43 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.metadata.aggregated; + +import java.lang.annotation.ElementType; + +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.facets.Cascadable; +import org.hibernate.validator.internal.properties.Property; + +/** + * A {@link Cascadable} backed by a getter of a Java bean. + * + * @author Gunnar Morling + * @author Marko Bekhta + */ +public class GetterCascadable extends PropertyCascadable { + + GetterCascadable(Property property, CascadingMetaData cascadingMetaData) { + super( property, cascadingMetaData ); + } + + @Override + public ElementType getElementType() { + return ElementType.METHOD; + } + + public static class Builder extends PropertyCascadable.Builder { + + protected Builder(ValueExtractorManager valueExtractorManager, Property property, CascadingMetaDataBuilder cascadingMetaDataBuilder) { + super( valueExtractorManager, property, cascadingMetaDataBuilder ); + } + + @Override + protected Cascadable create(Property property, CascadingMetaData cascadingMetaData) { + return new GetterCascadable( property, cascadingMetaData ); + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyCascadable.java index 7afa0fd018..eafc89bbb3 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyCascadable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyCascadable.java @@ -6,14 +6,13 @@ */ package org.hibernate.validator.internal.metadata.aggregated; -import java.lang.annotation.ElementType; import java.lang.reflect.Type; import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.facets.Cascadable; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Property; -import org.hibernate.validator.internal.properties.javabean.JavaBeanField; /** * A {@link Cascadable} backed by a field of a Java bean. @@ -21,23 +20,16 @@ * @author Gunnar Morling * @author Marko Bekhta */ -public class PropertyCascadable implements Cascadable { +public abstract class PropertyCascadable implements Cascadable { private final Property property; private final Type cascadableType; private final CascadingMetaData cascadingMetaData; - private final ElementType elementType; PropertyCascadable(Property property, CascadingMetaData cascadingMetaData) { this.property = property; this.cascadableType = property.getType(); this.cascadingMetaData = cascadingMetaData; - this.elementType = property instanceof JavaBeanField ? ElementType.FIELD : ElementType.METHOD; - } - - @Override - public ElementType getElementType() { - return elementType; } @Override @@ -60,13 +52,13 @@ public CascadingMetaData getCascadingMetaData() { return cascadingMetaData; } - public static class Builder implements Cascadable.Builder { + public abstract static class Builder implements Cascadable.Builder { private final ValueExtractorManager valueExtractorManager; private final Property property; private CascadingMetaDataBuilder cascadingMetaDataBuilder; - public Builder(ValueExtractorManager valueExtractorManager, Property property, CascadingMetaDataBuilder cascadingMetaDataBuilder) { + protected Builder(ValueExtractorManager valueExtractorManager, Property property, CascadingMetaDataBuilder cascadingMetaDataBuilder) { this.valueExtractorManager = valueExtractorManager; this.property = property; this.cascadingMetaDataBuilder = cascadingMetaDataBuilder; @@ -78,8 +70,20 @@ public void mergeCascadingMetaData(CascadingMetaDataBuilder cascadingMetaData) { } @Override - public PropertyCascadable build() { - return new PropertyCascadable( property, cascadingMetaDataBuilder.build( valueExtractorManager, property ) ); + public Cascadable build() { + return create( property, cascadingMetaDataBuilder.build( valueExtractorManager, property ) ); + } + + protected abstract Cascadable create(Property property, CascadingMetaData build); + + public static Cascadable.Builder builder(ConstrainedElementKind constrainedElementKind, ValueExtractorManager valueExtractorManager, Property property, CascadingMetaDataBuilder cascadingMetaDataBuilder) { + if ( ConstrainedElementKind.FIELD == constrainedElementKind ) { + return new FieldCascadable.Builder( valueExtractorManager, property, cascadingMetaDataBuilder ); + } + else if ( ConstrainedElementKind.METHOD == constrainedElementKind ) { + return new GetterCascadable.Builder( valueExtractorManager, property, cascadingMetaDataBuilder ); + } + throw new IllegalStateException( "It should either be field or method." ); } } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java index 9568a38dbd..3ef5565d16 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java @@ -18,6 +18,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -38,7 +39,6 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; import org.hibernate.validator.internal.metadata.raw.ConstrainedType; -import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; @@ -211,31 +211,31 @@ public final void add(ConstrainedElement constrainedElement) { if ( constrainedElement.getCascadingMetaDataBuilder().isMarkedForCascadingOnAnnotatedObjectOrContainerElements() || constrainedElement.getCascadingMetaDataBuilder().hasGroupConversionsOnAnnotatedObjectOrContainerElements() ) { - if ( constrainedElement.getKind() == ConstrainedElementKind.FIELD ) { - Property property = ( (ConstrainedField) constrainedElement ).getProperty(); - Cascadable.Builder builder = cascadableBuilders.get( property ); + Optional constrainable = getConstrainableFromConstrainedElement( constrainedElement ); + + if ( constrainable.isPresent() ) { + Property property = constrainable.get().as( Property.class ); + Cascadable.Builder builder = cascadableBuilders.get( property ); if ( builder == null ) { - builder = new PropertyCascadable.Builder( valueExtractorManager, property, constrainedElement.getCascadingMetaDataBuilder() ); + builder = PropertyCascadable.Builder.builder( constrainedElement.getKind(), valueExtractorManager, property, constrainedElement.getCascadingMetaDataBuilder() ); cascadableBuilders.put( property, builder ); } else { builder.mergeCascadingMetaData( constrainedElement.getCascadingMetaDataBuilder() ); } } - else if ( constrainedElement.getKind() == ConstrainedElementKind.METHOD ) { - Callable method = ( (ConstrainedExecutable) constrainedElement ).getCallable(); - Cascadable.Builder builder = cascadableBuilders.get( method ); + } + } - if ( builder == null ) { - builder = new PropertyCascadable.Builder( valueExtractorManager, method.as( Property.class ), constrainedElement.getCascadingMetaDataBuilder() ); - cascadableBuilders.put( method, builder ); - } - else { - builder.mergeCascadingMetaData( constrainedElement.getCascadingMetaDataBuilder() ); - } - } + private Optional getConstrainableFromConstrainedElement(ConstrainedElement constrainedElement) { + if ( constrainedElement.getKind() == ConstrainedElementKind.FIELD ) { + return Optional.of( ( (ConstrainedField) constrainedElement ).getProperty() ); + } + else if ( constrainedElement.getKind() == ConstrainedElementKind.METHOD ) { + return Optional.of( ( (ConstrainedExecutable) constrainedElement ).getCallable() ); } + return Optional.empty(); } @Override @@ -256,7 +256,7 @@ private MetaConstraint withGetterLocation(ConstraintLocation getterConstraint ConstraintLocation converted = null; // fast track if it's a regular constraint - if ( !(constraint.getLocation() instanceof TypeArgumentConstraintLocation) ) { + if ( !( constraint.getLocation() instanceof TypeArgumentConstraintLocation ) ) { // Change the constraint location to a GetterConstraintLocation if it is not already one if ( constraint.getLocation() instanceof GetterPropertyConstraintLocation ) { converted = constraint.getLocation(); From 4a6500f510fc0ef43688a8cc67613ae37c7558d5 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Wed, 30 May 2018 22:09:50 +0200 Subject: [PATCH 054/393] HV-1623 Remove redundant check in ConfiguredConstraint - based on the usage of the method we cannot receive methods into it, hence the check can be removed. And also the method can be named more specific to represent what it is really should be doing. --- .../internal/cfg/context/ConfiguredConstraint.java | 10 +++------- .../context/PropertyConstraintMappingContextImpl.java | 4 ++-- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java index c2f07e008a..87c1bb0ace 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java @@ -21,9 +21,7 @@ import org.hibernate.validator.cfg.ConstraintDef; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.properties.Callable; -import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; -import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; import org.hibernate.validator.internal.util.annotation.AnnotationDescriptor; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.internal.util.logging.Log; @@ -57,13 +55,11 @@ static ConfiguredConstraint forType(ConstraintDef( constraint, ConstraintLocation.forClass( beanType ), ElementType.TYPE ); } - static ConfiguredConstraint forProperty(ConstraintDef constraint, Property property) { + static ConfiguredConstraint forFieldProperty(ConstraintDef constraint, JavaBeanField javaBeanField) { return new ConfiguredConstraint<>( constraint, - property instanceof JavaBeanField - ? ConstraintLocation.forField( property.as( JavaBeanField.class ) ) - : ConstraintLocation.forGetter( property.as( JavaBeanGetter.class ) ), - property instanceof JavaBeanField ? ElementType.FIELD : ElementType.METHOD + ConstraintLocation.forField( javaBeanField ), + ElementType.FIELD ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java index 10fe537c9f..7443605991 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java @@ -62,8 +62,8 @@ protected PropertyConstraintMappingContextImpl getThis() { public PropertyConstraintMappingContext constraint(ConstraintDef definition) { if ( property instanceof JavaBeanField ) { super.addConstraint( - ConfiguredConstraint.forProperty( - definition, property + ConfiguredConstraint.forFieldProperty( + definition, property.as( JavaBeanField.class ) ) ); } From a9c4de8eac60818e07457972aa6dd89f3b60722b Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Wed, 30 May 2018 22:21:38 +0200 Subject: [PATCH 055/393] HV-1623 Clean up property metadata - changed Constrainable to Property to better represent the intended objects to be processed by the builder - removed unused parameters, fields and methods --- .../metadata/aggregated/PropertyMetaData.java | 34 ++----------------- 1 file changed, 3 insertions(+), 31 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java index 3ef5565d16..eda2d4b0f8 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java @@ -6,10 +6,7 @@ */ package org.hibernate.validator.internal.metadata.aggregated; -import java.lang.reflect.Method; import java.lang.reflect.Type; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayDeque; import java.util.Collections; import java.util.Deque; @@ -24,7 +21,6 @@ import javax.validation.ElementKind; -import org.hibernate.validator.HibernateValidatorPermission; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; @@ -44,7 +40,6 @@ import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; -import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethod; import org.hibernate.validator.internal.util.stereotypes.Immutable; /** @@ -72,8 +67,7 @@ private PropertyMetaData(String propertyName, Type type, Set> constraints, Set> containerElementsConstraints, - Set cascadables, - boolean cascadingProperty) { + Set cascadables) { super( propertyName, type, @@ -158,9 +152,8 @@ public static class Builder extends MetaDataBuilder { ); private final String propertyName; - private final Map cascadableBuilders = new HashMap<>(); + private final Map cascadableBuilders = new HashMap<>(); private final Type propertyType; - private boolean cascadingProperty = false; public Builder(Class beanClass, ConstrainedField constrainedProperty, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { @@ -207,8 +200,6 @@ public boolean accepts(ConstrainedElement constrainedElement) { public final void add(ConstrainedElement constrainedElement) { super.add( constrainedElement ); - cascadingProperty = cascadingProperty || constrainedElement.getCascadingMetaDataBuilder().isCascading(); - if ( constrainedElement.getCascadingMetaDataBuilder().isMarkedForCascadingOnAnnotatedObjectOrContainerElements() || constrainedElement.getCascadingMetaDataBuilder().hasGroupConversionsOnAnnotatedObjectOrContainerElements() ) { @@ -316,24 +307,6 @@ else if ( constrainedElement.getKind() == ConstrainedElementKind.METHOD ) { return null; } - /** - * Returns an accessible copy of the given member. - */ - private Method getAccessible(Method original) { - SecurityManager sm = System.getSecurityManager(); - if ( sm != null ) { - sm.checkPermission( HibernateValidatorPermission.ACCESS_PRIVATE_MEMBERS ); - } - - Class clazz = original.getDeclaringClass(); - - return run( GetDeclaredMethod.andMakeAccessible( clazz, original.getName() ) ); - } - - private T run(PrivilegedAction action) { - return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); - } - @Override public PropertyMetaData build() { Set cascadables = cascadableBuilders.values() @@ -346,8 +319,7 @@ public PropertyMetaData build() { propertyType, adaptOriginsAndImplicitGroups( getDirectConstraints() ), adaptOriginsAndImplicitGroups( getContainerElementConstraints() ), - cascadables, - cascadingProperty + cascadables ); } } From e409264da8bb06be253325f07729e8b64d88d648 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Wed, 30 May 2018 22:31:32 +0200 Subject: [PATCH 056/393] HV-1623 Add additional checks before casting --- .../metadata/aggregated/PropertyMetaData.java | 19 +++++++++++++++++-- .../validator/internal/util/logging/Log.java | 4 ++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java index eda2d4b0f8..8150ea009b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java @@ -6,6 +6,7 @@ */ package org.hibernate.validator.internal.metadata.aggregated; +import java.lang.invoke.MethodHandles; import java.lang.reflect.Type; import java.util.ArrayDeque; import java.util.Collections; @@ -40,6 +41,8 @@ import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.util.stereotypes.Immutable; /** @@ -60,6 +63,8 @@ */ public class PropertyMetaData extends AbstractConstraintMetaData { + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + @Immutable private final Set cascadables; @@ -221,10 +226,20 @@ public final void add(ConstrainedElement constrainedElement) { private Optional getConstrainableFromConstrainedElement(ConstrainedElement constrainedElement) { if ( constrainedElement.getKind() == ConstrainedElementKind.FIELD ) { - return Optional.of( ( (ConstrainedField) constrainedElement ).getProperty() ); + if ( constrainedElement instanceof ConstrainedField ) { + return Optional.of( ( (ConstrainedField) constrainedElement ).getProperty() ); + } + else { + LOG.getUnexpectedConstraintElementType( ConstrainedField.class, constrainedElement.getClass() ); + } } else if ( constrainedElement.getKind() == ConstrainedElementKind.METHOD ) { - return Optional.of( ( (ConstrainedExecutable) constrainedElement ).getCallable() ); + if ( constrainedElement instanceof ConstrainedExecutable ) { + return Optional.of( ( (ConstrainedExecutable) constrainedElement ).getCallable() ); + } + else { + LOG.getUnexpectedConstraintElementType( ConstrainedExecutable.class, constrainedElement.getClass() ); + } } return Optional.empty(); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 41bd6883f3..09f355ab3e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -63,6 +63,7 @@ import org.hibernate.validator.spi.scripting.ScriptEvaluationException; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; import org.hibernate.validator.spi.scripting.ScriptEvaluatorNotFoundException; + import org.jboss.logging.BasicLogger; import org.jboss.logging.annotations.Cause; import org.jboss.logging.annotations.FormatWith; @@ -857,4 +858,7 @@ ConstraintDefinitionException getConstraintValidatorDefinitionConstraintMismatch @FormatWith(ClassObjectFormatter.class) Class> constraintValidatorImplementationType, @FormatWith(ClassObjectFormatter.class) Class registeredConstraintAnnotationType, @FormatWith(TypeFormatter.class) Type declaredConstraintAnnotationType); + + @Message(id = 244, value = "ConstrainedElement expected class was %1$s, but instead received %2$s.") + AssertionError getUnexpectedConstraintElementType(@FormatWith(ClassObjectFormatter.class) Class expecting, @FormatWith(ClassObjectFormatter.class) Class got); } From 7356867ec9f530372960542aaeb4c1f927b079e0 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Wed, 30 May 2018 23:08:24 +0200 Subject: [PATCH 057/393] HV-1623 Remove ConstrainableFormatter and push the logic to toString implementations --- .../javabean/JavaBeanExecutable.java | 8 ++++ .../properties/javabean/JavaBeanField.java | 5 +++ .../validator/internal/util/logging/Log.java | 25 ++++++------ .../formatter/ConstrainableFormatter.java | 39 ------------------- 4 files changed, 25 insertions(+), 52 deletions(-) delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/util/logging/formatter/ConstrainableFormatter.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java index afe1e9211a..d7285fcb41 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java @@ -176,6 +176,14 @@ public int hashCode() { return result; } + @Override + public String toString() { + return ExecutableHelper.getExecutableAsString( + getDeclaringClass().getSimpleName() + "#" + name, + getParameterTypes() + ); + } + private boolean hasReturnValue(Executable executable) { if ( executable instanceof Constructor ) { return true; diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java index 8ea4eb2067..67271d68c9 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java @@ -95,6 +95,11 @@ public int hashCode() { return result; } + @Override + public String toString() { + return getName(); + } + /** * Returns an accessible copy of the given member. */ diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 09f355ab3e..18a6f24df3 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -54,7 +54,6 @@ import org.hibernate.validator.internal.util.logging.formatter.ClassObjectFormatter; import org.hibernate.validator.internal.util.logging.formatter.CollectionOfClassesObjectFormatter; import org.hibernate.validator.internal.util.logging.formatter.CollectionOfObjectsToStringFormatter; -import org.hibernate.validator.internal.util.logging.formatter.ConstrainableFormatter; import org.hibernate.validator.internal.util.logging.formatter.DurationFormatter; import org.hibernate.validator.internal.util.logging.formatter.ExecutableFormatter; import org.hibernate.validator.internal.util.logging.formatter.ObjectArrayFormatter; @@ -252,13 +251,13 @@ GroupDefinitionException getUnableToExpandDefaultGroupListException(@FormatWith( GroupDefinitionException getWrongDefaultGroupSequenceProviderTypeException(@FormatWith(ClassObjectFormatter.class) Class beanClass); @Message(id = 56, value = "Method or constructor %1$s doesn't have a parameter with index %2$d.") - IllegalArgumentException getInvalidExecutableParameterIndexException(@FormatWith(ConstrainableFormatter.class) Callable callable, int index); + IllegalArgumentException getInvalidExecutableParameterIndexException(Callable callable, int index); @Message(id = 59, value = "Unable to retrieve annotation parameter value.") ValidationException getUnableToRetrieveAnnotationParameterValueException(@Cause Exception e); @Message(id = 62, value = "Method or constructor %1$s has %2$s parameters, but the passed list of parameter meta data has a size of %3$s.") - IllegalArgumentException getInvalidLengthOfParameterMetaDataListException(@FormatWith(ConstrainableFormatter.class) Callable callable, int nbParameters, int listSize); + IllegalArgumentException getInvalidLengthOfParameterMetaDataListException(Callable callable, int nbParameters, int listSize); @Message(id = 63, value = "Unable to instantiate %s.") ValidationException getUnableToInstantiateException(@FormatWith(ClassObjectFormatter.class) Class clazz, @Cause Exception e); @@ -468,7 +467,7 @@ ConstraintDeclarationException getMultipleGroupConversionsForSameSourceException @Message(id = 132, value = "Void methods must not be constrained or marked for cascaded validation, but method %s is.") - ConstraintDeclarationException getVoidMethodsMustNotBeConstrainedException(@FormatWith(ConstrainableFormatter.class) Callable callable); + ConstraintDeclarationException getVoidMethodsMustNotBeConstrainedException(Callable callable); @Message(id = 133, value = "%1$s does not contain a constructor with the parameter types %2$s.") ValidationException getBeanDoesNotContainConstructorException(@FormatWith(ClassObjectFormatter.class) Class beanClass, @@ -503,7 +502,7 @@ ConstraintDeclarationException getImplicitConstraintTargetInAmbiguousConfigurati @Message(id = 142, value = "Cross parameter constraint %1$s is illegally placed on a parameterless method or constructor '%2$s'.") ConstraintDeclarationException getCrossParameterConstraintOnMethodWithoutParametersException( - @FormatWith(ClassObjectFormatter.class) Class constraint, @FormatWith(ConstrainableFormatter.class) Constrainable executable); + @FormatWith(ClassObjectFormatter.class) Class constraint, Constrainable executable); @Message(id = 143, value = "Cross parameter constraint %1$s is illegally placed on class level.") @@ -512,7 +511,7 @@ ConstraintDeclarationException getCrossParameterConstraintOnMethodWithoutParamet @Message(id = 144, value = "Cross parameter constraint %1$s is illegally placed on field '%2$s'.") ConstraintDeclarationException getCrossParameterConstraintOnFieldException(@FormatWith(ClassObjectFormatter.class) Class constraint, - @FormatWith(ConstrainableFormatter.class) Constrainable field); + Constrainable field); @Message(id = 146, value = "No parameter nodes may be added since path %s doesn't refer to a cross-parameter constraint.") @@ -538,11 +537,11 @@ UnexpectedTypeException getMultipleValidatorsForSameTypeException(@FormatWith(Cl @Message(id = 151, value = "A method overriding another method must not redefine the parameter constraint configuration, but method %2$s redefines the configuration of %1$s.") - ConstraintDeclarationException getParameterConfigurationAlteredInSubTypeException(@FormatWith(ConstrainableFormatter.class) Callable superMethod, @FormatWith(ConstrainableFormatter.class) Callable subMethod); + ConstraintDeclarationException getParameterConfigurationAlteredInSubTypeException(Callable superMethod, Callable subMethod); @Message(id = 152, value = "Two methods defined in parallel types must not declare parameter constraints, if they are overridden by the same method, but methods %s and %s both define parameter constraints.") - ConstraintDeclarationException getParameterConstraintsDefinedInMethodsFromParallelTypesException(@FormatWith(ConstrainableFormatter.class) Callable method1, @FormatWith(ConstrainableFormatter.class) Callable method2); + ConstraintDeclarationException getParameterConstraintsDefinedInMethodsFromParallelTypesException(Callable method1, Callable method2); @Message(id = 153, value = "The constraint %1$s used ConstraintTarget#%2$s but is not specified on a method or constructor.") @@ -584,7 +583,7 @@ ConstraintDefinitionException getValidatorForCrossParameterConstraintMustEitherV @Message(id = 161, value = "Two methods defined in parallel types must not define group conversions for a cascaded method return value, if they are overridden by the same method, but methods %s and %s both define parameter constraints.") - ConstraintDeclarationException getMethodsFromParallelTypesMustNotDefineGroupConversionsForCascadedReturnValueException(@FormatWith(ConstrainableFormatter.class) Callable method1, @FormatWith(ConstrainableFormatter.class) Callable method2); + ConstraintDeclarationException getMethodsFromParallelTypesMustNotDefineGroupConversionsForCascadedReturnValueException(Callable method1, Callable method2); @Message(id = 162, value = "The validated type %1$s does not specify the constructor/method: %2$s") @@ -632,11 +631,11 @@ ConstraintDefinitionException getValidatorForCrossParameterConstraintMustEitherV @Message(id = 174, value = "Parameter %3$s of method or constructor %2$s of type %1$s is configured more than once via the programmatic constraint declaration API.") - ValidationException getParameterHasAlreadyBeConfiguredViaProgrammaticApiException(@FormatWith(ClassObjectFormatter.class) Class beanClass, @FormatWith(ConstrainableFormatter.class) Callable callable, int parameterIndex); + ValidationException getParameterHasAlreadyBeConfiguredViaProgrammaticApiException(@FormatWith(ClassObjectFormatter.class) Class beanClass, Callable callable, int parameterIndex); @Message(id = 175, value = "The return value of method or constructor %2$s of type %1$s is configured more than once via the programmatic constraint declaration API.") - ValidationException getReturnValueHasAlreadyBeConfiguredViaProgrammaticApiException(@FormatWith(ClassObjectFormatter.class) Class beanClass, @FormatWith(ConstrainableFormatter.class) Callable callable); + ValidationException getReturnValueHasAlreadyBeConfiguredViaProgrammaticApiException(@FormatWith(ClassObjectFormatter.class) Class beanClass, Callable callable); @Message(id = 176, value = "Constructor %2$s of type %1$s is configured more than once via the programmatic constraint declaration API.") @@ -644,7 +643,7 @@ ConstraintDefinitionException getValidatorForCrossParameterConstraintMustEitherV @Message(id = 177, value = "Cross-parameter constraints for the method or constructor %2$s of type %1$s are declared more than once via the programmatic constraint declaration API.") - ValidationException getCrossParameterElementHasAlreadyBeConfiguredViaProgrammaticApiException(@FormatWith(ClassObjectFormatter.class) Class beanClass, @FormatWith(ConstrainableFormatter.class) Callable callable); + ValidationException getCrossParameterElementHasAlreadyBeConfiguredViaProgrammaticApiException(@FormatWith(ClassObjectFormatter.class) Class beanClass, Callable callable); @Message(id = 178, value = "Multiplier cannot be negative: %d.") IllegalArgumentException getMultiplierCannotBeNegativeException(int multiplier); @@ -717,7 +716,7 @@ ConstraintDeclarationException getInconsistentValueUnwrappingConfigurationBetwee ValueExtractorDefinitionException getValueExtractorDeclaresExtractedValueMultipleTimesException(@FormatWith(ClassObjectFormatter.class) Class extractorType); @Message(id = 205, value = "Invalid unwrapping configuration for constraint %2$s on %1$s. You can only define one of 'Unwrapping.Skip' or 'Unwrapping.Unwrap'.") - ConstraintDeclarationException getInvalidUnwrappingConfigurationForConstraintException(@FormatWith(ConstrainableFormatter.class) Constrainable constrainable, @FormatWith(ClassObjectFormatter.class) Class constraint); + ConstraintDeclarationException getInvalidUnwrappingConfigurationForConstraintException(Constrainable constrainable, @FormatWith(ClassObjectFormatter.class) Class constraint); @Message(id = 206, value = "Unable to instantiate value extractor class %s.") ValidationException getUnableToInstantiateValueExtractorClassException(String valueExtractorClassName, @Cause ValidationException e); diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/formatter/ConstrainableFormatter.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/formatter/ConstrainableFormatter.java deleted file mode 100644 index d5f8ea6f1a..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/formatter/ConstrainableFormatter.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.util.logging.formatter; - -import org.hibernate.validator.internal.properties.Callable; -import org.hibernate.validator.internal.properties.Constrainable; -import org.hibernate.validator.internal.util.ExecutableHelper; - -/** - * Used with JBoss Logging to display executables in log messages. - * - * @author Marko Bekhta - */ -public class ConstrainableFormatter { - - private final String stringRepresentation; - - public ConstrainableFormatter(Constrainable constrainable) { - String name = constrainable.getName(); - if ( constrainable instanceof Callable ) { - name = constrainable.getDeclaringClass().getSimpleName() + "#" + name; - Class[] parameterTypes = ( (Callable) constrainable ).getParameterTypes(); - - this.stringRepresentation = ExecutableHelper.getExecutableAsString( name, parameterTypes ); - } - else { - this.stringRepresentation = name; - } - } - - @Override - public String toString() { - return stringRepresentation; - } -} From 99e73809f3a5fecffae02d6b7b71f5be73d32328 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Thu, 31 May 2018 20:19:16 +0200 Subject: [PATCH 058/393] HV-1623 Wrap ElementType with ConstraintLocationKind --- .../cfg/context/ConfiguredConstraint.java | 31 ++++++++++------- .../ConstraintMappingContextImplBase.java | 2 +- ...erElementConstraintMappingContextImpl.java | 2 +- .../internal/engine/ValidatorImpl.java | 2 +- .../metadata/aggregated/BeanMetaDataImpl.java | 4 +-- .../aggregated/ExecutableMetaData.java | 17 ++++++---- .../metadata/aggregated/MetaDataBuilder.java | 2 +- .../metadata/core/MetaConstraint.java | 8 ++--- .../descriptor/ConstraintDescriptorImpl.java | 33 +++++++++---------- .../descriptor/ElementDescriptorImpl.java | 4 +-- .../metadata/location/ConstraintLocation.java | 21 ++++++++++++ .../provider/AnnotationMetaDataProvider.java | 20 ++++++----- .../metadata/raw/ConstrainedExecutable.java | 2 +- .../internal/properties/Callable.java | 3 +- .../javabean/JavaBeanExecutable.java | 7 ++-- .../ClassConstraintTypeStaxBuilder.java | 3 +- .../mapping/ConstrainedFieldStaxBuilder.java | 3 +- .../mapping/ConstrainedGetterStaxBuilder.java | 3 +- .../ConstrainedParameterStaxBuilder.java | 3 +- .../mapping/ConstraintTypeStaxBuilder.java | 5 +-- .../ContainerElementTypeStaxBuilder.java | 2 +- .../mapping/CrossParameterStaxBuilder.java | 3 +- .../xml/mapping/ReturnValueStaxBuilder.java | 5 +-- ...ssionLanguageMessageInterpolationTest.java | 5 +-- ...ResourceBundleMessageInterpolatorTest.java | 9 ++--- .../metadata/core/MetaConstraintTest.java | 7 ++-- .../AnnotationMetaDataProviderTest.java | 5 +-- 27 files changed, 129 insertions(+), 82 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java index 87c1bb0ace..3b2cbfdb6a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java @@ -7,7 +7,6 @@ package org.hibernate.validator.internal.cfg.context; import java.lang.annotation.Annotation; -import java.lang.annotation.ElementType; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.reflect.Type; @@ -20,6 +19,8 @@ import org.hibernate.validator.cfg.AnnotationDef; import org.hibernate.validator.cfg.ConstraintDef; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; import org.hibernate.validator.internal.util.annotation.AnnotationDescriptor; @@ -43,41 +44,41 @@ class ConfiguredConstraint { private final ConstraintDef constraint; private final ConstraintLocation location; - private final ElementType elementType; + private final ConstraintLocationKind kind; - private ConfiguredConstraint(ConstraintDef constraint, ConstraintLocation location, ElementType elementType) { + private ConfiguredConstraint(ConstraintDef constraint, ConstraintLocation location, ConstraintLocationKind kind) { this.constraint = constraint; this.location = location; - this.elementType = elementType; + this.kind = kind; } static ConfiguredConstraint forType(ConstraintDef constraint, Class beanType) { - return new ConfiguredConstraint<>( constraint, ConstraintLocation.forClass( beanType ), ElementType.TYPE ); + return new ConfiguredConstraint<>( constraint, ConstraintLocation.forClass( beanType ), ConstraintLocationKind.TYPE ); } static ConfiguredConstraint forFieldProperty(ConstraintDef constraint, JavaBeanField javaBeanField) { return new ConfiguredConstraint<>( constraint, ConstraintLocation.forField( javaBeanField ), - ElementType.FIELD + ConstraintLocationKind.FIELD ); } public static ConfiguredConstraint forParameter(ConstraintDef constraint, Callable callable, int parameterIndex) { return new ConfiguredConstraint<>( - constraint, ConstraintLocation.forParameter( callable, parameterIndex ), callable.isConstructor() ? ElementType.CONSTRUCTOR : ElementType.METHOD + constraint, ConstraintLocation.forParameter( callable, parameterIndex ), getConstraintLocationKindFromCallable( callable ) ); } public static ConfiguredConstraint forExecutable(ConstraintDef constraint, Callable callable) { return new ConfiguredConstraint<>( - constraint, ConstraintLocation.forReturnValue( callable ), callable.isConstructor() ? ElementType.CONSTRUCTOR : ElementType.METHOD + constraint, ConstraintLocation.forReturnValue( callable ), getConstraintLocationKindFromCallable( callable ) ); } public static ConfiguredConstraint forCrossParameter(ConstraintDef constraint, Callable callable) { return new ConfiguredConstraint<>( - constraint, ConstraintLocation.forCrossParameter( callable ), callable.isConstructor() ? ElementType.CONSTRUCTOR : ElementType.METHOD + constraint, ConstraintLocation.forCrossParameter( callable ), getConstraintLocationKindFromCallable( callable ) ); } @@ -85,7 +86,7 @@ public static ConfiguredConstraint forTypeArgument(Con return new ConfiguredConstraint<>( constraint, ConstraintLocation.forTypeArgument( delegate, typeArgument, typeOfAnnotatedElement ), - ElementType.TYPE_USE + ConstraintLocationKind.TYPE_USE ); } @@ -115,8 +116,14 @@ public String toString() { return constraint.toString(); } - public ElementType getElementType() { - return elementType; + public ConstraintLocationKind getConstraintLocationKind() { + return kind; + } + + private static ConstraintLocationKind getConstraintLocationKindFromCallable(Callable callable) { + return callable.getConstrainedElementKind() == ConstrainedElementKind.CONSTRUCTOR + ? ConstraintLocationKind.CONSTRUCTOR + : ConstraintLocationKind.METHOD; } /** diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintMappingContextImplBase.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintMappingContextImplBase.java index ec6257bd05..ed8582e4c7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintMappingContextImplBase.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintMappingContextImplBase.java @@ -75,7 +75,7 @@ private MetaConstraint asMetaConstraint(ConfiguredCons constraintHelper, config.getLocation().getConstrainable(), config.createAnnotationDescriptor(), - config.getElementType(), + config.getConstraintLocationKind(), getConstraintType() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java index 755b09f7ce..e9e05526a7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java @@ -239,7 +239,7 @@ private MetaConstraint asMetaConstraint(ConfiguredCons constraintHelper, config.getLocation().getConstrainable(), config.createAnnotationDescriptor(), - config.getElementType(), + config.getConstraintLocationKind(), getConstraintType() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index 202c758875..5ec5c85f0b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -1283,7 +1283,7 @@ private boolean isValidationRequired(BaseBeanValidationContext validationCont validationContext, valueContext.getCurrentBean(), valueContext.getPropertyPath(), - metaConstraint.getElementType() + metaConstraint.getConstraintLocationKind().getElementType() ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java index 3dfe4cbf63..dcd979012b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java @@ -9,7 +9,6 @@ import static org.hibernate.validator.internal.util.CollectionHelper.newHashMap; import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; -import java.lang.annotation.ElementType; import java.lang.invoke.MethodHandles; import java.lang.reflect.Executable; import java.util.ArrayList; @@ -39,6 +38,7 @@ import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.descriptor.ExecutableDescriptorImpl; import org.hibernate.validator.internal.metadata.facets.Cascadable; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; @@ -399,7 +399,7 @@ private static BeanDescriptor createBeanDescriptor(Class beanClass, Set> getClassLevelConstraintsAsDescriptors(Set> constraints) { return constraints.stream() - .filter( c -> c.getElementType() == ElementType.TYPE ) + .filter( c -> c.getConstraintLocationKind() == ConstraintLocationKind.TYPE ) .map( MetaConstraint::getDescriptor ) .collect( Collectors.toSet() ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java index d8c2df456c..a073d5056f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java @@ -28,6 +28,7 @@ import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.descriptor.ExecutableDescriptorImpl; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; import org.hibernate.validator.internal.properties.Callable; @@ -255,7 +256,7 @@ public static class Builder extends MetaDataBuilder { /** * Either CONSTRUCTOR or METHOD. */ - private final ConstrainedElement.ConstrainedElementKind kind; + private final ConstrainedElementKind kind; private final Set constrainedExecutables = newHashSet(); private Callable callable; private final boolean isGetterMethod; @@ -311,7 +312,7 @@ public boolean accepts(ConstrainedElement constrainedElement) { } private boolean isResolvedToSameMethodInHierarchy(Callable first, Callable other) { - if ( first.isConstructor() || other.isConstructor() ) { + if ( isConstructor( first ) || isConstructor( other ) ) { return first.equals( other ); } @@ -319,13 +320,17 @@ private boolean isResolvedToSameMethodInHierarchy(Callable first, Callable other } private boolean overrides(Callable first, Callable other) { - if ( first.isConstructor() || other.isConstructor() ) { + if ( isConstructor( first ) || isConstructor( other ) ) { return false; } return executableHelper.overrides( first, other ); } + private boolean isConstructor(Callable callable) { + return callable.getConstrainedElementKind() == ConstrainedElementKind.CONSTRUCTOR; + } + @Override public final void add(ConstrainedElement constrainedElement) { super.add( constrainedElement ); @@ -380,11 +385,11 @@ public ExecutableMetaData build() { assertCorrectnessOfConfiguration(); return new ExecutableMetaData( - kind == ConstrainedElement.ConstrainedElementKind.CONSTRUCTOR ? callable.getDeclaringClass().getSimpleName() : callable.getName(), + kind == ConstrainedElementKind.CONSTRUCTOR ? callable.getDeclaringClass().getSimpleName() : callable.getName(), callable.getType(), callable.getParameterTypes(), - kind == ConstrainedElement.ConstrainedElementKind.CONSTRUCTOR ? ElementKind.CONSTRUCTOR : ElementKind.METHOD, - kind == ConstrainedElement.ConstrainedElementKind.CONSTRUCTOR ? Collections.singleton( callable.getSignature() ) : + kind == ConstrainedElementKind.CONSTRUCTOR ? ElementKind.CONSTRUCTOR : ElementKind.METHOD, + kind == ConstrainedElementKind.CONSTRUCTOR ? Collections.singleton( callable.getSignature() ) : CollectionHelper.toImmutableSet( signatures ), adaptOriginsAndImplicitGroups( getDirectConstraints() ), adaptOriginsAndImplicitGroups( getContainerElementConstraints() ), diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/MetaDataBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/MetaDataBuilder.java index 66e756da06..cecf054f94 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/MetaDataBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/MetaDataBuilder.java @@ -131,7 +131,7 @@ private MetaConstraint adaptOriginAndImplicitGroup(Met constraintHelper, constraint.getLocation().getConstrainable(), constraint.getDescriptor().getAnnotationDescriptor(), - constraint.getElementType(), + constraint.getConstraintLocationKind(), constraintClass.isInterface() ? constraintClass : null, definedIn, constraint.getDescriptor().getConstraintType() diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java index a08f40a6b9..5fb3c1623b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java @@ -7,7 +7,6 @@ package org.hibernate.validator.internal.metadata.core; import java.lang.annotation.Annotation; -import java.lang.annotation.ElementType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.List; @@ -23,6 +22,7 @@ import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorHelper; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.util.StringHelper; import org.hibernate.validator.internal.util.stereotypes.Immutable; @@ -100,8 +100,8 @@ public final ConstraintDescriptorImpl getDescriptor() { return constraintTree.getDescriptor(); } - public final ElementType getElementType() { - return constraintTree.getDescriptor().getElementType(); + public final ConstraintLocationKind getConstraintLocationKind() { + return constraintTree.getDescriptor().getConstraintLocationKind(); } public boolean validateConstraint(ValidationContext validationContext, ValueContext valueContext) { @@ -123,7 +123,7 @@ public boolean validateConstraint(ValidationContext validationContext, ValueC } private boolean doValidateConstraint(ValidationContext executionContext, ValueContext valueContext) { - valueContext.setElementType( getElementType() ); + valueContext.setElementType( getConstraintLocationKind().getElementType() ); boolean validationResult = constraintTree.validateConstraints( executionContext, valueContext ); return validationResult; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ConstraintDescriptorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ConstraintDescriptorImpl.java index edecfb516c..692bb389c9 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ConstraintDescriptorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ConstraintDescriptorImpl.java @@ -12,7 +12,6 @@ import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.Target; @@ -45,6 +44,7 @@ import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorDescriptor; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.ConstraintOrigin; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.properties.Property; @@ -132,7 +132,7 @@ public class ConstraintDescriptorImpl implements Constrain * Describes on which level ({@code TYPE}, {@code METHOD}, {@code FIELD}) the constraint was * defined on. */ - private final ElementType elementType; + private final ConstraintLocationKind constraintLocationKind; /** * The origin of the constraint. Defined on the actual root class or somewhere in the class hierarchy @@ -165,12 +165,12 @@ public class ConstraintDescriptorImpl implements Constrain public ConstraintDescriptorImpl(ConstraintHelper constraintHelper, Constrainable constrainable, ConstraintAnnotationDescriptor annotationDescriptor, - ElementType type, + ConstraintLocationKind kind, Class implicitGroup, ConstraintOrigin definedOn, ConstraintType externalConstraintType) { this.annotationDescriptor = annotationDescriptor; - this.elementType = type; + this.constraintLocationKind = kind; this.definedOn = definedOn; this.isReportAsSingleInvalidConstraint = annotationDescriptor.getType().isAnnotationPresent( ReportAsSingleViolation.class @@ -206,7 +206,6 @@ public ConstraintDescriptorImpl(ConstraintHelper constraintHelper, this.constraintType = determineConstraintType( annotationDescriptor.getType(), constrainable, - type, !genericValidatorDescriptors.isEmpty(), !crossParameterValidatorDescriptors.isEmpty(), externalConstraintType @@ -228,16 +227,16 @@ public ConstraintDescriptorImpl(ConstraintHelper constraintHelper, public ConstraintDescriptorImpl(ConstraintHelper constraintHelper, Constrainable constrainable, ConstraintAnnotationDescriptor annotationDescriptor, - ElementType type) { - this( constraintHelper, constrainable, annotationDescriptor, type, null, ConstraintOrigin.DEFINED_LOCALLY, null ); + ConstraintLocationKind kind) { + this( constraintHelper, constrainable, annotationDescriptor, kind, null, ConstraintOrigin.DEFINED_LOCALLY, null ); } public ConstraintDescriptorImpl(ConstraintHelper constraintHelper, Constrainable constrainable, ConstraintAnnotationDescriptor annotationDescriptor, - ElementType type, + ConstraintLocationKind kind, ConstraintType constraintType) { - this( constraintHelper, constrainable, annotationDescriptor, type, null, ConstraintOrigin.DEFINED_LOCALLY, constraintType ); + this( constraintHelper, constrainable, annotationDescriptor, kind, null, ConstraintOrigin.DEFINED_LOCALLY, constraintType ); } public ConstraintAnnotationDescriptor getAnnotationDescriptor() { @@ -313,8 +312,8 @@ public boolean isReportAsSingleViolation() { return isReportAsSingleInvalidConstraint; } - public ElementType getElementType() { - return elementType; + public ConstraintLocationKind getConstraintLocationKind() { + return constraintLocationKind; } public ConstraintOrigin getDefinedOn() { @@ -361,7 +360,7 @@ public String toString() { sb.append( ", payloads=" ).append( payloads ); sb.append( ", hasComposingConstraints=" ).append( composingConstraints.isEmpty() ); sb.append( ", isReportAsSingleInvalidConstraint=" ).append( isReportAsSingleInvalidConstraint ); - sb.append( ", elementType=" ).append( elementType ); + sb.append( ", constraintLocationKind=" ).append( constraintLocationKind ); sb.append( ", definedOn=" ).append( definedOn ); sb.append( ", groups=" ).append( groups ); sb.append( ", attributes=" ).append( annotationDescriptor.getAttributes() ); @@ -389,7 +388,6 @@ public String toString() { * * * @param constrainable The annotated member - * @param elementType The type of the annotated element * @param hasGenericValidators Whether the constraint has at least one generic validator or * not * @param hasCrossParameterValidator Whether the constraint has a cross-parameter validator @@ -400,13 +398,12 @@ public String toString() { */ private ConstraintType determineConstraintType(Class constraintAnnotationType, Constrainable constrainable, - ElementType elementType, boolean hasGenericValidators, boolean hasCrossParameterValidator, ConstraintType externalConstraintType) { ConstraintTarget constraintTarget = validationAppliesTo; ConstraintType constraintType = null; - boolean isExecutable = isExecutable( elementType ); + boolean isExecutable = isExecutable( constraintLocationKind ); //target explicitly set to RETURN_VALUE if ( constraintTarget == ConstraintTarget.RETURN_VALUE ) { @@ -533,8 +530,8 @@ private void validateComposingConstraintTypes() { } } - private boolean isExecutable(ElementType elementType) { - return elementType == ElementType.METHOD || elementType == ElementType.CONSTRUCTOR; + private boolean isExecutable(ConstraintLocationKind locationKind) { + return locationKind == ConstraintLocationKind.METHOD || locationKind == ConstraintLocationKind.CONSTRUCTOR; } @SuppressWarnings("unchecked") @@ -744,7 +741,7 @@ annotationType, run( GetAnnotationAttributes.action( constraintAnnotation ) ) } return new ConstraintDescriptorImpl<>( - constraintHelper, constrainable, annotationDescriptorBuilder.build(), elementType, null, definedOn, constraintType + constraintHelper, constrainable, annotationDescriptorBuilder.build(), constraintLocationKind, null, definedOn, constraintType ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ElementDescriptorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ElementDescriptorImpl.java index d80a1972f2..0c865382fa 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ElementDescriptorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ElementDescriptorImpl.java @@ -142,7 +142,7 @@ public boolean hasConstraints() { private void addMatchingDescriptorsForGroup(Class group, Set> matchingDescriptors) { for ( ConstraintDescriptorImpl descriptor : constraintDescriptors ) { - if ( definedInSet.contains( descriptor.getDefinedOn() ) && elementTypes.contains( descriptor.getElementType() ) + if ( definedInSet.contains( descriptor.getDefinedOn() ) && elementTypes.contains( descriptor.getConstraintLocationKind().getElementType() ) && descriptor.getGroups().contains( group ) ) { matchingDescriptors.add( descriptor ); } @@ -160,7 +160,7 @@ private void findMatchingDescriptors(Set> matchingDescri } else { for ( ConstraintDescriptorImpl descriptor : constraintDescriptors ) { - if ( definedInSet.contains( descriptor.getDefinedOn() ) && elementTypes.contains( descriptor.getElementType() ) ) { + if ( definedInSet.contains( descriptor.getDefinedOn() ) && elementTypes.contains( descriptor.getConstraintLocationKind().getElementType() ) ) { matchingDescriptors.add( descriptor ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java index 54aafdbd5a..6e97299d98 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java @@ -6,6 +6,7 @@ */ package org.hibernate.validator.internal.metadata.location; +import java.lang.annotation.ElementType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; @@ -95,4 +96,24 @@ static ConstraintLocation forParameter(Callable callable, int index) { * object array for a {@link ParameterConstraintLocation}. */ Object getValue(Object parent); + + enum ConstraintLocationKind { + TYPE( ElementType.TYPE ), + CONSTRUCTOR( ElementType.CONSTRUCTOR ), + METHOD( ElementType.METHOD ), + PARAMETER( ElementType.PARAMETER ), + FIELD( ElementType.FIELD ), + TYPE_USE( ElementType.TYPE_USE ), + ; + + private final ElementType elementType; + + ConstraintLocationKind(ElementType elementType) { + this.elementType = elementType; + } + + public ElementType getElementType() { + return elementType; + } + } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java index 9f36621a08..cfa173174e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java @@ -12,7 +12,6 @@ import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES; import java.lang.annotation.Annotation; -import java.lang.annotation.ElementType; import java.lang.invoke.MethodHandles; import java.lang.reflect.AccessibleObject; import java.lang.reflect.AnnotatedArrayType; @@ -56,6 +55,7 @@ import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; @@ -234,7 +234,7 @@ private Set getFieldMetaData(Class beanClass) { private ConstrainedField findPropertyMetaData(Field field, JavaBeanField javaBeanField) { Set> constraints = convertToMetaConstraints( - findConstraints( field, ElementType.FIELD, javaBeanField ), + findConstraints( field, ConstraintLocationKind.FIELD, javaBeanField ), javaBeanField ); @@ -307,7 +307,9 @@ private ConstrainedExecutable findExecutableMetaData(Executable executable) { Map>> executableConstraints = findConstraints( executable, - callable.isConstructor() ? ElementType.CONSTRUCTOR : ElementType.METHOD, + callable.getConstrainedElementKind() == ConstrainedElement.ConstrainedElementKind.CONSTRUCTOR + ? ConstraintLocationKind.CONSTRUCTOR + : ConstraintLocationKind.METHOD, callable ).stream().collect( Collectors.groupingBy( ConstraintDescriptorImpl::getConstraintType ) ); @@ -424,7 +426,7 @@ private List getParameterMetaData(Executable executable, C for ( Annotation parameterAnnotation : parameterAnnotations ) { // collect constraints if this annotation is a constraint annotation List> constraints = findConstraintAnnotations( - callable, parameterAnnotation, ElementType.PARAMETER + callable, parameterAnnotation, ConstraintLocationKind.PARAMETER ); for ( ConstraintDescriptorImpl constraintDescriptorImpl : constraints ) { parameterConstraints.add( @@ -464,7 +466,7 @@ private List getParameterMetaData(Executable executable, C * * @return A list of constraint descriptors for all constraint specified for the given member. */ - private List> findConstraints(Member member, ElementType type, Constrainable constrainable) { + private List> findConstraints(Member member, ConstraintLocationKind type, Constrainable constrainable) { List> metaData = newArrayList(); for ( Annotation annotation : ( (AccessibleObject) member ).getDeclaredAnnotations() ) { metaData.addAll( findConstraintAnnotations( constrainable, annotation, type ) ); @@ -484,7 +486,7 @@ private List> findConstraints(Member member, Element private List> findClassLevelConstraints(Class beanClass) { List> metaData = newArrayList(); for ( Annotation annotation : beanClass.getDeclaredAnnotations() ) { - metaData.addAll( findConstraintAnnotations( null, annotation, ElementType.TYPE ) ); + metaData.addAll( findConstraintAnnotations( null, annotation, ConstraintLocationKind.TYPE ) ); } return metaData; } @@ -503,7 +505,7 @@ private List> findClassLevelConstraints(Class bea protected List> findConstraintAnnotations( Constrainable constrainable, A annotation, - ElementType type) { + ConstraintLocationKind type) { // HV-1049 and HV-1311 - Ignore annotations from the JDK (jdk.internal.* and java.*); They cannot be constraint // annotations so skip them right here, as for the proper check we'd need package access permission for @@ -561,7 +563,7 @@ private Map, Class> getGroupConversions(ConvertGroup groupConversion private ConstraintDescriptorImpl buildConstraintDescriptor(Constrainable constrainable, A annotation, - ElementType type) { + ConstraintLocationKind type) { return new ConstraintDescriptorImpl<>( constraintHelper, constrainable, @@ -785,7 +787,7 @@ else if ( annotatedType instanceof AnnotatedParameterizedType ) { */ private Set> findTypeUseConstraints(Constrainable constrainable, AnnotatedType typeArgument, TypeVariable typeVariable, TypeArgumentLocation location, Type type) { Set> constraints = Arrays.stream( typeArgument.getAnnotations() ) - .flatMap( a -> findConstraintAnnotations( constrainable, a, ElementType.TYPE_USE ).stream() ) + .flatMap( a -> findConstraintAnnotations( constrainable, a, ConstraintLocationKind.TYPE_USE ).stream() ) .map( d -> createTypeArgumentMetaConstraint( d, location, typeVariable, type ) ) .collect( Collectors.toSet() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedExecutable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedExecutable.java index f7d6b0c63f..1f8e989cd3 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedExecutable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedExecutable.java @@ -104,7 +104,7 @@ public ConstrainedExecutable( CascadingMetaDataBuilder cascadingMetaDataBuilder) { super( source, - callable.isConstructor() ? ConstrainedElementKind.CONSTRUCTOR : ConstrainedElementKind.METHOD, + callable.getConstrainedElementKind(), returnValueConstraints, typeArgumentConstraints, cascadingMetaDataBuilder diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/Callable.java b/engine/src/main/java/org/hibernate/validator/internal/properties/Callable.java index b25586c4b1..9095262992 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/Callable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/Callable.java @@ -8,6 +8,7 @@ import java.lang.reflect.Type; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; @@ -28,7 +29,7 @@ public interface Callable extends Constrainable { boolean isPrivate(); - boolean isConstructor(); + ConstrainedElementKind getConstrainedElementKind(); String getSignature(); diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java index d7285fcb41..3622c6db42 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java @@ -13,6 +13,7 @@ import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; @@ -30,6 +31,7 @@ public class JavaBeanExecutable implements Callable { private final boolean hasParameters; private final boolean hasReturnValue; private final Type type; + private final ConstrainedElementKind kind; JavaBeanExecutable(Executable executable) { this.executable = executable; @@ -38,6 +40,7 @@ public class JavaBeanExecutable implements Callable { this.typeForValidatorResolution = ReflectionHelper.boxedType( type ); this.hasParameters = executable.getParameterTypes().length > 0; this.hasReturnValue = hasReturnValue( executable ); + this.kind = executable instanceof Constructor ? ConstrainedElementKind.CONSTRUCTOR : ConstrainedElementKind.METHOD; } public static JavaBeanExecutable of(Executable executable) { @@ -100,8 +103,8 @@ public boolean isPrivate() { } @Override - public boolean isConstructor() { - return executable instanceof Constructor; + public ConstrainedElementKind getConstrainedElementKind() { + return kind; } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassConstraintTypeStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassConstraintTypeStaxBuilder.java index c75a851b14..1d059154eb 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassConstraintTypeStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassConstraintTypeStaxBuilder.java @@ -24,6 +24,7 @@ import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedType; import org.hibernate.validator.internal.util.TypeResolutionHelper; @@ -103,7 +104,7 @@ ConstrainedType build(Class beanClass) { ConstraintLocation constraintLocation = ConstraintLocation.forClass( beanClass ); Set> metaConstraints = constraintTypeStaxBuilders.stream() - .map( builder -> builder.build( constraintLocation, java.lang.annotation.ElementType.TYPE, null ) ) + .map( builder -> builder.build( constraintLocation, ConstraintLocationKind.TYPE, null ) ) .collect( Collectors.toSet() ); // ignore annotation diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java index 1126e715ab..bb0a350084 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java @@ -22,6 +22,7 @@ import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; @@ -74,7 +75,7 @@ ConstrainedField build(Class beanClass, List alreadyProcessedFieldNam ConstraintLocation constraintLocation = ConstraintLocation.forField( javaBeanField ); Set> metaConstraints = constraintTypeStaxBuilders.stream() - .map( builder -> builder.build( constraintLocation, java.lang.annotation.ElementType.FIELD, null ) ) + .map( builder -> builder.build( constraintLocation, ConstraintLocationKind.FIELD, null ) ) .collect( Collectors.toSet() ); ContainerElementTypeConfiguration containerElementTypeConfiguration = getContainerElementTypeConfiguration( diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java index fbe4766597..11bc792d33 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java @@ -23,6 +23,7 @@ import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; @@ -76,7 +77,7 @@ ConstrainedExecutable build(Class beanClass, List alreadyProcessedGet ConstraintLocation constraintLocation = ConstraintLocation.forGetter( javaBeanGetter ); Set> metaConstraints = constraintTypeStaxBuilders.stream() - .map( builder -> builder.build( constraintLocation, java.lang.annotation.ElementType.METHOD, null ) ) + .map( builder -> builder.build( constraintLocation, ConstraintLocationKind.METHOD, null ) ) .collect( Collectors.toSet() ); ContainerElementTypeConfiguration containerElementTypeConfiguration = getContainerElementTypeConfiguration( diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java index 5344231f1c..3d4eb1a090 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java @@ -20,6 +20,7 @@ import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; import org.hibernate.validator.internal.properties.Callable; @@ -73,7 +74,7 @@ ConstrainedParameter build(Callable callable, int index) { Type type = callable.getTypeOfParameter( index ); Set> metaConstraints = constraintTypeStaxBuilders.stream() - .map( builder -> builder.build( constraintLocation, java.lang.annotation.ElementType.PARAMETER, null ) ) + .map( builder -> builder.build( constraintLocation, ConstraintLocationKind.PARAMETER, null ) ) .collect( Collectors.toSet() ); ContainerElementTypeConfiguration containerElementTypeConfiguration = getContainerElementTypeConfiguration( type, constraintLocation ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintTypeStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintTypeStaxBuilder.java index 3292210ac0..10557668cb 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintTypeStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintTypeStaxBuilder.java @@ -35,6 +35,7 @@ import org.hibernate.validator.internal.metadata.core.MetaConstraints; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.annotation.AnnotationDescriptor; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; @@ -112,7 +113,7 @@ protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLS } @SuppressWarnings("unchecked") - MetaConstraint build(ConstraintLocation constraintLocation, java.lang.annotation.ElementType type, ConstraintDescriptorImpl.ConstraintType constraintType) { + MetaConstraint build(ConstraintLocation constraintLocation, ConstraintLocationKind kind, ConstraintDescriptorImpl.ConstraintType constraintType) { String defaultPackage = defaultPackageStaxBuilder.build().orElse( "" ); Class annotationClass; @@ -149,7 +150,7 @@ MetaConstraint build(ConstraintLocation constraintLoca // we set initially ConstraintOrigin.DEFINED_LOCALLY for all xml configured constraints // later we will make copies of this constraint descriptor when needed and adjust the ConstraintOrigin ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl<>( - constraintHelper, constraintLocation.getConstrainable(), annotationDescriptor, type, constraintType + constraintHelper, constraintLocation.getConstrainable(), annotationDescriptor, kind, constraintType ); return MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor, constraintLocation ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypeStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypeStaxBuilder.java index 1c24591a22..eeb2d16a6d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypeStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypeStaxBuilder.java @@ -163,7 +163,7 @@ public ContainerElementTypeConfiguration build(Set con .map( builder -> builder.build( containerElementTypeConstraintLocation, - java.lang.annotation.ElementType.TYPE_USE, + ConstraintLocation.ConstraintLocationKind.TYPE_USE, null ) ), diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java index ce40f9625f..c92463cf95 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java @@ -23,6 +23,7 @@ import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.xml.AbstractStaxBuilder; @@ -88,7 +89,7 @@ Set> build(Callable callable) { ConstraintLocation constraintLocation = ConstraintLocation.forCrossParameter( callable ); Set> crossParameterConstraints = constraintTypeStaxBuilders.stream() - .map( builder -> builder.build( constraintLocation, java.lang.annotation.ElementType.METHOD, ConstraintType.CROSS_PARAMETER ) ) + .map( builder -> builder.build( constraintLocation, ConstraintLocationKind.METHOD, ConstraintType.CROSS_PARAMETER ) ) .collect( Collectors.toSet() ); // ignore annotations diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java index b9458a5fdf..c3e2eb0136 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java @@ -6,7 +6,6 @@ */ package org.hibernate.validator.internal.xml.mapping; -import java.lang.annotation.ElementType; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -20,6 +19,8 @@ import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.xml.mapping.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; @@ -56,7 +57,7 @@ CascadingMetaDataBuilder build( ConstraintLocation constraintLocation = ConstraintLocation.forReturnValue( callable ); returnValueConstraints.addAll( constraintTypeStaxBuilders.stream() - .map( builder -> builder.build( constraintLocation, callable.isConstructor() ? ElementType.CONSTRUCTOR : ElementType.METHOD, ConstraintDescriptorImpl.ConstraintType.GENERIC ) ) + .map( builder -> builder.build( constraintLocation, callable.getConstrainedElementKind() == ConstrainedElementKind.CONSTRUCTOR ? ConstraintLocationKind.CONSTRUCTOR : ConstraintLocationKind.METHOD, ConstraintDescriptorImpl.ConstraintType.GENERIC ) ) .collect( Collectors.toSet() ) ); ContainerElementTypeConfiguration containerElementTypeConfiguration = getContainerElementTypeConfiguration( callable.getType(), constraintLocation ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java index b9515ff476..c869c51c9b 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java @@ -18,6 +18,7 @@ import org.hibernate.validator.internal.engine.MessageInterpolatorContext; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; import org.hibernate.validator.testutil.TestForIssue; @@ -44,7 +45,7 @@ public void setUp() { new ConstraintHelper(), null, notNullAnnotationDescriptorBuilder.build(), - java.lang.annotation.ElementType.FIELD + ConstraintLocationKind.FIELD ); ConstraintAnnotationDescriptor.Builder sizeAnnotationDescriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( Size.class ); @@ -52,7 +53,7 @@ public void setUp() { new ConstraintHelper(), null, sizeAnnotationDescriptorBuilder.build(), - java.lang.annotation.ElementType.FIELD + ConstraintLocationKind.FIELD ); interpolatorUnderTest = new ResourceBundleMessageInterpolator(); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java index 889120f615..29bdf5ff3a 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java @@ -27,6 +27,7 @@ import org.hibernate.validator.internal.engine.MessageInterpolatorContext; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; @@ -54,7 +55,7 @@ public void setUp() { new ConstraintHelper(), null, descriptorBuilder.build(), - java.lang.annotation.ElementType.FIELD + ConstraintLocationKind.FIELD ); ConstraintAnnotationDescriptor.Builder sizeAnnotationDescriptorBuilder = new ConstraintAnnotationDescriptor.Builder( Size.class ); @@ -62,7 +63,7 @@ public void setUp() { new ConstraintHelper(), null, sizeAnnotationDescriptorBuilder.build(), - java.lang.annotation.ElementType.FIELD + ConstraintLocationKind.FIELD ); } @@ -216,7 +217,7 @@ public void testRecursiveMessageInterpolation() { new ConstraintHelper(), null, descriptorBuilder.build(), - java.lang.annotation.ElementType.FIELD + ConstraintLocationKind.FIELD ); interpolator = new ResourceBundleMessageInterpolator( @@ -245,7 +246,7 @@ public void testCorrectMessageInterpolationIfParameterCannotBeReplaced() { new ConstraintHelper(), null, maxDescriptor, - java.lang.annotation.ElementType.FIELD + ConstraintLocationKind.FIELD ); interpolator = new ResourceBundleMessageInterpolator( diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java index 16fc4e3062..436f7e8b3a 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java @@ -6,7 +6,6 @@ */ package org.hibernate.validator.test.internal.metadata.core; -import static java.lang.annotation.ElementType.METHOD; import static org.testng.Assert.assertEquals; import java.lang.reflect.Method; @@ -20,10 +19,12 @@ import org.hibernate.validator.internal.metadata.core.MetaConstraints; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.testutil.TestForIssue; + import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -50,14 +51,14 @@ public void setUp() throws Exception { @TestForIssue(jiraKey = "HV-930") public void two_meta_constraints_for_the_same_constraint_should_be_equal() throws Exception { ConstraintDescriptorImpl constraintDescriptor1 = new ConstraintDescriptorImpl<>( - constraintHelper, JavaBeanExecutable.of( barMethod ), constraintAnnotationDescriptor, METHOD + constraintHelper, JavaBeanExecutable.of( barMethod ), constraintAnnotationDescriptor, ConstraintLocationKind.METHOD ); ConstraintLocation location1 = ConstraintLocation.forClass( Foo.class ); MetaConstraint metaConstraint1 = MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor1, location1 ); ConstraintDescriptorImpl constraintDescriptor2 = new ConstraintDescriptorImpl<>( - constraintHelper, JavaBeanExecutable.of( barMethod ), constraintAnnotationDescriptor, METHOD + constraintHelper, JavaBeanExecutable.of( barMethod ), constraintAnnotationDescriptor, ConstraintLocationKind.METHOD ); ConstraintLocation location2 = ConstraintLocation.forClass( Foo.class ); MetaConstraint metaConstraint2 = MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor2, location2 ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java index 95d3561fd9..47dc49bc44 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java @@ -12,7 +12,6 @@ import static org.hibernate.validator.internal.util.CollectionHelper.newHashMap; import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.Target; @@ -33,6 +32,7 @@ import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider; import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; @@ -43,6 +43,7 @@ import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.testutil.TestForIssue; + import org.joda.time.DateMidnight; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -79,7 +80,7 @@ public void testGetConstructorMetaData() throws Exception { MetaConstraint constraint = constructor.getConstraints().iterator().next(); assertThat( constraint.getDescriptor().getAnnotation().annotationType() ).isEqualTo( NotNull.class ); - assertThat( constraint.getElementType() ).isEqualTo( ElementType.CONSTRUCTOR ); + assertThat( constraint.getConstraintLocationKind() ).isEqualTo( ConstraintLocationKind.CONSTRUCTOR ); } @Test From 7ef6fcbabd79c1301d9ac93e9eb9956fc363f58e Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 1 Jun 2018 19:49:07 +0200 Subject: [PATCH 059/393] HV-1623 More abstraction work around executables --- ...xecutableConstraintMappingContextImpl.java | 2 +- ...ParameterConstraintMappingContextImpl.java | 4 +- .../TypeConstraintMappingContextImpl.java | 18 +- .../location/ParameterConstraintLocation.java | 2 +- .../provider/AnnotationMetaDataProvider.java | 190 ++++++++---------- .../metadata/raw/ConstrainedExecutable.java | 4 +- .../internal/properties/Callable.java | 9 +- .../JavaBeanAnnotatedConstrainable.java | 16 ++ .../javabean/JavaBeanAnnotatedElement.java | 34 ++++ .../javabean/JavaBeanConstructor.java | 32 +++ .../javabean/JavaBeanExecutable.java | 138 ++++++++----- .../properties/javabean/JavaBeanField.java | 30 ++- .../properties/javabean/JavaBeanGetter.java | 17 +- .../properties/javabean/JavaBeanMethod.java | 32 +++ .../javabean/JavaBeanParameter.java | 75 +++++++ .../ConstrainedConstructorStaxBuilder.java | 16 +- .../mapping/ConstrainedMethodStaxBuilder.java | 2 +- .../ConstrainedParameterStaxBuilder.java | 2 +- 18 files changed, 421 insertions(+), 202 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanAnnotatedConstrainable.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanAnnotatedElement.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanConstructor.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanMethod.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanParameter.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ExecutableConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ExecutableConstraintMappingContextImpl.java index 9cb9d826a2..503c284637 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ExecutableConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ExecutableConstraintMappingContextImpl.java @@ -130,7 +130,7 @@ private List getParameters(ConstraintHelper constraintHelp new ConstrainedParameter( ConfigurationSource.API, callable, - callable.getTypeOfParameter( i ), + callable.getParameterGenericType( i ), i ) ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ParameterConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ParameterConstraintMappingContextImpl.java index 1f8bc55dc5..314b23f1c7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ParameterConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ParameterConstraintMappingContextImpl.java @@ -40,7 +40,7 @@ final class ParameterConstraintMappingContextImpl ParameterConstraintMappingContextImpl(ExecutableConstraintMappingContextImpl executableContext, int parameterIndex) { super( executableContext.getTypeContext().getConstraintMapping(), - executableContext.callable.getGenericParameterTypes()[parameterIndex] + executableContext.callable.getParameterGenericType( parameterIndex ) ); this.executableContext = executableContext; @@ -121,7 +121,7 @@ public ContainerElementConstraintMappingContext containerElementType(int index, public ConstrainedParameter build(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { - Type parameterType = executableContext.getCallable().getTypeOfParameter( parameterIndex ); + Type parameterType = executableContext.getCallable().getParameterGenericType( parameterIndex ); return new ConstrainedParameter( ConfigurationSource.API, diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java index 7bc3b920ac..13fa7bd741 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java @@ -33,9 +33,9 @@ import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedType; -import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.javabean.JavaBeanConstructor; import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; @@ -154,17 +154,17 @@ public MethodConstraintMappingContext method(String name, Class... parameterT throw LOG.getBeanDoesNotContainMethodException( beanClass, name, parameterTypes ); } - Callable callable = JavaBeanExecutable.of( method ); + JavaBeanExecutable javaBeanExecutable = JavaBeanExecutable.of( method ); - if ( configuredMembers.contains( callable ) ) { + if ( configuredMembers.contains( javaBeanExecutable ) ) { throw LOG.getMethodHasAlreadyBeenConfiguredViaProgrammaticApiException( beanClass, ExecutableHelper.getExecutableAsString( name, parameterTypes ) ); } - MethodConstraintMappingContextImpl context = new MethodConstraintMappingContextImpl( this, callable ); - configuredMembers.add( callable ); + MethodConstraintMappingContextImpl context = new MethodConstraintMappingContextImpl( this, javaBeanExecutable ); + configuredMembers.add( javaBeanExecutable ); executableContexts.add( context ); return context; @@ -181,9 +181,9 @@ public ConstructorConstraintMappingContext constructor(Class... parameterType ); } - Callable callable = JavaBeanExecutable.of( constructor ); + JavaBeanConstructor javaBeanConstructor = new JavaBeanConstructor( constructor ); - if ( configuredMembers.contains( callable ) ) { + if ( configuredMembers.contains( javaBeanConstructor ) ) { throw LOG.getConstructorHasAlreadyBeConfiguredViaProgrammaticApiException( beanClass, ExecutableHelper.getExecutableAsString( beanClass.getSimpleName(), parameterTypes ) @@ -192,9 +192,9 @@ public ConstructorConstraintMappingContext constructor(Class... parameterType ConstructorConstraintMappingContextImpl context = new ConstructorConstraintMappingContextImpl( this, - callable + javaBeanConstructor ); - configuredMembers.add( callable ); + configuredMembers.add( javaBeanConstructor ); executableContexts.add( context ); return context; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java index c51b9308aa..f7ee26cac0 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java @@ -29,7 +29,7 @@ public class ParameterConstraintLocation implements ConstraintLocation { public ParameterConstraintLocation(Callable callable, int index) { this.callable = callable; this.index = index; - this.typeForValidatorResolution = ReflectionHelper.boxedType( callable.getTypeOfParameter( index ) ); + this.typeForValidatorResolution = ReflectionHelper.boxedType( callable.getParameterGenericType( index ) ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java index cfa173174e..ad4b3d408f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java @@ -13,18 +13,13 @@ import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandles; -import java.lang.reflect.AccessibleObject; import java.lang.reflect.AnnotatedArrayType; -import java.lang.reflect.AnnotatedElement; import java.lang.reflect.AnnotatedParameterizedType; import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Field; -import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.lang.reflect.Parameter; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; @@ -66,8 +61,11 @@ import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.javabean.JavaBeanAnnotatedConstrainable; +import org.hibernate.validator.internal.properties.javabean.JavaBeanAnnotatedElement; import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; +import org.hibernate.validator.internal.properties.javabean.JavaBeanParameter; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; @@ -227,19 +225,19 @@ private Set getFieldMetaData(Class beanClass) { continue; } - propertyMetaData.add( findPropertyMetaData( field, javaBeanField ) ); + propertyMetaData.add( findPropertyMetaData( javaBeanField ) ); } return propertyMetaData; } - private ConstrainedField findPropertyMetaData(Field field, JavaBeanField javaBeanField) { + private ConstrainedField findPropertyMetaData(JavaBeanField javaBeanField) { Set> constraints = convertToMetaConstraints( - findConstraints( field, ConstraintLocationKind.FIELD, javaBeanField ), + findConstraints( javaBeanField, ConstraintLocationKind.FIELD ), javaBeanField ); - CascadingMetaDataBuilder cascadingMetaDataBuilder = findCascadingMetaData( field ); - Set> typeArgumentsConstraints = findTypeAnnotationConstraints( field, javaBeanField ); + CascadingMetaDataBuilder cascadingMetaDataBuilder = findCascadingMetaData( javaBeanField ); + Set> typeArgumentsConstraints = findTypeAnnotationConstraints( javaBeanField ); return new ConstrainedField( ConfigurationSource.ANNOTATION, @@ -302,25 +300,24 @@ private Set getMetaData(Executable[] executableElements) * given element. */ private ConstrainedExecutable findExecutableMetaData(Executable executable) { - Callable callable = JavaBeanExecutable.of( executable ); - List parameterConstraints = getParameterMetaData( executable, callable ); + JavaBeanExecutable javaBeanExecutable = JavaBeanExecutable.of( executable ); + List parameterConstraints = getParameterMetaData( javaBeanExecutable ); Map>> executableConstraints = findConstraints( - executable, - callable.getConstrainedElementKind() == ConstrainedElement.ConstrainedElementKind.CONSTRUCTOR + javaBeanExecutable, + javaBeanExecutable.getConstrainedElementKind() == ConstrainedElement.ConstrainedElementKind.CONSTRUCTOR ? ConstraintLocationKind.CONSTRUCTOR - : ConstraintLocationKind.METHOD, - callable + : ConstraintLocationKind.METHOD ).stream().collect( Collectors.groupingBy( ConstraintDescriptorImpl::getConstraintType ) ); Set> crossParameterConstraints; - if ( annotationProcessingOptions.areCrossParameterConstraintsIgnoredFor( callable ) ) { + if ( annotationProcessingOptions.areCrossParameterConstraintsIgnoredFor( javaBeanExecutable ) ) { crossParameterConstraints = Collections.emptySet(); } else { crossParameterConstraints = convertToMetaConstraints( executableConstraints.get( ConstraintType.CROSS_PARAMETER ), - callable + javaBeanExecutable ); } @@ -328,25 +325,23 @@ private ConstrainedExecutable findExecutableMetaData(Executable executable) { Set> typeArgumentsConstraints; CascadingMetaDataBuilder cascadingMetaDataBuilder; - if ( annotationProcessingOptions.areReturnValueConstraintsIgnoredFor( callable ) ) { + if ( annotationProcessingOptions.areReturnValueConstraintsIgnoredFor( javaBeanExecutable ) ) { returnValueConstraints = Collections.emptySet(); typeArgumentsConstraints = Collections.emptySet(); cascadingMetaDataBuilder = CascadingMetaDataBuilder.nonCascading(); } else { - AnnotatedType annotatedReturnType = executable.getAnnotatedReturnType(); - - typeArgumentsConstraints = findTypeAnnotationConstraints( executable, callable, annotatedReturnType ); + typeArgumentsConstraints = findTypeAnnotationConstraints( javaBeanExecutable ); returnValueConstraints = convertToMetaConstraints( executableConstraints.get( ConstraintType.GENERIC ), - callable + javaBeanExecutable ); - cascadingMetaDataBuilder = findCascadingMetaData( executable, annotatedReturnType ); + cascadingMetaDataBuilder = findCascadingMetaData( javaBeanExecutable ); } return new ConstrainedExecutable( ConfigurationSource.ANNOTATION, - callable, + javaBeanExecutable, parameterConstraints, crossParameterConstraints, returnValueConstraints, @@ -377,25 +372,24 @@ private Set> convertToMetaConstraints(List getParameterMetaData(Executable executable, Callable callable) { - if ( executable.getParameterCount() == 0 ) { + private List getParameterMetaData(JavaBeanExecutable javaBeanExecutable) { + if ( !javaBeanExecutable.hasParameters() ) { return Collections.emptyList(); } - Parameter[] parameters = executable.getParameters(); + List parameters = javaBeanExecutable.getParameters(); - List metaData = new ArrayList<>( parameters.length ); + List metaData = new ArrayList<>( parameters.size() ); int i = 0; - for ( Parameter parameter : parameters ) { + for ( JavaBeanParameter parameter : parameters ) { Annotation[] parameterAnnotations; try { - parameterAnnotations = parameter.getAnnotations(); + parameterAnnotations = parameter.getDeclaredAnnotations(); } catch (ArrayIndexOutOfBoundsException ex) { LOG.warn( MESSAGES.constraintOnConstructorOfNonStaticInnerClass(), ex ); @@ -404,13 +398,12 @@ private List getParameterMetaData(Executable executable, C Set> parameterConstraints = newHashSet(); - if ( annotationProcessingOptions.areParameterConstraintsIgnoredFor( callable, i ) ) { - Type type = ReflectionHelper.typeOf( executable, i ); + if ( annotationProcessingOptions.areParameterConstraintsIgnoredFor( javaBeanExecutable, i ) ) { metaData.add( new ConstrainedParameter( ConfigurationSource.ANNOTATION, - callable, - type, + javaBeanExecutable, + parameter.getGenericType(), i, parameterConstraints, Collections.emptySet(), @@ -421,12 +414,12 @@ private List getParameterMetaData(Executable executable, C continue; } - ConstraintLocation location = ConstraintLocation.forParameter( callable, i ); + ConstraintLocation location = ConstraintLocation.forParameter( javaBeanExecutable, i ); for ( Annotation parameterAnnotation : parameterAnnotations ) { // collect constraints if this annotation is a constraint annotation List> constraints = findConstraintAnnotations( - callable, parameterAnnotation, ConstraintLocationKind.PARAMETER + javaBeanExecutable, parameterAnnotation, ConstraintLocationKind.PARAMETER ); for ( ConstraintDescriptorImpl constraintDescriptorImpl : constraints ) { parameterConstraints.add( @@ -435,16 +428,14 @@ private List getParameterMetaData(Executable executable, C } } - AnnotatedType parameterAnnotatedType = parameter.getAnnotatedType(); - - Set> typeArgumentsConstraints = findTypeAnnotationConstraintsForExecutableParameter( executable, callable, i, parameterAnnotatedType ); - CascadingMetaDataBuilder cascadingMetaData = findCascadingMetaData( executable, parameters, i, parameterAnnotatedType ); + Set> typeArgumentsConstraints = findTypeAnnotationConstraintsForExecutableParameter( parameter ); + CascadingMetaDataBuilder cascadingMetaData = findCascadingMetaData( parameter ); metaData.add( new ConstrainedParameter( ConfigurationSource.ANNOTATION, - callable, - ReflectionHelper.typeOf( executable, i ), + javaBeanExecutable, + parameter.getGenericType(), i, parameterConstraints, typeArgumentsConstraints, @@ -461,14 +452,14 @@ private List getParameterMetaData(Executable executable, C * Finds all constraint annotations defined for the given member and returns them in a list of * constraint descriptors. * - * @param member The member to check for constraints annotations. + * @param constrainable The constrainable to check for constraint annotations. * @param type The element type the constraint/annotation is placed on. * * @return A list of constraint descriptors for all constraint specified for the given member. */ - private List> findConstraints(Member member, ConstraintLocationKind type, Constrainable constrainable) { + private List> findConstraints(JavaBeanAnnotatedConstrainable constrainable, ConstraintLocationKind type) { List> metaData = newArrayList(); - for ( Annotation annotation : ( (AccessibleObject) member ).getDeclaredAnnotations() ) { + for ( Annotation annotation : constrainable.getDeclaredAnnotations() ) { metaData.addAll( findConstraintAnnotations( constrainable, annotation, type ) ); } @@ -528,10 +519,10 @@ else if ( constraintHelper.isMultiValueConstraint( annotationType ) ) { .collect( Collectors.toList() ); } - private Map, Class> getGroupConversions(AnnotatedElement annotatedElement) { + private Map, Class> getGroupConversions(AnnotatedType annotatedType) { return getGroupConversions( - annotatedElement.getAnnotation( ConvertGroup.class ), - annotatedElement.getAnnotation( ConvertGroup.List.class ) + annotatedType.getAnnotation( ConvertGroup.class ), + annotatedType.getAnnotation( ConvertGroup.List.class ) ); } @@ -585,35 +576,31 @@ private T run(PrivilegedAction action) { /** * Finds type arguments constraints for fields. */ - protected Set> findTypeAnnotationConstraints(Field field, Property property) { + protected Set> findTypeAnnotationConstraints(JavaBeanField javaBeanField) { return findTypeArgumentsConstraints( - property, - new TypeArgumentFieldLocation( field ), - field.getAnnotatedType() + javaBeanField, + new TypeArgumentFieldLocation( javaBeanField ), + javaBeanField.getAnnotatedType() ); } /** * Finds type arguments constraints for method return values. */ - protected Set> findTypeAnnotationConstraints(Executable executable, Callable callable, AnnotatedType annotatedReturnType) { + protected Set> findTypeAnnotationConstraints(JavaBeanExecutable javaBeanExecutable) { return findTypeArgumentsConstraints( - callable, - new TypeArgumentReturnValueLocation( executable ), - annotatedReturnType + javaBeanExecutable, + new TypeArgumentReturnValueLocation( javaBeanExecutable ), + javaBeanExecutable.getAnnotatedType() ); } - private CascadingMetaDataBuilder findCascadingMetaData(Executable executable, Parameter[] parameters, int i, AnnotatedType parameterAnnotatedType) { - Parameter parameter = parameters[i]; - TypeVariable[] typeParameters = parameter.getType().getTypeParameters(); - - Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaData = getTypeParametersCascadingMetadata( parameterAnnotatedType, - typeParameters ); + private CascadingMetaDataBuilder findCascadingMetaData(JavaBeanParameter javaBeanParameter) { + Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaData = getTypeParametersCascadingMetadata( javaBeanParameter.getAnnotatedType(), + javaBeanParameter.getTypeParameters() ); try { - return getCascadingMetaData( ReflectionHelper.typeOf( parameter.getDeclaringExecutable(), i ), - parameter, containerElementTypesCascadingMetaData ); + return getCascadingMetaData( javaBeanParameter, containerElementTypesCascadingMetaData ); } catch (ArrayIndexOutOfBoundsException ex) { LOG.warn( MESSAGES.constraintOnConstructorOfNonStaticInnerClass(), ex ); @@ -621,29 +608,19 @@ private CascadingMetaDataBuilder findCascadingMetaData(Executable executable, Pa } } - private CascadingMetaDataBuilder findCascadingMetaData(Field field) { - TypeVariable[] typeParameters = field.getType().getTypeParameters(); - AnnotatedType annotatedType = field.getAnnotatedType(); - - Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaData = getTypeParametersCascadingMetadata( annotatedType, typeParameters ); + private CascadingMetaDataBuilder findCascadingMetaData(JavaBeanField javaBeanField) { + Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaData = getTypeParametersCascadingMetadata( + javaBeanField.getAnnotatedType(), + javaBeanField.getTypeParameters() ); - return getCascadingMetaData( ReflectionHelper.typeOf( field ), field, containerElementTypesCascadingMetaData ); + return getCascadingMetaData( javaBeanField, containerElementTypesCascadingMetaData ); } - private CascadingMetaDataBuilder findCascadingMetaData(Executable executable, AnnotatedType annotatedReturnType) { - TypeVariable[] typeParameters; - - if ( executable instanceof Method ) { - typeParameters = ( (Method) executable ).getReturnType().getTypeParameters(); - } - else { - typeParameters = ( (Constructor) executable ).getDeclaringClass().getTypeParameters(); - } - - Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaData = getTypeParametersCascadingMetadata( annotatedReturnType, - typeParameters ); + private CascadingMetaDataBuilder findCascadingMetaData(JavaBeanExecutable javaBeanExecutable) { + Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaData = getTypeParametersCascadingMetadata( javaBeanExecutable.getAnnotatedType(), + javaBeanExecutable.getTypeParameters() ); - return getCascadingMetaData( ReflectionHelper.typeOf( executable ), executable, containerElementTypesCascadingMetaData ); + return getCascadingMetaData( javaBeanExecutable, containerElementTypesCascadingMetaData ); } private Map, CascadingMetaDataBuilder> getTypeParametersCascadingMetadata(AnnotatedType annotatedType, @@ -714,17 +691,16 @@ else if ( annotatedType instanceof AnnotatedParameterizedType ) { /** * Finds type arguments constraints for parameters. * - * @param executable the executable - * @param i the parameter index + * @param javaBeanParameter the parameter * * @return a set of type arguments constraints, or an empty set if no constrained type arguments are found */ - protected Set> findTypeAnnotationConstraintsForExecutableParameter(Executable executable, Callable callable, int i, AnnotatedType parameterAnnotatedType) { + protected Set> findTypeAnnotationConstraintsForExecutableParameter(JavaBeanParameter javaBeanParameter) { try { return findTypeArgumentsConstraints( - callable, - new TypeArgumentExecutableParameterLocation( executable, i ), - parameterAnnotatedType + javaBeanParameter.getExecutable(), + new TypeArgumentExecutableParameterLocation( javaBeanParameter.getExecutable(), javaBeanParameter.getIndex() ), + javaBeanParameter.getAnnotatedType() ); } catch (ArrayIndexOutOfBoundsException ex) { @@ -803,10 +779,10 @@ private MetaConstraint createTypeArgumentMetaConstrain return MetaConstraints.create( typeResolutionHelper, valueExtractorManager, descriptor, constraintLocation ); } - private CascadingMetaDataBuilder getCascadingMetaData(Type type, AnnotatedElement annotatedElement, + private CascadingMetaDataBuilder getCascadingMetaData(JavaBeanAnnotatedElement annotatedElement, Map, CascadingMetaDataBuilder> containerElementTypesCascadingMetaData) { - return CascadingMetaDataBuilder.annotatedObject( type, annotatedElement.isAnnotationPresent( Valid.class ), containerElementTypesCascadingMetaData, - getGroupConversions( annotatedElement ) ); + return CascadingMetaDataBuilder.annotatedObject( annotatedElement.getType(), annotatedElement.isAnnotationPresent( Valid.class ), + containerElementTypesCascadingMetaData, getGroupConversions( annotatedElement.getAnnotatedType() ) ); } /** @@ -821,44 +797,44 @@ private interface TypeArgumentLocation { } private static class TypeArgumentExecutableParameterLocation implements TypeArgumentLocation { - private final Executable executable; + private final JavaBeanExecutable javaBeanExecutable; private final int index; - private TypeArgumentExecutableParameterLocation(Executable executable, int index) { - this.executable = executable; + private TypeArgumentExecutableParameterLocation(JavaBeanExecutable javaBeanExecutable, int index) { + this.javaBeanExecutable = javaBeanExecutable; this.index = index; } @Override public ConstraintLocation toConstraintLocation() { - return ConstraintLocation.forParameter( JavaBeanExecutable.of( executable ), index ); + return ConstraintLocation.forParameter( javaBeanExecutable, index ); } } private static class TypeArgumentFieldLocation implements TypeArgumentLocation { - private final Field field; + private final JavaBeanField javaBeanField; - private TypeArgumentFieldLocation(Field field) { - this.field = field; + private TypeArgumentFieldLocation(JavaBeanField javaBeanField) { + this.javaBeanField = javaBeanField; } @Override public ConstraintLocation toConstraintLocation() { - return ConstraintLocation.forField( new JavaBeanField( field ) ); + return ConstraintLocation.forField( javaBeanField ); } } private static class TypeArgumentReturnValueLocation implements TypeArgumentLocation { - private final Executable executable; + private final JavaBeanExecutable javaBeanExecutable; - private TypeArgumentReturnValueLocation(Executable executable) { - this.executable = executable; + private TypeArgumentReturnValueLocation(JavaBeanExecutable javaBeanExecutable) { + this.javaBeanExecutable = javaBeanExecutable; } @Override public ConstraintLocation toConstraintLocation() { - return ConstraintLocation.forReturnValue( JavaBeanExecutable.of( executable ) ); + return ConstraintLocation.forReturnValue( javaBeanExecutable ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedExecutable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedExecutable.java index 1f8e989cd3..0c42157833 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedExecutable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedExecutable.java @@ -112,10 +112,10 @@ public ConstrainedExecutable( this.callable = callable; - if ( parameterMetaData.size() != callable.getParameterTypes().length ) { + if ( parameterMetaData.size() != callable.getParameterCount() ) { throw LOG.getInvalidLengthOfParameterMetaDataListException( callable, - callable.getParameterTypes().length, + callable.getParameterCount(), parameterMetaData.size() ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/Callable.java b/engine/src/main/java/org/hibernate/validator/internal/properties/Callable.java index 9095262992..2e72191a1d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/Callable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/Callable.java @@ -14,6 +14,7 @@ /** * @author Marko Bekhta + * @author Guillaume Smet */ public interface Callable extends Constrainable { @@ -21,9 +22,11 @@ public interface Callable extends Constrainable { boolean hasParameters(); - Class[] getParameterTypes(); + int getParameterCount(); + + Type getParameterGenericType(int index); - Type[] getGenericParameterTypes(); + Class[] getParameterTypes(); String getParameterName(ExecutableParameterNameProvider parameterNameProvider, int parameterIndex); @@ -33,8 +36,6 @@ public interface Callable extends Constrainable { String getSignature(); - Type getTypeOfParameter(int parameterIndex); - boolean overrides(ExecutableHelper executableHelper, Callable superTypeMethod); boolean isResolvedToSameMethodInHierarchy(ExecutableHelper executableHelper, Class mainSubType, Callable superTypeMethod); diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanAnnotatedConstrainable.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanAnnotatedConstrainable.java new file mode 100644 index 0000000000..55589a6c4a --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanAnnotatedConstrainable.java @@ -0,0 +1,16 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.properties.javabean; + +import org.hibernate.validator.internal.properties.Constrainable; + +/** + * @author Guillaume Smet + */ +public interface JavaBeanAnnotatedConstrainable extends Constrainable, JavaBeanAnnotatedElement { + +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanAnnotatedElement.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanAnnotatedElement.java new file mode 100644 index 0000000000..11a99d3eab --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanAnnotatedElement.java @@ -0,0 +1,34 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.properties.javabean; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; + +/** + * @author Guillaume Smet + */ +public interface JavaBeanAnnotatedElement { + + Type getType(); + + AnnotatedType getAnnotatedType(); + + Annotation[] getDeclaredAnnotations(); + + Type getGenericType(); + + TypeVariable[] getTypeParameters(); + + A getAnnotation(Class annotationClass); + + default boolean isAnnotationPresent(Class annotationClass) { + return getAnnotation( annotationClass ) != null; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanConstructor.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanConstructor.java new file mode 100644 index 0000000000..2ffbce8677 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanConstructor.java @@ -0,0 +1,32 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.properties.javabean; + +import java.lang.reflect.Constructor; +import java.lang.reflect.TypeVariable; + +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; + +/** + * @author Guillaume Smet + */ +public class JavaBeanConstructor extends JavaBeanExecutable> { + + public JavaBeanConstructor(Constructor executable) { + super( executable, true ); + } + + @Override + public ConstrainedElementKind getConstrainedElementKind() { + return ConstrainedElementKind.CONSTRUCTOR; + } + + @Override + public TypeVariable[] getTypeParameters() { + return executable.getDeclaringClass().getTypeParameters(); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java index 3622c6db42..1d69c8e629 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java @@ -6,15 +6,21 @@ */ package org.hibernate.validator.internal.properties.javabean; +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedType; import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.lang.reflect.Parameter; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; -import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.ReflectionHelper; @@ -22,34 +28,52 @@ /** * @author Marko Bekhta + * @author Guillaume Smet */ -public class JavaBeanExecutable implements Callable { +public abstract class JavaBeanExecutable implements Callable, JavaBeanAnnotatedConstrainable { - protected final Executable executable; + protected final T executable; private final Type typeForValidatorResolution; private final String name; - private final boolean hasParameters; private final boolean hasReturnValue; private final Type type; - private final ConstrainedElementKind kind; + private final List parameters; - JavaBeanExecutable(Executable executable) { + JavaBeanExecutable(T executable, boolean hasReturnValue) { this.executable = executable; this.name = executable.getName(); this.type = ReflectionHelper.typeOf( executable ); this.typeForValidatorResolution = ReflectionHelper.boxedType( type ); - this.hasParameters = executable.getParameterTypes().length > 0; - this.hasReturnValue = hasReturnValue( executable ); - this.kind = executable instanceof Constructor ? ConstrainedElementKind.CONSTRUCTOR : ConstrainedElementKind.METHOD; + this.hasReturnValue = hasReturnValue; + + if ( executable.getParameterCount() > 0 ) { + List parameters = new ArrayList<>( executable.getParameterCount() ); + + Parameter[] parameterArray = executable.getParameters(); + Class[] parameterTypes = executable.getParameterTypes(); + Type[] genericParameterTypes = executable.getGenericParameterTypes(); + + for ( int i = 0; i < parameterArray.length; i++ ) { + parameters.add( new JavaBeanParameter( this, i, parameterArray[i], parameterTypes[i], + getParameterGenericType( parameterTypes, genericParameterTypes, i ) ) ); + } + this.parameters = CollectionHelper.toImmutableList( parameters ); + } + else { + this.parameters = Collections.emptyList(); + } } - public static JavaBeanExecutable of(Executable executable) { + public static JavaBeanExecutable of(Executable executable) { + if ( executable instanceof Constructor ) { + return new JavaBeanConstructor( (Constructor) executable ); + } + if ( ReflectionHelper.isGetterMethod( executable ) ) { return new JavaBeanGetter( (Method) executable ); } - else { - return new JavaBeanExecutable( executable ); - } + + return new JavaBeanMethod( (Method) executable ); } @Override @@ -59,7 +83,7 @@ public boolean hasReturnValue() { @Override public boolean hasParameters() { - return hasParameters; + return !parameters.isEmpty(); } @Override @@ -83,60 +107,67 @@ public Type getType() { } @Override - public Class[] getParameterTypes() { - return executable.getParameterTypes(); + public String getParameterName(ExecutableParameterNameProvider parameterNameProvider, int parameterIndex) { + return parameterNameProvider.getParameterNames( executable ).get( parameterIndex ); } @Override - public Type[] getGenericParameterTypes() { - return executable.getGenericParameterTypes(); + public boolean isPrivate() { + return Modifier.isPrivate( executable.getModifiers() ); } @Override - public String getParameterName(ExecutableParameterNameProvider parameterNameProvider, int parameterIndex) { - return parameterNameProvider.getParameterNames( executable ).get( parameterIndex ); + public String getSignature() { + return ExecutableHelper.getSignature( executable ); } @Override - public boolean isPrivate() { - return Modifier.isPrivate( executable.getModifiers() ); + public Annotation[] getDeclaredAnnotations() { + return executable.getDeclaredAnnotations(); } @Override - public ConstrainedElementKind getConstrainedElementKind() { - return kind; + public boolean overrides(ExecutableHelper executableHelper, Callable superTypeMethod) { + return executableHelper.overrides( ( (Method) this.executable ), ( (Method) ( (JavaBeanExecutable) superTypeMethod ).executable ) ); } @Override - public String getSignature() { - return ExecutableHelper.getSignature( executable ); + public boolean isResolvedToSameMethodInHierarchy(ExecutableHelper executableHelper, Class mainSubType, Callable superTypeMethod) { + return executableHelper.isResolvedToSameMethodInHierarchy( mainSubType, ( (Method) this.executable ), ( (Method) ( (JavaBeanExecutable) superTypeMethod ).executable ) ); } @Override - public Type getTypeOfParameter(int parameterIndex) { - Type[] genericParameterTypes = executable.getGenericParameterTypes(); + public Type getGenericType() { + return ReflectionHelper.typeOf( executable ); + } - // getGenericParameterTypes() doesn't return synthetic parameters; in this case fall back to getParameterTypes() - if ( parameterIndex >= genericParameterTypes.length ) { - genericParameterTypes = executable.getParameterTypes(); - } + @Override + public AnnotatedType getAnnotatedType() { + return executable.getAnnotatedReturnType(); + } - Type type = genericParameterTypes[parameterIndex]; + @Override + public A getAnnotation(Class annotationClass) { + return executable.getAnnotation( annotationClass ); + } - if ( type instanceof TypeVariable ) { - type = TypeHelper.getErasedType( type ); - } - return type; + public List getParameters() { + return parameters; } @Override - public boolean overrides(ExecutableHelper executableHelper, Callable superTypeMethod) { - return executableHelper.overrides( ( (Method) this.executable ), ( (Method) ( (JavaBeanExecutable) superTypeMethod ).executable ) ); + public Type getParameterGenericType(int index) { + return parameters.get( index ).getGenericType(); } @Override - public boolean isResolvedToSameMethodInHierarchy(ExecutableHelper executableHelper, Class mainSubType, Callable superTypeMethod) { - return executableHelper.isResolvedToSameMethodInHierarchy( mainSubType, ( (Method) this.executable ), ( (Method) ( (JavaBeanExecutable) superTypeMethod ).executable ) ); + public int getParameterCount() { + return parameters.size(); + } + + @Override + public Class[] getParameterTypes() { + return executable.getParameterTypes(); } @Override @@ -148,11 +179,8 @@ public boolean equals(Object o) { return false; } - JavaBeanExecutable that = (JavaBeanExecutable) o; + JavaBeanExecutable that = (JavaBeanExecutable) o; - if ( this.hasParameters != that.hasParameters ) { - return false; - } if ( this.hasReturnValue != that.hasReturnValue ) { return false; } @@ -173,7 +201,6 @@ public int hashCode() { int result = this.executable.hashCode(); result = 31 * result + this.typeForValidatorResolution.hashCode(); result = 31 * result + this.name.hashCode(); - result = 31 * result + ( this.hasParameters ? 1 : 0 ); result = 31 * result + ( this.hasReturnValue ? 1 : 0 ); result = 31 * result + this.type.hashCode(); return result; @@ -183,16 +210,25 @@ public int hashCode() { public String toString() { return ExecutableHelper.getExecutableAsString( getDeclaringClass().getSimpleName() + "#" + name, - getParameterTypes() + executable.getParameterTypes() ); } - private boolean hasReturnValue(Executable executable) { - if ( executable instanceof Constructor ) { - return true; + private static Type getParameterGenericType(Type[] parameterTypes, Type[] genericParameterTypes, int parameterIndex) { + // getGenericParameterTypes() doesn't return synthetic parameters; in this case fall back to getParameterTypes() + Type[] typesToConsider; + if ( parameterIndex >= genericParameterTypes.length ) { + typesToConsider = parameterTypes; } else { - return ( (Method) executable ).getGenericReturnType() != void.class; + typesToConsider = genericParameterTypes; } + + Type type = typesToConsider[parameterIndex]; + + if ( type instanceof TypeVariable ) { + type = TypeHelper.getErasedType( type ); + } + return type; } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java index 67271d68c9..c6013a8de0 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java @@ -6,8 +6,11 @@ */ package org.hibernate.validator.internal.properties.javabean; +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedType; import java.lang.reflect.Field; import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; import java.security.AccessController; import java.security.PrivilegedAction; @@ -19,7 +22,7 @@ /** * @author Marko Bekhta */ -public class JavaBeanField implements Property { +public class JavaBeanField implements Property, JavaBeanAnnotatedConstrainable { private final Field field; private final String name; @@ -63,6 +66,31 @@ public String getPropertyName() { return getName(); } + @Override + public AnnotatedType getAnnotatedType() { + return field.getAnnotatedType(); + } + + @Override + public Annotation[] getDeclaredAnnotations() { + return field.getDeclaredAnnotations(); + } + + @Override + public A getAnnotation(Class annotationClass) { + return field.getAnnotation( annotationClass ); + } + + @Override + public Type getGenericType() { + return ReflectionHelper.typeOf( field ); + } + + @Override + public TypeVariable[] getTypeParameters() { + return field.getType().getTypeParameters(); + } + @Override public boolean equals(Object o) { if ( this == o ) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java index 113aca02a5..65ec83aa8b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java @@ -7,7 +7,6 @@ package org.hibernate.validator.internal.properties.javabean; import java.lang.reflect.Method; -import java.lang.reflect.Type; import java.security.AccessController; import java.security.PrivilegedAction; @@ -20,9 +19,7 @@ /** * @author Marko Bekhta */ -public class JavaBeanGetter extends JavaBeanExecutable implements Property { - - private static final Class[] PARAMETER_TYPES = new Class[0]; +public class JavaBeanGetter extends JavaBeanMethod implements Property { private final String name; @@ -48,7 +45,7 @@ public JavaBeanGetter(Class declaringClass, Method method) { @Override public Object getValueFrom(Object bean) { - return ReflectionHelper.getValue( (Method) executable, bean ); + return ReflectionHelper.getValue( executable, bean ); } @Override @@ -68,16 +65,6 @@ public boolean hasParameters() { return false; } - @Override - public Class[] getParameterTypes() { - return PARAMETER_TYPES; - } - - @Override - public Type[] getGenericParameterTypes() { - return PARAMETER_TYPES; - } - @Override public String getParameterName(ExecutableParameterNameProvider parameterNameProvider, int parameterIndex) { throw new IllegalStateException( "Getters cannot have parameters" ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanMethod.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanMethod.java new file mode 100644 index 0000000000..166af53e8d --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanMethod.java @@ -0,0 +1,32 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.properties.javabean; + +import java.lang.reflect.Method; +import java.lang.reflect.TypeVariable; + +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; + +/** + * @author Guillaume Smet + */ +public class JavaBeanMethod extends JavaBeanExecutable { + + JavaBeanMethod(Method method) { + super( method, method.getGenericReturnType() != void.class ); + } + + @Override + public ConstrainedElementKind getConstrainedElementKind() { + return ConstrainedElementKind.METHOD; + } + + @Override + public TypeVariable[] getTypeParameters() { + return executable.getReturnType().getTypeParameters(); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanParameter.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanParameter.java new file mode 100644 index 0000000000..416b842c79 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanParameter.java @@ -0,0 +1,75 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.properties.javabean; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Parameter; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; + +/** + * @author Guillaume Smet + */ +public class JavaBeanParameter implements JavaBeanAnnotatedElement { + + private final JavaBeanExecutable executable; + + private final int index; + + private final Parameter parameter; + + private final Class type; + + private final Type genericType; + + JavaBeanParameter(JavaBeanExecutable executable, int index, Parameter parameter, Class type, Type genericType) { + this.executable = executable; + this.index = index; + this.parameter = parameter; + this.type = type; + this.genericType = genericType; + } + + public JavaBeanExecutable getExecutable() { + return executable; + } + + public int getIndex() { + return index; + } + + @Override + public Class getType() { + return type; + } + + @Override + public AnnotatedType getAnnotatedType() { + return parameter.getAnnotatedType(); + } + + @Override + public Annotation[] getDeclaredAnnotations() { + return parameter.getDeclaredAnnotations(); + } + + @Override + public Type getGenericType() { + return genericType; + } + + @Override + public TypeVariable[] getTypeParameters() { + return parameter.getType().getTypeParameters(); + } + + @Override + public A getAnnotation(Class annotationClass) { + return parameter.getAnnotation( annotationClass ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java index 1807e03322..dd8da3e3e3 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java @@ -26,7 +26,7 @@ import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; -import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; +import org.hibernate.validator.internal.properties.javabean.JavaBeanConstructor; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; @@ -85,7 +85,8 @@ ConstrainedExecutable build(Class beanClass, List> alreadyProc parameterTypes ); } - JavaBeanExecutable executable = JavaBeanExecutable.of( constructor ); + + JavaBeanConstructor javaBeanConstructor = new JavaBeanConstructor( constructor ); if ( alreadyProcessedConstructors.contains( constructor ) ) { throw LOG.getConstructorIsDefinedTwiceInMappingXmlForBeanException( constructor, beanClass ); @@ -97,7 +98,7 @@ ConstrainedExecutable build(Class beanClass, List> alreadyProc // ignore annotations if ( ignoreAnnotations.isPresent() ) { annotationProcessingOptions.ignoreConstraintAnnotationsOnMember( - executable, + javaBeanConstructor, ignoreAnnotations.get() ); } @@ -105,21 +106,22 @@ ConstrainedExecutable build(Class beanClass, List> alreadyProc List constrainedParameters = CollectionHelper.newArrayList( constrainedParameterStaxBuilders.size() ); for ( int index = 0; index < constrainedParameterStaxBuilders.size(); index++ ) { ConstrainedParameterStaxBuilder builder = constrainedParameterStaxBuilders.get( index ); - constrainedParameters.add( builder.build( executable, index ) ); + constrainedParameters.add( builder.build( javaBeanConstructor, index ) ); } Set> crossParameterConstraints = getCrossParameterStaxBuilder() - .map( builder -> builder.build( executable ) ).orElse( Collections.emptySet() ); + .map( builder -> builder.build( javaBeanConstructor ) ).orElse( Collections.emptySet() ); // parse the return value Set> returnValueConstraints = new HashSet<>(); Set> returnValueTypeArgumentConstraints = new HashSet<>(); - CascadingMetaDataBuilder cascadingMetaDataBuilder = getReturnValueStaxBuilder().map( builder -> builder.build( executable, returnValueConstraints, returnValueTypeArgumentConstraints ) ) + CascadingMetaDataBuilder cascadingMetaDataBuilder = getReturnValueStaxBuilder() + .map( builder -> builder.build( javaBeanConstructor, returnValueConstraints, returnValueTypeArgumentConstraints ) ) .orElse( CascadingMetaDataBuilder.nonCascading() ); return new ConstrainedExecutable( ConfigurationSource.XML, - executable, + javaBeanConstructor, constrainedParameters, crossParameterConstraints, returnValueConstraints, diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java index f1876750c4..4a78d244bc 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java @@ -97,7 +97,7 @@ ConstrainedExecutable build(Class beanClass, List alreadyProcessedMet else { alreadyProcessedMethods.add( method ); } - JavaBeanExecutable executable = JavaBeanExecutable.of( method ); + JavaBeanExecutable executable = JavaBeanExecutable.of( method ); // ignore annotations if ( ignoreAnnotations.isPresent() ) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java index 3d4eb1a090..5cc0cb2f65 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java @@ -71,7 +71,7 @@ public Class getParameterType(Class beanClass) { ConstrainedParameter build(Callable callable, int index) { ConstraintLocation constraintLocation = ConstraintLocation.forParameter( callable, index ); - Type type = callable.getTypeOfParameter( index ); + Type type = callable.getParameterGenericType( index ); Set> metaConstraints = constraintTypeStaxBuilders.stream() .map( builder -> builder.build( constraintLocation, ConstraintLocationKind.PARAMETER, null ) ) From b0beaafd3bbc8e7aa15db22f091981fb2710b3a8 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 4 Jun 2018 11:48:40 +0200 Subject: [PATCH 060/393] HV-1623 Propagate ConstraintLocationKind as far as possible --- .../engine/ConstraintViolationImpl.java | 72 +++++++++---------- .../internal/engine/ValidatorImpl.java | 32 +++++---- .../internal/engine/ValueContext.java | 16 ++--- .../BeanValidationContext.java | 1 - .../ParameterExecutableValidationContext.java | 1 - .../PropertyValidationContext.java | 1 - ...eturnValueExecutableValidationContext.java | 1 - .../metadata/aggregated/FieldCascadable.java | 7 +- .../metadata/aggregated/GetterCascadable.java | 7 +- .../aggregated/ParameterMetaData.java | 6 +- .../aggregated/ReturnValueMetaData.java | 6 +- .../metadata/core/MetaConstraint.java | 2 +- .../descriptor/ConstraintDescriptorImpl.java | 14 ++-- .../internal/metadata/facets/Cascadable.java | 8 +-- 14 files changed, 81 insertions(+), 93 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ConstraintViolationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ConstraintViolationImpl.java index 59e3ee04c9..69aa6d1619 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ConstraintViolationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ConstraintViolationImpl.java @@ -7,7 +7,6 @@ package org.hibernate.validator.internal.engine; import java.io.Serializable; -import java.lang.annotation.ElementType; import java.lang.invoke.MethodHandles; import java.util.Map; @@ -45,17 +44,16 @@ public class ConstraintViolationImpl implements HibernateConstraintViolation< private final int hashCode; public static ConstraintViolation forBeanValidation(String messageTemplate, - Map messageParameters, - Map expressionVariables, - String interpolatedMessage, - Class rootBeanClass, - T rootBean, - Object leafBeanInstance, - Object value, - Path propertyPath, - ConstraintDescriptor constraintDescriptor, - ElementType elementType, - Object dynamicPayload) { + Map messageParameters, + Map expressionVariables, + String interpolatedMessage, + Class rootBeanClass, + T rootBean, + Object leafBeanInstance, + Object value, + Path propertyPath, + ConstraintDescriptor constraintDescriptor, + Object dynamicPayload) { return new ConstraintViolationImpl<>( messageTemplate, messageParameters, @@ -67,7 +65,6 @@ public static ConstraintViolation forBeanValidation(String messageTemplat value, propertyPath, constraintDescriptor, - elementType, null, null, dynamicPayload @@ -75,18 +72,17 @@ public static ConstraintViolation forBeanValidation(String messageTemplat } public static ConstraintViolation forParameterValidation(String messageTemplate, - Map messageParameters, - Map expressionVariables, - String interpolatedMessage, - Class rootBeanClass, - T rootBean, - Object leafBeanInstance, - Object value, - Path propertyPath, - ConstraintDescriptor constraintDescriptor, - ElementType elementType, - Object[] executableParameters, - Object dynamicPayload) { + Map messageParameters, + Map expressionVariables, + String interpolatedMessage, + Class rootBeanClass, + T rootBean, + Object leafBeanInstance, + Object value, + Path propertyPath, + ConstraintDescriptor constraintDescriptor, + Object[] executableParameters, + Object dynamicPayload) { return new ConstraintViolationImpl<>( messageTemplate, messageParameters, @@ -98,7 +94,6 @@ public static ConstraintViolation forParameterValidation(String messageTe value, propertyPath, constraintDescriptor, - elementType, executableParameters, null, dynamicPayload @@ -106,18 +101,17 @@ public static ConstraintViolation forParameterValidation(String messageTe } public static ConstraintViolation forReturnValueValidation(String messageTemplate, - Map messageParameters, - Map expressionVariables, - String interpolatedMessage, - Class rootBeanClass, - T rootBean, - Object leafBeanInstance, - Object value, - Path propertyPath, - ConstraintDescriptor constraintDescriptor, - ElementType elementType, - Object executableReturnValue, - Object dynamicPayload) { + Map messageParameters, + Map expressionVariables, + String interpolatedMessage, + Class rootBeanClass, + T rootBean, + Object leafBeanInstance, + Object value, + Path propertyPath, + ConstraintDescriptor constraintDescriptor, + Object executableReturnValue, + Object dynamicPayload) { return new ConstraintViolationImpl<>( messageTemplate, messageParameters, @@ -129,7 +123,6 @@ public static ConstraintViolation forReturnValueValidation(String message value, propertyPath, constraintDescriptor, - elementType, null, executableReturnValue, dynamicPayload @@ -146,7 +139,6 @@ private ConstraintViolationImpl(String messageTemplate, Object value, Path propertyPath, ConstraintDescriptor constraintDescriptor, - ElementType elementType, Object[] executableParameters, Object executableReturnValue, Object dynamicPayload) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index 5ec5c85f0b..9bbe13193e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -8,7 +8,6 @@ import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES; -import java.lang.annotation.ElementType; import java.lang.invoke.MethodHandles; import java.lang.reflect.Constructor; import java.lang.reflect.Executable; @@ -63,6 +62,7 @@ import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.facets.Cascadable; import org.hibernate.validator.internal.metadata.facets.Validatable; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ReflectionHelper; @@ -552,8 +552,8 @@ private void validateCascadedConstraints(BaseBeanValidationContext validation for ( Cascadable cascadable : validatable.getCascadables() ) { valueContext.appendNode( cascadable ); - ElementType elementType = cascadable.getElementType(); - if ( isCascadeRequired( validationContext, valueContext.getCurrentBean(), valueContext.getPropertyPath(), elementType ) ) { + if ( isCascadeRequired( validationContext, valueContext.getCurrentBean(), valueContext.getPropertyPath(), + cascadable.getConstraintLocationKind() ) ) { Object value = getCascadableValue( validationContext, valueContext.getCurrentBean(), cascadable ); CascadingMetaData cascadingMetaData = cascadable.getCascadingMetaData(); @@ -1283,12 +1283,13 @@ private boolean isValidationRequired(BaseBeanValidationContext validationCont validationContext, valueContext.getCurrentBean(), valueContext.getPropertyPath(), - metaConstraint.getConstraintLocationKind().getElementType() + metaConstraint.getConstraintLocationKind() ); } - private boolean isReachable(BaseBeanValidationContext validationContext, Object traversableObject, PathImpl path, ElementType type) { - if ( needToCallTraversableResolver( path, type ) ) { + private boolean isReachable(BaseBeanValidationContext validationContext, Object traversableObject, PathImpl path, + ConstraintLocationKind constraintLocationKind) { + if ( needToCallTraversableResolver( path, constraintLocationKind ) ) { return true; } @@ -1299,7 +1300,7 @@ private boolean isReachable(BaseBeanValidationContext validationContext, Obje path.getLeafNode(), validationContext.getRootBeanClass(), pathToObject, - type + constraintLocationKind.getElementType() ); } catch (RuntimeException e) { @@ -1307,23 +1308,24 @@ private boolean isReachable(BaseBeanValidationContext validationContext, Obje } } - private boolean needToCallTraversableResolver(PathImpl path, ElementType type) { + private boolean needToCallTraversableResolver(PathImpl path, ConstraintLocationKind constraintLocationKind) { // as the TraversableResolver interface is designed right now it does not make sense to call it when // there is no traversable object hosting the property to be accessed. For this reason we don't call the resolver // for class level constraints (ElementType.TYPE) or top level method parameters or return values. // see also BV expert group discussion - http://lists.jboss.org/pipermail/beanvalidation-dev/2013-January/000722.html - return isClassLevelConstraint( type ) + return isClassLevelConstraint( constraintLocationKind ) || isCrossParameterValidation( path ) || isParameterValidation( path ) || isReturnValueValidation( path ); } - private boolean isCascadeRequired(BaseBeanValidationContext validationContext, Object traversableObject, PathImpl path, ElementType type) { - if ( needToCallTraversableResolver( path, type ) ) { + private boolean isCascadeRequired(BaseBeanValidationContext validationContext, Object traversableObject, PathImpl path, + ConstraintLocationKind constraintLocationKind) { + if ( needToCallTraversableResolver( path, constraintLocationKind ) ) { return true; } - boolean isReachable = isReachable( validationContext, traversableObject, path, type ); + boolean isReachable = isReachable( validationContext, traversableObject, path, constraintLocationKind ); if ( !isReachable ) { return false; } @@ -1335,7 +1337,7 @@ private boolean isCascadeRequired(BaseBeanValidationContext validationContext path.getLeafNode(), validationContext.getRootBeanClass(), pathToObject, - type + constraintLocationKind.getElementType() ); } catch (RuntimeException e) { @@ -1343,8 +1345,8 @@ private boolean isCascadeRequired(BaseBeanValidationContext validationContext } } - private boolean isClassLevelConstraint(ElementType type) { - return ElementType.TYPE.equals( type ); + private boolean isClassLevelConstraint(ConstraintLocationKind constraintLocationKind) { + return ConstraintLocationKind.TYPE.equals( constraintLocationKind ); } private boolean isCrossParameterValidation(PathImpl path) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValueContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValueContext.java index 88ba7f7d35..024b5419ec 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValueContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValueContext.java @@ -6,7 +6,6 @@ */ package org.hibernate.validator.internal.engine; -import java.lang.annotation.ElementType; import java.lang.reflect.TypeVariable; import javax.validation.groups.Default; @@ -19,6 +18,7 @@ import org.hibernate.validator.internal.metadata.facets.Cascadable; import org.hibernate.validator.internal.metadata.facets.Validatable; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.TypeVariables; @@ -67,9 +67,9 @@ public class ValueContext { private final Validatable currentValidatable; /** - * The {@code ElementType} the constraint was defined on + * The {@code ConstraintLocationKind} the constraint was defined on */ - private ElementType elementType; + private ConstraintLocationKind constraintLocationKind; public static ValueContext getLocalExecutionContext(BeanMetaDataManager beanMetaDataManager, ExecutableParameterNameProvider parameterNameProvider, T value, Validatable validatable, PathImpl propertyPath) { @@ -199,12 +199,12 @@ public final boolean validatingDefault() { return getCurrentGroup() != null && getCurrentGroup().getName().equals( Default.class.getName() ); } - public final ElementType getElementType() { - return elementType; + public final ConstraintLocationKind getConstraintLocationKind() { + return constraintLocationKind; } - public final void setElementType(ElementType elementType) { - this.elementType = elementType; + public final void setConstraintLocationKind(ConstraintLocationKind constraintLocationKind) { + this.constraintLocationKind = constraintLocationKind; } public final ValueState getCurrentValueState() { @@ -225,7 +225,7 @@ public String toString() { sb.append( ", propertyPath=" ).append( propertyPath ); sb.append( ", currentGroup=" ).append( currentGroup ); sb.append( ", currentValue=" ).append( currentValue ); - sb.append( ", elementType=" ).append( elementType ); + sb.append( ", constraintLocationKind=" ).append( constraintLocationKind ); sb.append( '}' ); return sb.toString(); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BeanValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BeanValidationContext.java index 3aaee06783..3a6afdb698 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BeanValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BeanValidationContext.java @@ -61,7 +61,6 @@ protected ConstraintViolation createConstraintViolation( localContext.getCurrentValidatedValue(), propertyPath, constraintDescriptor, - localContext.getElementType(), constraintViolationCreationContext.getDynamicPayload() ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ParameterExecutableValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ParameterExecutableValidationContext.java index c581746598..c7eaa48498 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ParameterExecutableValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ParameterExecutableValidationContext.java @@ -129,7 +129,6 @@ protected ConstraintViolation createConstraintViolation( valueContext.getCurrentValidatedValue(), propertyPath, constraintDescriptor, - valueContext.getElementType(), executableParameters, constraintViolationCreationContext.getDynamicPayload() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java index 04e37dfecb..c16acc1deb 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java @@ -94,7 +94,6 @@ protected ConstraintViolation createConstraintViolation( localContext.getCurrentValidatedValue(), propertyPath, constraintDescriptor, - localContext.getElementType(), constraintViolationCreationContext.getDynamicPayload() ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ReturnValueExecutableValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ReturnValueExecutableValidationContext.java index 1c2455fa4d..da619edddc 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ReturnValueExecutableValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ReturnValueExecutableValidationContext.java @@ -101,7 +101,6 @@ protected ConstraintViolation createConstraintViolation(String messageTemplat valueContext.getCurrentValidatedValue(), propertyPath, constraintDescriptor, - valueContext.getElementType(), executableReturnValue, constraintViolationCreationContext.getDynamicPayload() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java index 37d82ff6da..7021170530 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java @@ -6,10 +6,9 @@ */ package org.hibernate.validator.internal.metadata.aggregated; -import java.lang.annotation.ElementType; - import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.facets.Cascadable; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.properties.Property; /** @@ -25,8 +24,8 @@ public class FieldCascadable extends PropertyCascadable { } @Override - public ElementType getElementType() { - return ElementType.FIELD; + public ConstraintLocationKind getConstraintLocationKind() { + return ConstraintLocationKind.FIELD; } public static class Builder extends PropertyCascadable.Builder { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java index fbb379ab2e..b9e7e6bcae 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java @@ -6,10 +6,9 @@ */ package org.hibernate.validator.internal.metadata.aggregated; -import java.lang.annotation.ElementType; - import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.facets.Cascadable; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.properties.Property; /** @@ -25,8 +24,8 @@ public class GetterCascadable extends PropertyCascadable { } @Override - public ElementType getElementType() { - return ElementType.METHOD; + public ConstraintLocationKind getConstraintLocationKind() { + return ConstraintLocationKind.METHOD; } public static class Builder extends PropertyCascadable.Builder { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ParameterMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ParameterMetaData.java index c40e659fb1..839d12f812 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ParameterMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ParameterMetaData.java @@ -6,7 +6,6 @@ */ package org.hibernate.validator.internal.metadata.aggregated; -import java.lang.annotation.ElementType; import java.lang.reflect.Type; import java.util.List; import java.util.Set; @@ -20,6 +19,7 @@ import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.descriptor.ParameterDescriptorImpl; import org.hibernate.validator.internal.metadata.facets.Cascadable; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; @@ -64,8 +64,8 @@ public int getIndex() { } @Override - public ElementType getElementType() { - return ElementType.PARAMETER; + public ConstraintLocationKind getConstraintLocationKind() { + return ConstraintLocationKind.PARAMETER; } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ReturnValueMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ReturnValueMetaData.java index 6e9062b131..aac44bf57f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ReturnValueMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ReturnValueMetaData.java @@ -6,7 +6,6 @@ */ package org.hibernate.validator.internal.metadata.aggregated; -import java.lang.annotation.ElementType; import java.lang.reflect.Type; import java.util.Collections; import java.util.List; @@ -20,6 +19,7 @@ import org.hibernate.validator.internal.metadata.descriptor.ReturnValueDescriptorImpl; import org.hibernate.validator.internal.metadata.facets.Cascadable; import org.hibernate.validator.internal.metadata.facets.Validatable; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.util.stereotypes.Immutable; /** @@ -67,8 +67,8 @@ public boolean hasCascadables() { } @Override - public ElementType getElementType() { - return ElementType.METHOD; + public ConstraintLocationKind getConstraintLocationKind() { + return ConstraintLocationKind.METHOD; } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java index 5fb3c1623b..de3a33005a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java @@ -123,7 +123,7 @@ public boolean validateConstraint(ValidationContext validationContext, ValueC } private boolean doValidateConstraint(ValidationContext executionContext, ValueContext valueContext) { - valueContext.setElementType( getConstraintLocationKind().getElementType() ); + valueContext.setConstraintLocationKind( getConstraintLocationKind() ); boolean validationResult = constraintTree.validateConstraints( executionContext, valueContext ); return validationResult; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ConstraintDescriptorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ConstraintDescriptorImpl.java index 692bb389c9..e8b69be279 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ConstraintDescriptorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ConstraintDescriptorImpl.java @@ -129,7 +129,7 @@ public class ConstraintDescriptorImpl implements Constrain private final boolean isReportAsSingleInvalidConstraint; /** - * Describes on which level ({@code TYPE}, {@code METHOD}, {@code FIELD}) the constraint was + * Describes on which level ({@code TYPE}, {@code METHOD}, {@code FIELD}...) the constraint was * defined on. */ private final ConstraintLocationKind constraintLocationKind; @@ -165,12 +165,12 @@ public class ConstraintDescriptorImpl implements Constrain public ConstraintDescriptorImpl(ConstraintHelper constraintHelper, Constrainable constrainable, ConstraintAnnotationDescriptor annotationDescriptor, - ConstraintLocationKind kind, + ConstraintLocationKind constraintLocationKind, Class implicitGroup, ConstraintOrigin definedOn, ConstraintType externalConstraintType) { this.annotationDescriptor = annotationDescriptor; - this.constraintLocationKind = kind; + this.constraintLocationKind = constraintLocationKind; this.definedOn = definedOn; this.isReportAsSingleInvalidConstraint = annotationDescriptor.getType().isAnnotationPresent( ReportAsSingleViolation.class @@ -227,16 +227,16 @@ public ConstraintDescriptorImpl(ConstraintHelper constraintHelper, public ConstraintDescriptorImpl(ConstraintHelper constraintHelper, Constrainable constrainable, ConstraintAnnotationDescriptor annotationDescriptor, - ConstraintLocationKind kind) { - this( constraintHelper, constrainable, annotationDescriptor, kind, null, ConstraintOrigin.DEFINED_LOCALLY, null ); + ConstraintLocationKind constraintLocationKind) { + this( constraintHelper, constrainable, annotationDescriptor, constraintLocationKind, null, ConstraintOrigin.DEFINED_LOCALLY, null ); } public ConstraintDescriptorImpl(ConstraintHelper constraintHelper, Constrainable constrainable, ConstraintAnnotationDescriptor annotationDescriptor, - ConstraintLocationKind kind, + ConstraintLocationKind constraintLocationKind, ConstraintType constraintType) { - this( constraintHelper, constrainable, annotationDescriptor, kind, null, ConstraintOrigin.DEFINED_LOCALLY, constraintType ); + this( constraintHelper, constrainable, annotationDescriptor, constraintLocationKind, null, ConstraintOrigin.DEFINED_LOCALLY, constraintType ); } public ConstraintAnnotationDescriptor getAnnotationDescriptor() { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/facets/Cascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/facets/Cascadable.java index f63ed55c9b..fd5864a3d2 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/facets/Cascadable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/facets/Cascadable.java @@ -6,12 +6,12 @@ */ package org.hibernate.validator.internal.metadata.facets; -import java.lang.annotation.ElementType; import java.lang.reflect.Type; import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaData; import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; /** * Provides a unified view on cascadable elements of all kinds, be it properties @@ -24,11 +24,11 @@ public interface Cascadable { /** - * Returns the element type of the cascadable. + * Returns the constraint location kind of the cascadable. * - * @return Returns the element type of the cascadable. + * @return Returns the constraint location kind of the cascadable. */ - ElementType getElementType(); + ConstraintLocationKind getConstraintLocationKind(); /** * Returns the data type of this cascadable, e.g. the type of a bean property or the From 8d96d9bd81c7c2cf249d2d9f7af8e2a5b64f25c4 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 4 Jun 2018 12:17:19 +0200 Subject: [PATCH 061/393] HV-1623 Encapsulate ConstraintLocationKind inside ConstraintLocation --- .../cfg/context/ConfiguredConstraint.java | 40 ++++--------------- .../ConstraintMappingContextImplBase.java | 2 +- ...erElementConstraintMappingContextImpl.java | 2 +- .../location/BeanConstraintLocation.java | 6 +++ .../metadata/location/ConstraintLocation.java | 5 +++ .../CrossParameterConstraintLocation.java | 16 +++++++- .../FieldPropertyConstraintLocation.java | 5 +++ .../GetterPropertyConstraintLocation.java | 5 +++ .../location/ParameterConstraintLocation.java | 13 +++++- .../location/PropertyConstraintLocation.java | 1 + .../ReturnValueConstraintLocation.java | 14 ++++++- .../TypeArgumentConstraintLocation.java | 5 +++ 12 files changed, 76 insertions(+), 38 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java index 3b2cbfdb6a..3798389f52 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java @@ -19,8 +19,6 @@ import org.hibernate.validator.cfg.AnnotationDef; import org.hibernate.validator.cfg.ConstraintDef; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; -import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; import org.hibernate.validator.internal.util.annotation.AnnotationDescriptor; @@ -34,6 +32,7 @@ * related to its location (bean type etc.). * * @author Gunnar Morling + * @author Guillaume Smet */ class ConfiguredConstraint { @@ -44,49 +43,36 @@ class ConfiguredConstraint { private final ConstraintDef constraint; private final ConstraintLocation location; - private final ConstraintLocationKind kind; - private ConfiguredConstraint(ConstraintDef constraint, ConstraintLocation location, ConstraintLocationKind kind) { + private ConfiguredConstraint(ConstraintDef constraint, ConstraintLocation location) { this.constraint = constraint; this.location = location; - this.kind = kind; } static ConfiguredConstraint forType(ConstraintDef constraint, Class beanType) { - return new ConfiguredConstraint<>( constraint, ConstraintLocation.forClass( beanType ), ConstraintLocationKind.TYPE ); + return new ConfiguredConstraint<>( constraint, ConstraintLocation.forClass( beanType ) ); } static ConfiguredConstraint forFieldProperty(ConstraintDef constraint, JavaBeanField javaBeanField) { - return new ConfiguredConstraint<>( - constraint, - ConstraintLocation.forField( javaBeanField ), - ConstraintLocationKind.FIELD - ); + return new ConfiguredConstraint<>( constraint, ConstraintLocation.forField( javaBeanField ) ); } public static ConfiguredConstraint forParameter(ConstraintDef constraint, Callable callable, int parameterIndex) { - return new ConfiguredConstraint<>( - constraint, ConstraintLocation.forParameter( callable, parameterIndex ), getConstraintLocationKindFromCallable( callable ) - ); + return new ConfiguredConstraint<>( constraint, ConstraintLocation.forParameter( callable, parameterIndex ) ); } public static ConfiguredConstraint forExecutable(ConstraintDef constraint, Callable callable) { - return new ConfiguredConstraint<>( - constraint, ConstraintLocation.forReturnValue( callable ), getConstraintLocationKindFromCallable( callable ) - ); + return new ConfiguredConstraint<>( constraint, ConstraintLocation.forReturnValue( callable ) ); } public static ConfiguredConstraint forCrossParameter(ConstraintDef constraint, Callable callable) { - return new ConfiguredConstraint<>( - constraint, ConstraintLocation.forCrossParameter( callable ), getConstraintLocationKindFromCallable( callable ) - ); + return new ConfiguredConstraint<>( constraint, ConstraintLocation.forCrossParameter( callable ) ); } public static ConfiguredConstraint forTypeArgument(ConstraintDef constraint, ConstraintLocation delegate, TypeVariable typeArgument, Type typeOfAnnotatedElement) { return new ConfiguredConstraint<>( constraint, - ConstraintLocation.forTypeArgument( delegate, typeArgument, typeOfAnnotatedElement ), - ConstraintLocationKind.TYPE_USE + ConstraintLocation.forTypeArgument( delegate, typeArgument, typeOfAnnotatedElement ) ); } @@ -116,16 +102,6 @@ public String toString() { return constraint.toString(); } - public ConstraintLocationKind getConstraintLocationKind() { - return kind; - } - - private static ConstraintLocationKind getConstraintLocationKindFromCallable(Callable callable) { - return callable.getConstrainedElementKind() == ConstrainedElementKind.CONSTRUCTOR - ? ConstraintLocationKind.CONSTRUCTOR - : ConstraintLocationKind.METHOD; - } - /** * Runs the given privileged action, using a privileged block if required. * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintMappingContextImplBase.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintMappingContextImplBase.java index ed8582e4c7..3598e1d70f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintMappingContextImplBase.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintMappingContextImplBase.java @@ -75,7 +75,7 @@ private MetaConstraint asMetaConstraint(ConfiguredCons constraintHelper, config.getLocation().getConstrainable(), config.createAnnotationDescriptor(), - config.getConstraintLocationKind(), + config.getLocation().getKind(), getConstraintType() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java index e9e05526a7..2b5f20f630 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java @@ -239,7 +239,7 @@ private MetaConstraint asMetaConstraint(ConfiguredCons constraintHelper, config.getLocation().getConstrainable(), config.createAnnotationDescriptor(), - config.getConstraintLocationKind(), + config.getLocation().getKind(), getConstraintType() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/BeanConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/BeanConstraintLocation.java index d6d8f3a0ab..0ff0fd218f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/BeanConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/BeanConstraintLocation.java @@ -18,6 +18,7 @@ * * @author Hardy Ferentschik * @author Gunnar Morling + * @author Guillaume Smet */ class BeanConstraintLocation implements ConstraintLocation { @@ -66,6 +67,11 @@ public Object getValue(Object parent) { return parent; } + @Override + public ConstraintLocationKind getKind() { + return ConstraintLocationKind.TYPE; + } + @Override public String toString() { return "BeanConstraintLocation [declaringClass=" + declaringClass + ", typeForValidatorResolution=" + typeForValidatorResolution + "]"; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java index 6e97299d98..d8197f5560 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java @@ -97,6 +97,11 @@ static ConstraintLocation forParameter(Callable callable, int index) { */ Object getValue(Object parent); + /** + * Returns the nature of the constraint location. + */ + ConstraintLocationKind getKind(); + enum ConstraintLocationKind { TYPE( ElementType.TYPE ), CONSTRUCTOR( ElementType.CONSTRUCTOR ), diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java index 549ab73e1e..04ef4d100e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java @@ -9,6 +9,7 @@ import java.lang.reflect.Type; import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; @@ -18,13 +19,19 @@ * * @author Hardy Ferentschik * @author Gunnar Morling + * @author Guillaume Smet */ class CrossParameterConstraintLocation implements ConstraintLocation { private final Callable callable; - CrossParameterConstraintLocation(Callable executable) { - this.callable = executable; + private final ConstraintLocationKind kind; + + CrossParameterConstraintLocation(Callable callable) { + this.callable = callable; + this.kind = callable.getConstrainedElementKind() == ConstrainedElementKind.CONSTRUCTOR + ? ConstraintLocationKind.CONSTRUCTOR + : ConstraintLocationKind.METHOD; } @Override @@ -52,6 +59,11 @@ public Object getValue(Object parent) { return parent; } + @Override + public ConstraintLocationKind getKind() { + return kind; + } + @Override public String toString() { return "CrossParameterConstraintLocation [callable=" + callable + "]"; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldPropertyConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldPropertyConstraintLocation.java index 2cdb6840cc..4687132dea 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldPropertyConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldPropertyConstraintLocation.java @@ -18,4 +18,9 @@ public class FieldPropertyConstraintLocation extends PropertyConstraintLocation< FieldPropertyConstraintLocation(JavaBeanField javaBeanGetter) { super( javaBeanGetter ); } + + @Override + public ConstraintLocationKind getKind() { + return ConstraintLocationKind.FIELD; + } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterPropertyConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterPropertyConstraintLocation.java index 2d450be8bf..12e2b42bab 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterPropertyConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterPropertyConstraintLocation.java @@ -18,4 +18,9 @@ public class GetterPropertyConstraintLocation extends PropertyConstraintLocation GetterPropertyConstraintLocation(JavaBeanGetter javaBeanGetter) { super( javaBeanGetter ); } + + @Override + public ConstraintLocationKind getKind() { + return ConstraintLocationKind.METHOD; + } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java index f7ee26cac0..a732e556aa 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java @@ -9,6 +9,7 @@ import java.lang.reflect.Type; import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; @@ -19,17 +20,22 @@ * * @author Hardy Ferentschik * @author Gunnar Morling + * @author Guillaume Smet */ public class ParameterConstraintLocation implements ConstraintLocation { private final Callable callable; private final int index; private final Type typeForValidatorResolution; + private final ConstraintLocationKind kind; public ParameterConstraintLocation(Callable callable, int index) { this.callable = callable; this.index = index; this.typeForValidatorResolution = ReflectionHelper.boxedType( callable.getParameterGenericType( index ) ); + this.kind = callable.getConstrainedElementKind() == ConstrainedElementKind.CONSTRUCTOR + ? ConstraintLocationKind.CONSTRUCTOR + : ConstraintLocationKind.METHOD; } @Override @@ -61,9 +67,14 @@ public Object getValue(Object parent) { return ( (Object[]) parent )[index]; } + @Override + public ConstraintLocationKind getKind() { + return kind; + } + @Override public String toString() { - return "ParameterConstraintLocation [executable=" + callable + ", index=" + index + "]"; + return "ParameterConstraintLocation [callable=" + callable + ", index=" + index + "]"; } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java index b64181c185..a9f0f17b64 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java @@ -16,6 +16,7 @@ * An abstract property constraint location. * * @author Marko Bekhta + * @author Guillaume Smet */ public abstract class PropertyConstraintLocation implements ConstraintLocation { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java index 30c66c5889..9203e4a9d5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java @@ -9,6 +9,7 @@ import java.lang.reflect.Type; import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; @@ -19,13 +20,19 @@ * @author Hardy Ferentschik * @author Gunnar Morling * @author Marko Bekhta + * @author Guillaume Smet */ class ReturnValueConstraintLocation implements ConstraintLocation { private final Callable callable; + private final ConstraintLocationKind kind; + ReturnValueConstraintLocation(Callable callable) { this.callable = callable; + this.kind = callable.getConstrainedElementKind() == ConstrainedElementKind.CONSTRUCTOR + ? ConstraintLocationKind.CONSTRUCTOR + : ConstraintLocationKind.METHOD; } @Override @@ -53,9 +60,14 @@ public Object getValue(Object parent) { return parent; } + @Override + public ConstraintLocationKind getKind() { + return kind; + } + @Override public String toString() { - return "ReturnValueConstraintLocation [executable=" + callable + "]"; + return "ReturnValueConstraintLocation [callable=" + callable + "]"; } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/TypeArgumentConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/TypeArgumentConstraintLocation.java index d470c8c8bd..0f82da3644 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/TypeArgumentConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/TypeArgumentConstraintLocation.java @@ -87,6 +87,11 @@ public ConstraintLocation getOuterDelegate() { return outerDelegate; } + @Override + public ConstraintLocationKind getKind() { + return ConstraintLocationKind.TYPE_USE; + } + @Override public String toString() { return "TypeArgumentValueConstraintLocation [typeForValidatorResolution=" + StringHelper.toShortString( typeForValidatorResolution ) From c2b9432c6d91865d603ef8da3f7615ae86dbf616 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Tue, 5 Jun 2018 00:02:51 +0200 Subject: [PATCH 062/393] HV-1623 Extract class-level metadata from property metadata case --- .../metadata/aggregated/BeanMetaDataImpl.java | 21 ++-- .../metadata/aggregated/ClassMetaData.java | 115 ++++++++++++++++++ .../metadata/aggregated/PropertyMetaData.java | 11 -- .../descriptor/ClassDescriptorImpl.java | 37 ++++++ .../provider/AnnotationMetaDataProvider.java | 2 - 5 files changed, 164 insertions(+), 22 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ClassMetaData.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ClassDescriptorImpl.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java index dcd979012b..7e3d64f372 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java @@ -196,6 +196,7 @@ public BeanMetaDataImpl(Class beanClass, Set tmpUnconstrainedExecutables = newHashSet(); boolean hasConstraints = false; + Set> allMetaConstraints = newHashSet(); for ( ConstraintMetaData constraintMetaData : constraintMetaDataSet ) { boolean elementHasConstraints = constraintMetaData.isCascading() || constraintMetaData.isConstrained(); @@ -204,6 +205,9 @@ public BeanMetaDataImpl(Class beanClass, if ( constraintMetaData.getKind() == ElementKind.PROPERTY ) { propertyMetaDataSet.add( (PropertyMetaData) constraintMetaData ); } + else if ( constraintMetaData.getKind() == ElementKind.BEAN ) { + allMetaConstraints.addAll( ( (ClassMetaData) constraintMetaData ).getAllConstraints() ); + } else { ExecutableMetaData executableMetaData = (ExecutableMetaData) constraintMetaData; if ( elementHasConstraints ) { @@ -216,7 +220,6 @@ public BeanMetaDataImpl(Class beanClass, } Set cascadedProperties = newHashSet(); - Set> allMetaConstraints = newHashSet(); for ( PropertyMetaData propertyMetaData : propertyMetaDataSet ) { propertyMetaDataMap.put( propertyMetaData.getName(), propertyMetaData ); @@ -696,7 +699,7 @@ private static class BuilderDelegate { private final TypeResolutionHelper typeResolutionHelper; private final ValueExtractorManager valueExtractorManager; private final ExecutableParameterNameProvider parameterNameProvider; - private MetaDataBuilder propertyBuilder; + private MetaDataBuilder metaDataBuilder; private ExecutableMetaData.Builder methodBuilder; private final MethodValidationConfiguration methodValidationConfiguration; private final int hashCode; @@ -723,7 +726,7 @@ public BuilderDelegate( switch ( constrainedElement.getKind() ) { case FIELD: ConstrainedField constrainedField = (ConstrainedField) constrainedElement; - propertyBuilder = new PropertyMetaData.Builder( + metaDataBuilder = new PropertyMetaData.Builder( beanClass, constrainedField, constraintHelper, @@ -752,7 +755,7 @@ public BuilderDelegate( } if ( constrainedExecutable.isGetterMethod() ) { - propertyBuilder = new PropertyMetaData.Builder( + metaDataBuilder = new PropertyMetaData.Builder( beanClass, constrainedExecutable, constraintHelper, @@ -763,7 +766,7 @@ public BuilderDelegate( break; case TYPE: ConstrainedType constrainedType = (ConstrainedType) constrainedElement; - propertyBuilder = new PropertyMetaData.Builder( + metaDataBuilder = new ClassMetaData.Builder( beanClass, constrainedType, constraintHelper, @@ -784,8 +787,8 @@ public boolean add(ConstrainedElement constrainedElement) { added = true; } - if ( propertyBuilder != null && propertyBuilder.accepts( constrainedElement ) ) { - propertyBuilder.add( constrainedElement ); + if ( metaDataBuilder != null && metaDataBuilder.accepts( constrainedElement ) ) { + metaDataBuilder.add( constrainedElement ); if ( !added && constrainedElement.getKind() == ConstrainedElementKind.METHOD && methodBuilder == null ) { ConstrainedExecutable constrainedMethod = (ConstrainedExecutable) constrainedElement; @@ -810,8 +813,8 @@ public boolean add(ConstrainedElement constrainedElement) { public Set build() { Set metaDataSet = newHashSet(); - if ( propertyBuilder != null ) { - metaDataSet.add( propertyBuilder.build() ); + if ( metaDataBuilder != null ) { + metaDataSet.add( metaDataBuilder.build() ); } if ( methodBuilder != null ) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ClassMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ClassMetaData.java new file mode 100644 index 0000000000..1c69196f2c --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ClassMetaData.java @@ -0,0 +1,115 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.metadata.aggregated; + +import java.util.List; +import java.util.Set; + +import javax.validation.ElementKind; + +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.metadata.descriptor.ClassDescriptorImpl; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; +import org.hibernate.validator.internal.metadata.raw.ConstrainedType; +import org.hibernate.validator.internal.util.TypeResolutionHelper; + +/** + * Represents the constraint related meta data for a type i.e. class-level + * constraints. + * + * @author Gunnar Morling + * @author Guillaume Smet + * @author Marko Bekhta + */ +public class ClassMetaData extends AbstractConstraintMetaData { + + private ClassMetaData(Class beanClass, + Set> constraints, + Set> containerElementsConstraints) { + super( + beanClass.getSimpleName(), + beanClass, + constraints, + containerElementsConstraints, + false, + !constraints.isEmpty() || !containerElementsConstraints.isEmpty() + ); + } + + @Override + public ClassDescriptorImpl asDescriptor(boolean defaultGroupSequenceRedefined, List> defaultGroupSequence) { + return new ClassDescriptorImpl( + getType(), + asDescriptors( getDirectConstraints() ), + defaultGroupSequenceRedefined, + defaultGroupSequence + ); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append( getClass().getSimpleName() ).append( "[ " ); + sb.append( "type=" ).append( getType() ); + sb.append( "]" ); + return sb.toString(); + } + + @Override + public ElementKind getKind() { + return ElementKind.BEAN; + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if ( this == obj ) { + return true; + } + if ( !super.equals( obj ) ) { + return false; + } + if ( getClass() != obj.getClass() ) { + return false; + } + return true; + } + + public static class Builder extends MetaDataBuilder { + public Builder(Class beanClass, ConstrainedType constrainedType, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, + ValueExtractorManager valueExtractorManager) { + super( beanClass, constraintHelper, typeResolutionHelper, valueExtractorManager ); + + add( constrainedType ); + } + + @Override + public boolean accepts(ConstrainedElement constrainedElement) { + return constrainedElement.getKind() == ConstrainedElement.ConstrainedElementKind.TYPE; + } + + @Override + public final void add(ConstrainedElement constrainedElement) { + super.add( constrainedElement ); + } + + @Override + public ClassMetaData build() { + return new ClassMetaData( + getBeanClass(), + adaptOriginsAndImplicitGroups( getDirectConstraints() ), + adaptOriginsAndImplicitGroups( getContainerElementConstraints() ) + ); + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java index 8150ea009b..f87e1c9b55 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java @@ -35,7 +35,6 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; -import org.hibernate.validator.internal.metadata.raw.ConstrainedType; import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; @@ -151,7 +150,6 @@ public boolean equals(Object obj) { public static class Builder extends MetaDataBuilder { private static final EnumSet SUPPORTED_ELEMENT_KINDS = EnumSet.of( - ConstrainedElementKind.TYPE, ConstrainedElementKind.FIELD, ConstrainedElementKind.METHOD ); @@ -169,15 +167,6 @@ public Builder(Class beanClass, ConstrainedField constrainedProperty, Constra add( constrainedProperty ); } - public Builder(Class beanClass, ConstrainedType constrainedType, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager) { - super( beanClass, constraintHelper, typeResolutionHelper, valueExtractorManager ); - - this.propertyName = null; - this.propertyType = null; - add( constrainedType ); - } - public Builder(Class beanClass, ConstrainedExecutable constrainedMethod, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { super( beanClass, constraintHelper, typeResolutionHelper, valueExtractorManager ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ClassDescriptorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ClassDescriptorImpl.java new file mode 100644 index 0000000000..0d1f0017b4 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ClassDescriptorImpl.java @@ -0,0 +1,37 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.metadata.descriptor; + +import java.lang.reflect.Type; +import java.util.List; +import java.util.Set; + +import javax.validation.metadata.ElementDescriptor; + +/** + * Describes a validated type class-level constraints. + * + * @author Marko Bekhta + */ +public class ClassDescriptorImpl extends ElementDescriptorImpl implements ElementDescriptor { + + public ClassDescriptorImpl(Type beanType, + Set> constraints, + boolean defaultGroupSequenceRedefined, + List> defaultGroupSequence) { + super( beanType, constraints, defaultGroupSequenceRedefined, defaultGroupSequence ); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( getClass().getSimpleName() ); + sb.append( "{beanType=" ).append( getElementClass() ); + sb.append( '}' ); + return sb.toString(); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java index ad4b3d408f..4afaa5e2fe 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java @@ -136,8 +136,6 @@ private BeanConfiguration retrieveBeanConfiguration(Class beanClass) { constrainedElements.addAll( getMethodMetaData( beanClass ) ); constrainedElements.addAll( getConstructorMetaData( beanClass ) ); - //TODO GM: currently class level constraints are represented by a PropertyMetaData. This - //works but seems somewhat unnatural Set> classLevelConstraints = getClassLevelConstraints( beanClass ); if ( !classLevelConstraints.isEmpty() ) { ConstrainedType classLevelMetaData = From 2714267e248917b930c5659b041d2abf4eb453a3 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Tue, 5 Jun 2018 21:10:21 +0200 Subject: [PATCH 063/393] HV-1623 Create different programmatic mapping contexts for getter and field - create different implementations of PropertyConstraintMappingContextImpl for getter and field to separate the logic. --- ...dPropertyConstraintMappingContextImpl.java | 58 +++++++++++++ ...rPropertyConstraintMappingContextImpl.java | 52 ++++++++++++ .../PropertyConstraintMappingContextImpl.java | 83 ++++++++----------- .../TypeConstraintMappingContextImpl.java | 14 ++-- .../validator/internal/util/logging/Log.java | 3 + 5 files changed, 151 insertions(+), 59 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldPropertyConstraintMappingContextImpl.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterPropertyConstraintMappingContextImpl.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldPropertyConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldPropertyConstraintMappingContextImpl.java new file mode 100644 index 0000000000..417d963c2d --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldPropertyConstraintMappingContextImpl.java @@ -0,0 +1,58 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.cfg.context; + +import org.hibernate.validator.cfg.ConstraintDef; +import org.hibernate.validator.cfg.context.PropertyConstraintMappingContext; +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; +import org.hibernate.validator.internal.metadata.raw.ConstrainedField; +import org.hibernate.validator.internal.properties.javabean.JavaBeanField; +import org.hibernate.validator.internal.util.TypeResolutionHelper; + +/** + * An implementation of {@link PropertyConstraintMappingContextImpl} for a field property. + * Represents a constraint mapping creational context which allows to configure the constraints + * for one of the bean's field properties. + * + * @author Marko Bekhta + */ +final class FieldPropertyConstraintMappingContextImpl extends PropertyConstraintMappingContextImpl { + + FieldPropertyConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, JavaBeanField javaBeanField) { + super( typeContext, javaBeanField, ConstraintLocation.forField( javaBeanField ) ); + } + + @Override + public PropertyConstraintMappingContext constraint(ConstraintDef definition) { + super.addConstraint( + ConfiguredConstraint.forFieldProperty( + definition, getProperty() + ) + ); + return this; + } + + ConstrainedElement build(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { + return new ConstrainedField( + ConfigurationSource.API, + getProperty(), + getConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), + getTypeArgumentConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), + getCascadingMetaDataBuilder() + ); + } + + @Override + protected ConstraintType getConstraintType() { + return ConstraintType.GENERIC; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterPropertyConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterPropertyConstraintMappingContextImpl.java new file mode 100644 index 0000000000..1bfc8a1389 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterPropertyConstraintMappingContextImpl.java @@ -0,0 +1,52 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.cfg.context; + +import org.hibernate.validator.cfg.ConstraintDef; +import org.hibernate.validator.cfg.context.PropertyConstraintMappingContext; +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; +import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; +import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; +import org.hibernate.validator.internal.util.TypeResolutionHelper; + +/** + * An implementation of {@link PropertyConstraintMappingContextImpl} for a getter property. + * Represents a constraint mapping creational context which allows to configure the constraints + * for one of the bean's getter properties. + * + * @author Marko Bekhta + */ +final class GetterPropertyConstraintMappingContextImpl extends PropertyConstraintMappingContextImpl { + + GetterPropertyConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, JavaBeanGetter javaBeanGetter) { + super( typeContext, javaBeanGetter, ConstraintLocation.forGetter( javaBeanGetter ) ); + } + + @Override + public PropertyConstraintMappingContext constraint(ConstraintDef definition) { + super.addConstraint( + ConfiguredConstraint.forExecutable( + definition, getProperty() + ) + ); + return this; + } + + ConstrainedElement build(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { + return new ConstrainedExecutable( + ConfigurationSource.API, + getProperty(), + getConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), + getTypeArgumentConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), + getCascadingMetaDataBuilder() + ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java index 7443605991..64001f2709 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java @@ -7,8 +7,8 @@ package org.hibernate.validator.internal.cfg.context; import java.lang.annotation.ElementType; +import java.lang.invoke.MethodHandles; -import org.hibernate.validator.cfg.ConstraintDef; import org.hibernate.validator.cfg.context.ConstructorConstraintMappingContext; import org.hibernate.validator.cfg.context.ContainerElementConstraintMappingContext; import org.hibernate.validator.cfg.context.MethodConstraintMappingContext; @@ -17,15 +17,13 @@ import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; -import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; -import org.hibernate.validator.internal.metadata.raw.ConstrainedField; -import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; /** * Constraint mapping creational context which allows to configure the constraints for one bean property. @@ -33,24 +31,43 @@ * @author Hardy Ferentschik * @author Gunnar Morling * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI + * @author Marko Bekhta */ -final class PropertyConstraintMappingContextImpl +abstract class PropertyConstraintMappingContextImpl extends CascadableConstraintMappingContextImplBase implements PropertyConstraintMappingContext { + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + private final TypeConstraintMappingContextImpl typeContext; // either Field or Method - private final Property property; + private final T property; private final ConstraintLocation location; - PropertyConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, Property property) { + static PropertyConstraintMappingContextImpl context(ElementType elementType, TypeConstraintMappingContextImpl typeContext, Property property) { + if ( elementType == ElementType.FIELD ) { + return new FieldPropertyConstraintMappingContextImpl( + typeContext, + property.as( JavaBeanField.class ) + ); + } + else if ( elementType == ElementType.METHOD ) { + return new GetterPropertyConstraintMappingContextImpl( + typeContext, + property.as( JavaBeanGetter.class ) + ); + } + else { + throw LOG.getUnexpectedElementType( elementType, ElementType.FIELD, ElementType.METHOD ); + } + } + + protected PropertyConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, T property, ConstraintLocation location) { super( typeContext.getConstraintMapping(), property.getType() ); this.typeContext = typeContext; this.property = property; - this.location = property instanceof JavaBeanField - ? ConstraintLocation.forField( property.as( JavaBeanField.class ) ) - : ConstraintLocation.forGetter( property.as( JavaBeanGetter.class ) ); + this.location = location; } @Override @@ -58,25 +75,6 @@ protected PropertyConstraintMappingContextImpl getThis() { return this; } - @Override - public PropertyConstraintMappingContext constraint(ConstraintDef definition) { - if ( property instanceof JavaBeanField ) { - super.addConstraint( - ConfiguredConstraint.forFieldProperty( - definition, property.as( JavaBeanField.class ) - ) - ); - } - else { - super.addConstraint( - ConfiguredConstraint.forExecutable( - definition, property.as( Callable.class ) - ) - ); - } - return this; - } - @Override public PropertyConstraintMappingContext ignoreAnnotations() { return ignoreAnnotations( true ); @@ -113,29 +111,14 @@ public ContainerElementConstraintMappingContext containerElementType(int index, return super.containerElement( this, typeContext, location, index, nestedIndexes ); } - ConstrainedElement build(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { - if ( property instanceof JavaBeanField ) { - return new ConstrainedField( - ConfigurationSource.API, - property, - getConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), - getTypeArgumentConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), - getCascadingMetaDataBuilder() - ); - } - else { - return new ConstrainedExecutable( - ConfigurationSource.API, - property.as( Callable.class ), - getConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), - getTypeArgumentConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), - getCascadingMetaDataBuilder() - ); - } - } + abstract ConstrainedElement build(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager); @Override protected ConstraintType getConstraintType() { return ConstraintType.GENERIC; } + + protected T getProperty() { + return property; + } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java index 13fa7bd741..e2b1ff288e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java @@ -122,24 +122,20 @@ public PropertyConstraintMappingContext property(String property, ElementType el Contracts.assertNotNull( elementType, "The element type must not be null." ); Contracts.assertNotEmpty( property, MESSAGES.propertyNameMustNotBeEmpty() ); - Property member = getProperty( + Property foundProperty = getProperty( beanClass, property, elementType ); - if ( member == null || member.getDeclaringClass() != beanClass ) { + if ( foundProperty == null || foundProperty.getDeclaringClass() != beanClass ) { throw LOG.getUnableToFindPropertyWithAccessException( beanClass, property, elementType ); } - if ( configuredMembers.contains( member ) ) { + if ( configuredMembers.contains( foundProperty ) ) { throw LOG.getPropertyHasAlreadyBeConfiguredViaProgrammaticApiException( beanClass, property ); } - PropertyConstraintMappingContextImpl context = new PropertyConstraintMappingContextImpl( - this, - member - ); - - configuredMembers.add( member ); + PropertyConstraintMappingContextImpl context = PropertyConstraintMappingContextImpl.context( elementType, this, foundProperty ); + configuredMembers.add( foundProperty ); propertyContexts.add( context ); return context; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 18a6f24df3..4267ee49e0 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -860,4 +860,7 @@ ConstraintDefinitionException getConstraintValidatorDefinitionConstraintMismatch @Message(id = 244, value = "ConstrainedElement expected class was %1$s, but instead received %2$s.") AssertionError getUnexpectedConstraintElementType(@FormatWith(ClassObjectFormatter.class) Class expecting, @FormatWith(ClassObjectFormatter.class) Class got); + + @Message(id = 245, value = "Allowed ElementTypes are %2$s, but instead received %1$s.") + AssertionError getUnexpectedElementType(ElementType received, @FormatWith(ObjectArrayFormatter.class) ElementType... got); } From 088294218ef2059fc9a8c1e063a04ac13f177da5 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Wed, 6 Jun 2018 00:04:06 +0200 Subject: [PATCH 064/393] HV-1623 Make parameters more specific in programmatic API executable mapping contexts --- .../ConstructorConstraintMappingContextImpl.java | 4 ++-- .../context/MethodConstraintMappingContextImpl.java | 4 ++-- .../cfg/context/TypeConstraintMappingContextImpl.java | 9 +++++---- .../properties/javabean/JavaBeanExecutable.java | 10 +++++++--- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstructorConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstructorConstraintMappingContextImpl.java index 2b71b966a4..f062f38ab0 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstructorConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstructorConstraintMappingContextImpl.java @@ -7,7 +7,7 @@ package org.hibernate.validator.internal.cfg.context; import org.hibernate.validator.cfg.context.ConstructorConstraintMappingContext; -import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.properties.javabean.JavaBeanConstructor; /** * Constraint mapping creational context representing a constructor. @@ -16,7 +16,7 @@ */ class ConstructorConstraintMappingContextImpl extends ExecutableConstraintMappingContextImpl implements ConstructorConstraintMappingContext { - ConstructorConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, Callable constructor) { + ConstructorConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, JavaBeanConstructor constructor) { super( typeContext, constructor ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/MethodConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/MethodConstraintMappingContextImpl.java index 19e74b27db..7e8ae93bbe 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/MethodConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/MethodConstraintMappingContextImpl.java @@ -7,7 +7,7 @@ package org.hibernate.validator.internal.cfg.context; import org.hibernate.validator.cfg.context.MethodConstraintMappingContext; -import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.properties.javabean.JavaBeanMethod; /** * Constraint mapping creational context representing a method. @@ -16,7 +16,7 @@ */ class MethodConstraintMappingContextImpl extends ExecutableConstraintMappingContextImpl implements MethodConstraintMappingContext { - MethodConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, Callable callable) { + MethodConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, JavaBeanMethod callable) { super( typeContext, callable ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java index e2b1ff288e..2c05aed768 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java @@ -39,6 +39,7 @@ import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; +import org.hibernate.validator.internal.properties.javabean.JavaBeanMethod; import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ReflectionHelper; @@ -150,17 +151,17 @@ public MethodConstraintMappingContext method(String name, Class... parameterT throw LOG.getBeanDoesNotContainMethodException( beanClass, name, parameterTypes ); } - JavaBeanExecutable javaBeanExecutable = JavaBeanExecutable.of( method ); + JavaBeanMethod javaBeanMethod = JavaBeanExecutable.of( method ); - if ( configuredMembers.contains( javaBeanExecutable ) ) { + if ( configuredMembers.contains( javaBeanMethod ) ) { throw LOG.getMethodHasAlreadyBeenConfiguredViaProgrammaticApiException( beanClass, ExecutableHelper.getExecutableAsString( name, parameterTypes ) ); } - MethodConstraintMappingContextImpl context = new MethodConstraintMappingContextImpl( this, javaBeanExecutable ); - configuredMembers.add( javaBeanExecutable ); + MethodConstraintMappingContextImpl context = new MethodConstraintMappingContextImpl( this, javaBeanMethod ); + configuredMembers.add( javaBeanMethod ); executableContexts.add( context ); return context; diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java index 1d69c8e629..25e181ba23 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java @@ -69,11 +69,15 @@ public static JavaBeanExecutable of(Executable executable) { return new JavaBeanConstructor( (Constructor) executable ); } - if ( ReflectionHelper.isGetterMethod( executable ) ) { - return new JavaBeanGetter( (Method) executable ); + return of( ( (Method) executable ) ); + } + + public static JavaBeanMethod of(Method method) { + if ( ReflectionHelper.isGetterMethod( method ) ) { + return new JavaBeanGetter( method ); } - return new JavaBeanMethod( (Method) executable ); + return new JavaBeanMethod( method ); } @Override From e6c9e485d5b93e6324575a1bd11feea8fb0be20f Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Wed, 6 Jun 2018 23:43:30 +0200 Subject: [PATCH 065/393] HV-1623 Deprecate property() in programmatic API and introduce field() and getter() instead - add two new methods field() and getter() to replace deprecated property() - update property constraint mapping implementations to use generics and get rid of casting objects --- .../validator/cfg/context/PropertyTarget.java | 35 ++++++- ...erElementConstraintMappingContextImpl.java | 10 ++ .../PropertyConstraintMappingContextImpl.java | 35 ++----- .../TypeConstraintMappingContextImpl.java | 95 +++++++++++-------- .../test/cfg/ConstraintMappingTest.java | 23 +++++ 5 files changed, 132 insertions(+), 66 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/cfg/context/PropertyTarget.java b/engine/src/main/java/org/hibernate/validator/cfg/context/PropertyTarget.java index 3fae3760fa..3546ce6dd0 100644 --- a/engine/src/main/java/org/hibernate/validator/cfg/context/PropertyTarget.java +++ b/engine/src/main/java/org/hibernate/validator/cfg/context/PropertyTarget.java @@ -21,15 +21,46 @@ public interface PropertyTarget { *

* Until this method is called constraints apply on class level. After calling this method constraints * apply on the specified property with the given access type. - *

*

* A given property may only be configured once. - *

* * @param property The property on which to apply the following constraints (Java Bean notation). * @param type The access type (field/property). * * @return A creational context representing the selected property. + * + * @deprecated Since 6.1. Planned for removal. Use either {@link PropertyTarget#field(String)} or + * {@link PropertyTarget#getter(String)} instead. */ + @Deprecated PropertyConstraintMappingContext property(String property, ElementType type); + + /** + * Selects a field to which the next operations shall apply. + *

+ * Until this method is called constraints apply on class level. After calling this method constraints + * apply on the specified field property. + *

+ * A given field may only be configured once. + * + * @param property The field name that represents a property on which to apply the following constraints. + * + * @return A creational context representing the selected field property. + */ + PropertyConstraintMappingContext field(String property); + + /** + * Selects a getter to which the next operations shall apply. + *

+ * Until this method is called constraints apply on class level. After calling this method constraints + * apply on the specified getter property. + *

+ * A given getter may only be configured once. + * + * @param property The getter property name (using the Java Bean notation, e.g. {@code name} to address {@code getName()}) + * that represents a property on which to apply the following constraints. + * + * @return A creational context representing the selected getter property. + */ + PropertyConstraintMappingContext getter(String property); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java index 2b5f20f630..e3eb9f3338 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java @@ -123,6 +123,16 @@ public PropertyConstraintMappingContext property(String property, ElementType el return typeContext.property( property, elementType ); } + @Override + public PropertyConstraintMappingContext field(String property) { + return typeContext.field( property ); + } + + @Override + public PropertyConstraintMappingContext getter(String property) { + return typeContext.getter( property ); + } + @Override public ConstructorConstraintMappingContext constructor(Class... parameterTypes) { return typeContext.constructor( parameterTypes ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java index 64001f2709..61f65e2fd7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java @@ -7,7 +7,6 @@ package org.hibernate.validator.internal.cfg.context; import java.lang.annotation.ElementType; -import java.lang.invoke.MethodHandles; import org.hibernate.validator.cfg.context.ConstructorConstraintMappingContext; import org.hibernate.validator.cfg.context.ContainerElementConstraintMappingContext; @@ -19,11 +18,7 @@ import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.properties.Property; -import org.hibernate.validator.internal.properties.javabean.JavaBeanField; -import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; import org.hibernate.validator.internal.util.TypeResolutionHelper; -import org.hibernate.validator.internal.util.logging.Log; -import org.hibernate.validator.internal.util.logging.LoggerFactory; /** * Constraint mapping creational context which allows to configure the constraints for one bean property. @@ -37,32 +32,12 @@ abstract class PropertyConstraintMappingContextImpl extends CascadableConstraintMappingContextImplBase implements PropertyConstraintMappingContext { - private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - private final TypeConstraintMappingContextImpl typeContext; // either Field or Method private final T property; private final ConstraintLocation location; - static PropertyConstraintMappingContextImpl context(ElementType elementType, TypeConstraintMappingContextImpl typeContext, Property property) { - if ( elementType == ElementType.FIELD ) { - return new FieldPropertyConstraintMappingContextImpl( - typeContext, - property.as( JavaBeanField.class ) - ); - } - else if ( elementType == ElementType.METHOD ) { - return new GetterPropertyConstraintMappingContextImpl( - typeContext, - property.as( JavaBeanGetter.class ) - ); - } - else { - throw LOG.getUnexpectedElementType( elementType, ElementType.FIELD, ElementType.METHOD ); - } - } - protected PropertyConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, T property, ConstraintLocation location) { super( typeContext.getConstraintMapping(), property.getType() ); this.typeContext = typeContext; @@ -91,6 +66,16 @@ public PropertyConstraintMappingContext property(String property, ElementType el return typeContext.property( property, elementType ); } + @Override + public PropertyConstraintMappingContext field(String property) { + return typeContext.field( property ); + } + + @Override + public PropertyConstraintMappingContext getter(String property) { + return typeContext.getter( property ); + } + @Override public ConstructorConstraintMappingContext constructor(Class... parameterTypes) { return typeContext.constructor( parameterTypes ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java index 2c05aed768..6581084b0c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java @@ -34,7 +34,6 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedType; import org.hibernate.validator.internal.properties.Constrainable; -import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.properties.javabean.JavaBeanConstructor; import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; @@ -119,24 +118,58 @@ public TypeConstraintMappingContext defaultGroupSequenceProviderClass(Class clazz, String property, ElementType elementType) { + private JavaBeanField getFieldProperty(Class clazz, String property) { Contracts.assertNotNull( clazz, MESSAGES.classCannotBeNull() ); - if ( property == null || property.length() == 0 ) { - throw LOG.getPropertyNameCannotBeNullOrEmptyException(); - } + Field field = run( GetDeclaredField.action( clazz, property ) ); + return field == null ? null : new JavaBeanField( field ); + } - if ( !( ElementType.FIELD.equals( elementType ) || ElementType.METHOD.equals( elementType ) ) ) { - throw LOG.getElementTypeHasToBeFieldOrMethodException(); - } + private JavaBeanGetter getGetterProperty(Class clazz, String property) { + Contracts.assertNotNull( clazz, MESSAGES.classCannotBeNull() ); - if ( ElementType.FIELD.equals( elementType ) ) { - Field field = run( GetDeclaredField.action( clazz, property ) ); - return field == null ? null : new JavaBeanField( field ); - } - else { - Method method = null; - String methodName = property.substring( 0, 1 ).toUpperCase( Locale.ROOT ) + property.substring( 1 ); - for ( String prefix : ReflectionHelper.PROPERTY_ACCESSOR_PREFIXES ) { - method = run( GetMethod.action( clazz, prefix + methodName ) ); - if ( method != null ) { - break; - } + Method method = null; + String methodName = property.substring( 0, 1 ).toUpperCase( Locale.ROOT ) + property.substring( 1 ); + for ( String prefix : ReflectionHelper.PROPERTY_ACCESSOR_PREFIXES ) { + method = run( GetMethod.action( clazz, prefix + methodName ) ); + if ( method != null ) { + break; } - return method == null ? null : new JavaBeanGetter( method ); } + return method == null ? null : new JavaBeanGetter( method ); } /** diff --git a/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java b/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java index ae7fd8a3f5..68a4b3af17 100644 --- a/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java @@ -60,6 +60,7 @@ import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.spi.group.DefaultGroupSequenceProvider; import org.hibernate.validator.testutils.ValidatorUtil; + import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -535,6 +536,28 @@ public void testProgrammaticAndAnnotationPropertyConstraintsAddUp() { ); } + @Test + public void testFieldAndGetterMethodsForProgrammaticConstraintDefinition() { + mapping.type( Marathon.class ) + .getter( "name" ) + .constraint( new SizeDef().min( 5 ) ) + .constraint( new SizeDef().min( 10 ) ) + .field( "runners" ) + .constraint( new SizeDef().max( 10 ).min( 1 ) ); + config.addMapping( mapping ); + Validator validator = config.buildValidatorFactory().getValidator(); + + Marathon marathon = new Marathon(); + marathon.setName( "Foo" ); + + Set> violations = validator.validate( marathon ); + assertThat( violations ).containsOnlyViolations( + violationOf( Size.class ).withMessage( "size must be between 10 and 2147483647" ), + violationOf( Size.class ).withMessage( "size must be between 5 and 2147483647" ), + violationOf( Size.class ).withMessage( "size must be between 1 and 10" ) + ); + } + private BeanConfiguration getBeanConfiguration(Class type) { Set> beanConfigurations = mapping.getBeanConfigurations( new ConstraintHelper(), From ba56ab3da36dc98ec10cab8564a4f8b484b8cc6d Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Thu, 7 Jun 2018 11:45:55 +0200 Subject: [PATCH 066/393] HV-1623 Replace empty check in Contracts with null and empty check at the same time - based on our usage of not empty check passed parameters should not be null as well hence the implementation of the check can use StringHelper.isNullOrEmptyString utility method. --- .../internal/cfg/context/TypeConstraintMappingContextImpl.java | 2 -- .../java/org/hibernate/validator/internal/util/Contracts.java | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java index 6581084b0c..4aebdbc4a4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java @@ -134,7 +134,6 @@ public PropertyConstraintMappingContext property(String property, ElementType el @Override public PropertyConstraintMappingContext field(String property) { - Contracts.assertNotNull( property, "The property name must not be null." ); Contracts.assertNotEmpty( property, MESSAGES.propertyNameMustNotBeEmpty() ); JavaBeanField javaBeanField = getFieldProperty( beanClass, property ); @@ -155,7 +154,6 @@ public PropertyConstraintMappingContext field(String property) { @Override public PropertyConstraintMappingContext getter(String property) { - Contracts.assertNotNull( property, "The property name must not be null." ); Contracts.assertNotEmpty( property, MESSAGES.propertyNameMustNotBeEmpty() ); JavaBeanGetter javaBeanGetter = getGetterProperty( beanClass, property ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/Contracts.java b/engine/src/main/java/org/hibernate/validator/internal/util/Contracts.java index dc57395795..b7164465c6 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/Contracts.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/Contracts.java @@ -75,7 +75,7 @@ public static void assertTrue(boolean condition, String message, Object... messa } public static void assertNotEmpty(String s, String message) { - if ( s.length() == 0 ) { + if ( StringHelper.isNullOrEmptyString( s ) ) { throw LOG.getIllegalArgumentException( message ); } } From aa490b1fb96dacc2d1e5e15208f2f61db0360ccb Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Thu, 7 Jun 2018 14:49:59 +0200 Subject: [PATCH 067/393] HV-1623 Introduce getter as a constraint location kind --- .../metadata/aggregated/GetterCascadable.java | 2 +- .../descriptor/ConstraintDescriptorImpl.java | 6 +----- .../metadata/location/ConstraintLocation.java | 16 ++++++++++++++++ .../CrossParameterConstraintLocation.java | 5 +---- .../GetterPropertyConstraintLocation.java | 2 +- .../location/ParameterConstraintLocation.java | 5 +---- .../location/ReturnValueConstraintLocation.java | 5 +---- .../provider/AnnotationMetaDataProvider.java | 4 +--- .../mapping/ConstrainedGetterStaxBuilder.java | 2 +- .../xml/mapping/CrossParameterStaxBuilder.java | 2 +- .../xml/mapping/ReturnValueStaxBuilder.java | 3 +-- .../ConstraintValidatorInitializationHelper.java | 3 ++- 12 files changed, 28 insertions(+), 27 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java index b9e7e6bcae..ea3a398349 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java @@ -25,7 +25,7 @@ public class GetterCascadable extends PropertyCascadable { @Override public ConstraintLocationKind getConstraintLocationKind() { - return ConstraintLocationKind.METHOD; + return ConstraintLocationKind.GETTER; } public static class Builder extends PropertyCascadable.Builder { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ConstraintDescriptorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ConstraintDescriptorImpl.java index e8b69be279..372e45dc44 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ConstraintDescriptorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/descriptor/ConstraintDescriptorImpl.java @@ -403,7 +403,7 @@ private ConstraintType determineConstraintType(Class const ConstraintType externalConstraintType) { ConstraintTarget constraintTarget = validationAppliesTo; ConstraintType constraintType = null; - boolean isExecutable = isExecutable( constraintLocationKind ); + boolean isExecutable = constraintLocationKind.isExecutable(); //target explicitly set to RETURN_VALUE if ( constraintTarget == ConstraintTarget.RETURN_VALUE ) { @@ -530,10 +530,6 @@ private void validateComposingConstraintTypes() { } } - private boolean isExecutable(ConstraintLocationKind locationKind) { - return locationKind == ConstraintLocationKind.METHOD || locationKind == ConstraintLocationKind.CONSTRUCTOR; - } - @SuppressWarnings("unchecked") private static Set> buildPayloadSet(ConstraintAnnotationDescriptor annotationDescriptor) { Set> payloadSet = newHashSet(); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java index d8197f5560..440d34317b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java @@ -11,6 +11,7 @@ import java.lang.reflect.TypeVariable; import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; @@ -108,6 +109,7 @@ enum ConstraintLocationKind { METHOD( ElementType.METHOD ), PARAMETER( ElementType.PARAMETER ), FIELD( ElementType.FIELD ), + GETTER( ElementType.METHOD ), TYPE_USE( ElementType.TYPE_USE ), ; @@ -120,5 +122,19 @@ enum ConstraintLocationKind { public ElementType getElementType() { return elementType; } + + public boolean isExecutable() { + return this == CONSTRUCTOR || isMethod(); + } + + public boolean isMethod() { + return this == METHOD || this == GETTER; + } + + public static ConstraintLocationKind of(Callable callable) { + return callable.getConstrainedElementKind() == ConstrainedElementKind.CONSTRUCTOR + ? ConstraintLocationKind.CONSTRUCTOR + : callable instanceof JavaBeanGetter ? ConstraintLocationKind.GETTER : ConstraintLocationKind.METHOD; + } } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java index 04ef4d100e..494a9c173b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java @@ -9,7 +9,6 @@ import java.lang.reflect.Type; import org.hibernate.validator.internal.engine.path.PathImpl; -import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; @@ -29,9 +28,7 @@ class CrossParameterConstraintLocation implements ConstraintLocation { CrossParameterConstraintLocation(Callable callable) { this.callable = callable; - this.kind = callable.getConstrainedElementKind() == ConstrainedElementKind.CONSTRUCTOR - ? ConstraintLocationKind.CONSTRUCTOR - : ConstraintLocationKind.METHOD; + this.kind = ConstraintLocationKind.of( callable ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterPropertyConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterPropertyConstraintLocation.java index 12e2b42bab..0f40edd9fe 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterPropertyConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterPropertyConstraintLocation.java @@ -21,6 +21,6 @@ public class GetterPropertyConstraintLocation extends PropertyConstraintLocation @Override public ConstraintLocationKind getKind() { - return ConstraintLocationKind.METHOD; + return ConstraintLocationKind.GETTER; } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java index a732e556aa..415175b77a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java @@ -9,7 +9,6 @@ import java.lang.reflect.Type; import org.hibernate.validator.internal.engine.path.PathImpl; -import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; @@ -33,9 +32,7 @@ public ParameterConstraintLocation(Callable callable, int index) { this.callable = callable; this.index = index; this.typeForValidatorResolution = ReflectionHelper.boxedType( callable.getParameterGenericType( index ) ); - this.kind = callable.getConstrainedElementKind() == ConstrainedElementKind.CONSTRUCTOR - ? ConstraintLocationKind.CONSTRUCTOR - : ConstraintLocationKind.METHOD; + this.kind = ConstraintLocationKind.of( callable ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java index 9203e4a9d5..6532fa6a33 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java @@ -9,7 +9,6 @@ import java.lang.reflect.Type; import org.hibernate.validator.internal.engine.path.PathImpl; -import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; @@ -30,9 +29,7 @@ class ReturnValueConstraintLocation implements ConstraintLocation { ReturnValueConstraintLocation(Callable callable) { this.callable = callable; - this.kind = callable.getConstrainedElementKind() == ConstrainedElementKind.CONSTRUCTOR - ? ConstraintLocationKind.CONSTRUCTOR - : ConstraintLocationKind.METHOD; + this.kind = ConstraintLocationKind.of( callable ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java index 4afaa5e2fe..ec13ce0964 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java @@ -303,9 +303,7 @@ private ConstrainedExecutable findExecutableMetaData(Executable executable) { Map>> executableConstraints = findConstraints( javaBeanExecutable, - javaBeanExecutable.getConstrainedElementKind() == ConstrainedElement.ConstrainedElementKind.CONSTRUCTOR - ? ConstraintLocationKind.CONSTRUCTOR - : ConstraintLocationKind.METHOD + ConstraintLocationKind.of( javaBeanExecutable ) ).stream().collect( Collectors.groupingBy( ConstraintDescriptorImpl::getConstraintType ) ); Set> crossParameterConstraints; diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java index 11bc792d33..3969c10577 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java @@ -77,7 +77,7 @@ ConstrainedExecutable build(Class beanClass, List alreadyProcessedGet ConstraintLocation constraintLocation = ConstraintLocation.forGetter( javaBeanGetter ); Set> metaConstraints = constraintTypeStaxBuilders.stream() - .map( builder -> builder.build( constraintLocation, ConstraintLocationKind.METHOD, null ) ) + .map( builder -> builder.build( constraintLocation, ConstraintLocationKind.GETTER, null ) ) .collect( Collectors.toSet() ); ContainerElementTypeConfiguration containerElementTypeConfiguration = getContainerElementTypeConfiguration( diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java index c92463cf95..64e2a183b9 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java @@ -89,7 +89,7 @@ Set> build(Callable callable) { ConstraintLocation constraintLocation = ConstraintLocation.forCrossParameter( callable ); Set> crossParameterConstraints = constraintTypeStaxBuilders.stream() - .map( builder -> builder.build( constraintLocation, ConstraintLocationKind.METHOD, ConstraintType.CROSS_PARAMETER ) ) + .map( builder -> builder.build( constraintLocation, ConstraintLocationKind.of( callable ), ConstraintType.CROSS_PARAMETER ) ) .collect( Collectors.toSet() ); // ignore annotations diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java index c3e2eb0136..56b27f5455 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java @@ -20,7 +20,6 @@ import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; -import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.xml.mapping.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; @@ -57,7 +56,7 @@ CascadingMetaDataBuilder build( ConstraintLocation constraintLocation = ConstraintLocation.forReturnValue( callable ); returnValueConstraints.addAll( constraintTypeStaxBuilders.stream() - .map( builder -> builder.build( constraintLocation, callable.getConstrainedElementKind() == ConstrainedElementKind.CONSTRUCTOR ? ConstraintLocationKind.CONSTRUCTOR : ConstraintLocationKind.METHOD, ConstraintDescriptorImpl.ConstraintType.GENERIC ) ) + .map( builder -> builder.build( constraintLocation, ConstraintLocationKind.of( callable ), ConstraintDescriptorImpl.ConstraintType.GENERIC ) ) .collect( Collectors.toSet() ) ); ContainerElementTypeConfiguration containerElementTypeConfiguration = getContainerElementTypeConfiguration( callable.getType(), constraintLocation ); diff --git a/engine/src/test/java/org/hibernate/validator/testutils/ConstraintValidatorInitializationHelper.java b/engine/src/test/java/org/hibernate/validator/testutils/ConstraintValidatorInitializationHelper.java index ea3e4b917d..30dbe909d4 100644 --- a/engine/src/test/java/org/hibernate/validator/testutils/ConstraintValidatorInitializationHelper.java +++ b/engine/src/test/java/org/hibernate/validator/testutils/ConstraintValidatorInitializationHelper.java @@ -18,6 +18,7 @@ import org.hibernate.validator.internal.engine.scripting.DefaultScriptEvaluatorFactory; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.spi.scripting.ScriptEvaluator; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; @@ -40,7 +41,7 @@ public static ConstraintDescriptor descriptorFrom(Cons CONSTRAINT_HELPER, null, annotationDescriptor, - null + ConstraintLocationKind.GETTER ); } From af0bb7b0f74843009357d9dfec7099910bc2a47b Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 8 Jun 2018 18:16:34 +0200 Subject: [PATCH 068/393] HV-1623 Introduce ConstrainedElementKind.GETTER --- .../metadata/aggregated/BeanMetaDataImpl.java | 11 ++++-- .../aggregated/ExecutableMetaData.java | 6 ++-- .../aggregated/PropertyCascadable.java | 4 +-- .../metadata/aggregated/PropertyMetaData.java | 13 +++---- .../metadata/location/ConstraintLocation.java | 26 ++++++++++---- .../CrossParameterConstraintLocation.java | 2 +- .../location/ParameterConstraintLocation.java | 2 +- .../ReturnValueConstraintLocation.java | 2 +- .../provider/AnnotationMetaDataProvider.java | 2 +- .../metadata/raw/ConstrainedElement.java | 34 +++++++++++++------ .../metadata/raw/ConstrainedExecutable.java | 14 -------- .../properties/javabean/JavaBeanGetter.java | 8 ++++- .../mapping/CrossParameterStaxBuilder.java | 3 +- .../xml/mapping/ReturnValueStaxBuilder.java | 3 +- .../test/cfg/ConstraintMappingTest.java | 2 +- 15 files changed, 76 insertions(+), 56 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java index 7e3d64f372..c9619bde27 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java @@ -15,6 +15,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; @@ -42,10 +43,10 @@ import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; -import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; import org.hibernate.validator.internal.metadata.raw.ConstrainedType; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.ExecutableHelper; @@ -736,6 +737,7 @@ public BuilderDelegate( break; case CONSTRUCTOR: case METHOD: + case GETTER: ConstrainedExecutable constrainedExecutable = (ConstrainedExecutable) constrainedElement; Callable callable = constrainedExecutable.getCallable(); @@ -754,7 +756,7 @@ public BuilderDelegate( ); } - if ( constrainedExecutable.isGetterMethod() ) { + if ( constrainedElement.getKind() == ConstrainedElementKind.GETTER ) { metaDataBuilder = new PropertyMetaData.Builder( beanClass, constrainedExecutable, @@ -774,6 +776,9 @@ public BuilderDelegate( valueExtractorManager ); break; + default: + throw new IllegalStateException( + String.format( Locale.ROOT, "Constrained element kind '%1$s' not supported here.", constrainedElement.getKind() ) ); } this.hashCode = buildHashCode(); @@ -790,7 +795,7 @@ public boolean add(ConstrainedElement constrainedElement) { if ( metaDataBuilder != null && metaDataBuilder.accepts( constrainedElement ) ) { metaDataBuilder.add( constrainedElement ); - if ( !added && constrainedElement.getKind() == ConstrainedElementKind.METHOD && methodBuilder == null ) { + if ( !added && constrainedElement.getKind().isMethod() && methodBuilder == null ) { ConstrainedExecutable constrainedMethod = (ConstrainedExecutable) constrainedElement; methodBuilder = new ExecutableMetaData.Builder( beanClass, diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java index a073d5056f..cd86946d31 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java @@ -254,12 +254,11 @@ public static class Builder extends MetaDataBuilder { private final Set signatures = newHashSet(); /** - * Either CONSTRUCTOR or METHOD. + * Either CONSTRUCTOR, METHOD or GETTER. */ private final ConstrainedElementKind kind; private final Set constrainedExecutables = newHashSet(); private Callable callable; - private final boolean isGetterMethod; private final Set> crossParameterConstraints = newHashSet(); private final Set rules; private boolean isConstrained = false; @@ -293,7 +292,6 @@ public Builder( this.kind = constrainedExecutable.getKind(); this.callable = constrainedExecutable.getCallable(); this.rules = methodValidationConfiguration.getConfiguredRuleSet(); - this.isGetterMethod = constrainedExecutable.isGetterMethod(); add( constrainedExecutable ); } @@ -397,7 +395,7 @@ public ExecutableMetaData build() { adaptOriginsAndImplicitGroups( crossParameterConstraints ), cascadingMetaDataBuilder.build( valueExtractorManager, callable ), isConstrained, - isGetterMethod + kind == ConstrainedElementKind.GETTER ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyCascadable.java index eafc89bbb3..a8acce09d0 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyCascadable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyCascadable.java @@ -80,10 +80,10 @@ public static Cascadable.Builder builder(ConstrainedElementKind constrainedEleme if ( ConstrainedElementKind.FIELD == constrainedElementKind ) { return new FieldCascadable.Builder( valueExtractorManager, property, cascadingMetaDataBuilder ); } - else if ( ConstrainedElementKind.METHOD == constrainedElementKind ) { + else if ( ConstrainedElementKind.GETTER == constrainedElementKind ) { return new GetterCascadable.Builder( valueExtractorManager, property, cascadingMetaDataBuilder ); } - throw new IllegalStateException( "It should either be field or method." ); + throw new IllegalStateException( "It should be either a field or a getter." ); } } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java index f87e1c9b55..3d372e1ed8 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java @@ -151,7 +151,7 @@ public static class Builder extends MetaDataBuilder { private static final EnumSet SUPPORTED_ELEMENT_KINDS = EnumSet.of( ConstrainedElementKind.FIELD, - ConstrainedElementKind.METHOD + ConstrainedElementKind.GETTER ); private final String propertyName; @@ -182,11 +182,6 @@ public boolean accepts(ConstrainedElement constrainedElement) { return false; } - if ( constrainedElement.getKind() == ConstrainedElementKind.METHOD && - !( (ConstrainedExecutable) constrainedElement ).isGetterMethod() ) { - return false; - } - return Objects.equals( getPropertyName( constrainedElement ), propertyName ); } @@ -222,7 +217,7 @@ private Optional getConstrainableFromConstrainedElement(Constrain LOG.getUnexpectedConstraintElementType( ConstrainedField.class, constrainedElement.getClass() ); } } - else if ( constrainedElement.getKind() == ConstrainedElementKind.METHOD ) { + else if ( constrainedElement.getKind() == ConstrainedElementKind.GETTER ) { if ( constrainedElement instanceof ConstrainedExecutable ) { return Optional.of( ( (ConstrainedExecutable) constrainedElement ).getCallable() ); } @@ -235,7 +230,7 @@ else if ( constrainedElement.getKind() == ConstrainedElementKind.METHOD ) { @Override protected Set> adaptConstraints(ConstrainedElement constrainedElement, Set> constraints) { - if ( constraints.isEmpty() || constrainedElement.getKind() != ConstrainedElementKind.METHOD ) { + if ( constraints.isEmpty() || constrainedElement.getKind() != ConstrainedElementKind.GETTER ) { return constraints; } @@ -304,7 +299,7 @@ private String getPropertyName(ConstrainedElement constrainedElement) { if ( constrainedElement.getKind() == ConstrainedElementKind.FIELD ) { return ( (ConstrainedField) constrainedElement ).getProperty().getPropertyName(); } - else if ( constrainedElement.getKind() == ConstrainedElementKind.METHOD ) { + else if ( constrainedElement.getKind() == ConstrainedElementKind.GETTER ) { return ( (ConstrainedExecutable) constrainedElement ).getCallable().as( Property.class ).getPropertyName(); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java index 440d34317b..f5ae00de56 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java @@ -9,6 +9,7 @@ import java.lang.annotation.ElementType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; +import java.util.Locale; import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; @@ -110,8 +111,7 @@ enum ConstraintLocationKind { PARAMETER( ElementType.PARAMETER ), FIELD( ElementType.FIELD ), GETTER( ElementType.METHOD ), - TYPE_USE( ElementType.TYPE_USE ), - ; + TYPE_USE( ElementType.TYPE_USE ); private final ElementType elementType; @@ -131,10 +131,24 @@ public boolean isMethod() { return this == METHOD || this == GETTER; } - public static ConstraintLocationKind of(Callable callable) { - return callable.getConstrainedElementKind() == ConstrainedElementKind.CONSTRUCTOR - ? ConstraintLocationKind.CONSTRUCTOR - : callable instanceof JavaBeanGetter ? ConstraintLocationKind.GETTER : ConstraintLocationKind.METHOD; + public static ConstraintLocationKind of(ConstrainedElementKind constrainedElementKind) { + switch ( constrainedElementKind ) { + case CONSTRUCTOR: + return ConstraintLocationKind.CONSTRUCTOR; + case FIELD: + return ConstraintLocationKind.FIELD; + case METHOD: + return ConstraintLocationKind.METHOD; + case PARAMETER: + return ConstraintLocationKind.PARAMETER; + case TYPE: + return ConstraintLocationKind.TYPE; + case GETTER: + return ConstraintLocationKind.GETTER; + default: + throw new IllegalArgumentException( + String.format( Locale.ROOT, "Constrained element kind '%1$s' not supported.", constrainedElementKind ) ); + } } } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java index 494a9c173b..0f36fa5ed7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/CrossParameterConstraintLocation.java @@ -28,7 +28,7 @@ class CrossParameterConstraintLocation implements ConstraintLocation { CrossParameterConstraintLocation(Callable callable) { this.callable = callable; - this.kind = ConstraintLocationKind.of( callable ); + this.kind = ConstraintLocationKind.of( callable.getConstrainedElementKind() ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java index 415175b77a..29392b77ff 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ParameterConstraintLocation.java @@ -32,7 +32,7 @@ public ParameterConstraintLocation(Callable callable, int index) { this.callable = callable; this.index = index; this.typeForValidatorResolution = ReflectionHelper.boxedType( callable.getParameterGenericType( index ) ); - this.kind = ConstraintLocationKind.of( callable ); + this.kind = ConstraintLocationKind.of( callable.getConstrainedElementKind() ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java index 6532fa6a33..6ee7b3f924 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ReturnValueConstraintLocation.java @@ -29,7 +29,7 @@ class ReturnValueConstraintLocation implements ConstraintLocation { ReturnValueConstraintLocation(Callable callable) { this.callable = callable; - this.kind = ConstraintLocationKind.of( callable ); + this.kind = ConstraintLocationKind.of( callable.getConstrainedElementKind() ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java index ec13ce0964..cac8cb06e7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java @@ -303,7 +303,7 @@ private ConstrainedExecutable findExecutableMetaData(Executable executable) { Map>> executableConstraints = findConstraints( javaBeanExecutable, - ConstraintLocationKind.of( javaBeanExecutable ) + ConstraintLocationKind.of( javaBeanExecutable.getConstrainedElementKind() ) ).stream().collect( Collectors.groupingBy( ConstraintDescriptorImpl::getConstraintType ) ); Set> crossParameterConstraints; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedElement.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedElement.java index fc7114ab4e..a1b1c456fd 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedElement.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedElement.java @@ -40,16 +40,6 @@ */ public interface ConstrainedElement extends Iterable> { - /** - * The kind of a {@link ConstrainedElement}. Can be used to determine an - * element's type when traversing over a collection of constrained elements. - * - * @author Gunnar Morling - */ - enum ConstrainedElementKind { - TYPE, FIELD, CONSTRUCTOR, METHOD, PARAMETER - } - /** * Returns the kind of this constrained element. * @@ -91,4 +81,28 @@ enum ConstrainedElementKind { * Returns the configuration source contributing this constrained element. */ ConfigurationSource getSource(); + + /** + * The kind of a {@link ConstrainedElement}. Can be used to determine an + * element's type when traversing over a collection of constrained elements. + * + * @author Gunnar Morling + */ + enum ConstrainedElementKind { + + TYPE, + FIELD, + CONSTRUCTOR, + METHOD, + PARAMETER, + GETTER; + + public boolean isExecutable() { + return this == CONSTRUCTOR || isMethod(); + } + + public boolean isMethod() { + return this == METHOD || this == GETTER; + } + } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedExecutable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedExecutable.java index 0c42157833..2d9a612929 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedExecutable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedExecutable.java @@ -20,7 +20,6 @@ import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.properties.Callable; -import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -51,8 +50,6 @@ public class ConstrainedExecutable extends AbstractConstrainedElement { @Immutable private final Set> crossParameterConstraints; - private final boolean isGetterMethod; - /** * Creates a new executable meta data object for a parameter-less executable. * @@ -123,7 +120,6 @@ public ConstrainedExecutable( this.crossParameterConstraints = CollectionHelper.toImmutableSet( crossParameterConstraints ); this.parameterMetaData = CollectionHelper.toImmutableList( parameterMetaData ); this.hasParameterConstraints = hasParameterConstraints( parameterMetaData ) || !crossParameterConstraints.isEmpty(); - this.isGetterMethod = callable instanceof Property; } /** @@ -190,16 +186,6 @@ public boolean hasParameterConstraints() { return hasParameterConstraints; } - /** - * Whether the represented executable is a JavaBeans getter executable or not. - * - * @return {@code True}, if this executable is a getter method, {@code false} - * otherwise. - */ - public boolean isGetterMethod() { - return isGetterMethod; - } - public Callable getCallable() { return callable; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java index 65ec83aa8b..722da007d5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java @@ -11,6 +11,7 @@ import java.security.PrivilegedAction; import org.hibernate.validator.HibernateValidatorPermission; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.ReflectionHelper; @@ -67,7 +68,7 @@ public boolean hasParameters() { @Override public String getParameterName(ExecutableParameterNameProvider parameterNameProvider, int parameterIndex) { - throw new IllegalStateException( "Getters cannot have parameters" ); + throw new IllegalStateException( "Getters may not have parameters" ); } @Override @@ -75,6 +76,11 @@ public Class getDeclaringClass() { return declaringClass; } + @Override + public ConstrainedElementKind getConstrainedElementKind() { + return ConstrainedElementKind.GETTER; + } + @Override public boolean equals(Object o) { if ( this == o ) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java index 64e2a183b9..84119ecbd3 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java @@ -89,7 +89,8 @@ Set> build(Callable callable) { ConstraintLocation constraintLocation = ConstraintLocation.forCrossParameter( callable ); Set> crossParameterConstraints = constraintTypeStaxBuilders.stream() - .map( builder -> builder.build( constraintLocation, ConstraintLocationKind.of( callable ), ConstraintType.CROSS_PARAMETER ) ) + .map( builder -> builder.build( constraintLocation, ConstraintLocationKind.of( callable.getConstrainedElementKind() ), + ConstraintType.CROSS_PARAMETER ) ) .collect( Collectors.toSet() ); // ignore annotations diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java index 56b27f5455..8157a2ba6d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java @@ -56,7 +56,8 @@ CascadingMetaDataBuilder build( ConstraintLocation constraintLocation = ConstraintLocation.forReturnValue( callable ); returnValueConstraints.addAll( constraintTypeStaxBuilders.stream() - .map( builder -> builder.build( constraintLocation, ConstraintLocationKind.of( callable ), ConstraintDescriptorImpl.ConstraintType.GENERIC ) ) + .map( builder -> builder.build( constraintLocation, ConstraintLocationKind.of( callable.getConstrainedElementKind() ), + ConstraintDescriptorImpl.ConstraintType.GENERIC ) ) .collect( Collectors.toSet() ) ); ContainerElementTypeConfiguration containerElementTypeConfiguration = getContainerElementTypeConfiguration( callable.getType(), constraintLocation ); diff --git a/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java b/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java index 68a4b3af17..73f9d1632b 100644 --- a/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java @@ -589,7 +589,7 @@ private ConstrainedField getConstrainedField(BeanConfiguration beanConfigurat private ConstrainedExecutable getConstrainedExecutable(BeanConfiguration beanConfiguration, String executableName) { for ( ConstrainedElement constrainedElement : beanConfiguration.getConstrainedElements() ) { - if ( constrainedElement.getKind() == ConstrainedElementKind.METHOD && + if ( constrainedElement.getKind().isMethod() && ( (ConstrainedExecutable) constrainedElement ).getCallable().getName().equals( executableName ) ) { return (ConstrainedExecutable) constrainedElement; } From 7740b9a4cf263271f823d098e18f0bd45d05c934 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 8 Jun 2018 19:06:19 +0200 Subject: [PATCH 069/393] HV-1623 Stop the propagation of JavaBeanField/Getter We don't need the elements to be typed so let's be looser to open the gate for JSON properties (which will probably simply be treated as fields). --- .../internal/cfg/context/ConfiguredConstraint.java | 7 ++++++- ...mpl.java => FieldConstraintMappingContextImpl.java} | 6 +++--- ...pl.java => GetterConstraintMappingContextImpl.java} | 6 +++--- .../cfg/context/TypeConstraintMappingContextImpl.java | 4 ++-- .../internal/metadata/aggregated/PropertyMetaData.java | 9 +++++---- .../internal/metadata/location/ConstraintLocation.java | 4 ++-- ...raintLocation.java => FieldConstraintLocation.java} | 8 ++++---- ...aintLocation.java => GetterConstraintLocation.java} | 8 ++++---- .../metadata/location/PropertyConstraintLocation.java | 10 +++++----- 9 files changed, 34 insertions(+), 28 deletions(-) rename engine/src/main/java/org/hibernate/validator/internal/cfg/context/{FieldPropertyConstraintMappingContextImpl.java => FieldConstraintMappingContextImpl.java} (88%) rename engine/src/main/java/org/hibernate/validator/internal/cfg/context/{GetterPropertyConstraintMappingContextImpl.java => GetterConstraintMappingContextImpl.java} (87%) rename engine/src/main/java/org/hibernate/validator/internal/metadata/location/{FieldPropertyConstraintLocation.java => FieldConstraintLocation.java} (63%) rename engine/src/main/java/org/hibernate/validator/internal/metadata/location/{GetterPropertyConstraintLocation.java => GetterConstraintLocation.java} (63%) diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java index 3798389f52..965c5711fa 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConfiguredConstraint.java @@ -21,6 +21,7 @@ import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; +import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; import org.hibernate.validator.internal.util.annotation.AnnotationDescriptor; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.internal.util.logging.Log; @@ -53,10 +54,14 @@ static ConfiguredConstraint forType(ConstraintDef( constraint, ConstraintLocation.forClass( beanType ) ); } - static ConfiguredConstraint forFieldProperty(ConstraintDef constraint, JavaBeanField javaBeanField) { + static ConfiguredConstraint forField(ConstraintDef constraint, JavaBeanField javaBeanField) { return new ConfiguredConstraint<>( constraint, ConstraintLocation.forField( javaBeanField ) ); } + static ConfiguredConstraint forGetter(ConstraintDef constraint, JavaBeanGetter javaBeanGetter) { + return forExecutable( constraint, javaBeanGetter ); + } + public static ConfiguredConstraint forParameter(ConstraintDef constraint, Callable callable, int parameterIndex) { return new ConfiguredConstraint<>( constraint, ConstraintLocation.forParameter( callable, parameterIndex ) ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldPropertyConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldConstraintMappingContextImpl.java similarity index 88% rename from engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldPropertyConstraintMappingContextImpl.java rename to engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldConstraintMappingContextImpl.java index 417d963c2d..04cb100abc 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldPropertyConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldConstraintMappingContextImpl.java @@ -25,16 +25,16 @@ * * @author Marko Bekhta */ -final class FieldPropertyConstraintMappingContextImpl extends PropertyConstraintMappingContextImpl { +final class FieldConstraintMappingContextImpl extends PropertyConstraintMappingContextImpl { - FieldPropertyConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, JavaBeanField javaBeanField) { + FieldConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, JavaBeanField javaBeanField) { super( typeContext, javaBeanField, ConstraintLocation.forField( javaBeanField ) ); } @Override public PropertyConstraintMappingContext constraint(ConstraintDef definition) { super.addConstraint( - ConfiguredConstraint.forFieldProperty( + ConfiguredConstraint.forField( definition, getProperty() ) ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterPropertyConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterConstraintMappingContextImpl.java similarity index 87% rename from engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterPropertyConstraintMappingContextImpl.java rename to engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterConstraintMappingContextImpl.java index 1bfc8a1389..ab749aba1f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterPropertyConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterConstraintMappingContextImpl.java @@ -24,16 +24,16 @@ * * @author Marko Bekhta */ -final class GetterPropertyConstraintMappingContextImpl extends PropertyConstraintMappingContextImpl { +final class GetterConstraintMappingContextImpl extends PropertyConstraintMappingContextImpl { - GetterPropertyConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, JavaBeanGetter javaBeanGetter) { + GetterConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, JavaBeanGetter javaBeanGetter) { super( typeContext, javaBeanGetter, ConstraintLocation.forGetter( javaBeanGetter ) ); } @Override public PropertyConstraintMappingContext constraint(ConstraintDef definition) { super.addConstraint( - ConfiguredConstraint.forExecutable( + ConfiguredConstraint.forGetter( definition, getProperty() ) ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java index 4aebdbc4a4..aa73b50aff 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java @@ -146,7 +146,7 @@ public PropertyConstraintMappingContext field(String property) { throw LOG.getPropertyHasAlreadyBeConfiguredViaProgrammaticApiException( beanClass, property ); } - PropertyConstraintMappingContextImpl context = new FieldPropertyConstraintMappingContextImpl( this, javaBeanField ); + PropertyConstraintMappingContextImpl context = new FieldConstraintMappingContextImpl( this, javaBeanField ); configuredMembers.add( javaBeanField ); propertyContexts.add( context ); return context; @@ -166,7 +166,7 @@ public PropertyConstraintMappingContext getter(String property) { throw LOG.getPropertyHasAlreadyBeConfiguredViaProgrammaticApiException( beanClass, property ); } - PropertyConstraintMappingContextImpl context = new GetterPropertyConstraintMappingContextImpl( this, javaBeanGetter ); + PropertyConstraintMappingContextImpl context = new GetterConstraintMappingContextImpl( this, javaBeanGetter ); configuredMembers.add( javaBeanGetter ); propertyContexts.add( context ); return context; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java index 3d372e1ed8..c630c6bfb8 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java @@ -29,7 +29,7 @@ import org.hibernate.validator.internal.metadata.descriptor.PropertyDescriptorImpl; import org.hibernate.validator.internal.metadata.facets.Cascadable; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.metadata.location.GetterPropertyConstraintLocation; +import org.hibernate.validator.internal.metadata.location.GetterConstraintLocation; import org.hibernate.validator.internal.metadata.location.TypeArgumentConstraintLocation; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; @@ -234,7 +234,8 @@ protected Set> adaptConstraints(ConstrainedElement constrained return constraints; } - ConstraintLocation getterConstraintLocation = ConstraintLocation.forGetter( ( (ConstrainedExecutable) constrainedElement ).getCallable().as( JavaBeanGetter.class ) ); + ConstraintLocation getterConstraintLocation = ConstraintLocation + .forGetter( ( (ConstrainedExecutable) constrainedElement ).getCallable().as( JavaBeanGetter.class ) ); // convert return value locations into getter locations for usage within this meta-data return constraints.stream() @@ -248,7 +249,7 @@ private MetaConstraint withGetterLocation(ConstraintLocation getterConstraint // fast track if it's a regular constraint if ( !( constraint.getLocation() instanceof TypeArgumentConstraintLocation ) ) { // Change the constraint location to a GetterConstraintLocation if it is not already one - if ( constraint.getLocation() instanceof GetterPropertyConstraintLocation ) { + if ( constraint.getLocation() instanceof GetterConstraintLocation ) { converted = constraint.getLocation(); } else { @@ -275,7 +276,7 @@ private MetaConstraint withGetterLocation(ConstraintLocation getterConstraint for ( ConstraintLocation location : locationStack ) { if ( !(location instanceof TypeArgumentConstraintLocation) ) { // Change the constraint location to a GetterConstraintLocation if it is not already one - if ( location instanceof GetterPropertyConstraintLocation ) { + if ( location instanceof GetterConstraintLocation ) { converted = location; } else { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java index f5ae00de56..2a9a90d283 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java @@ -43,11 +43,11 @@ static ConstraintLocation forClass(Class declaringClass) { } static ConstraintLocation forField(JavaBeanField field) { - return new FieldPropertyConstraintLocation( field ); + return new FieldConstraintLocation( field ); } static ConstraintLocation forGetter(JavaBeanGetter getter) { - return new GetterPropertyConstraintLocation( getter ); + return new GetterConstraintLocation( getter ); } static ConstraintLocation forTypeArgument(ConstraintLocation delegate, TypeVariable typeParameter, Type typeOfAnnotatedElement) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldPropertyConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java similarity index 63% rename from engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldPropertyConstraintLocation.java rename to engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java index 4687132dea..594ae9dbef 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldPropertyConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java @@ -6,17 +6,17 @@ */ package org.hibernate.validator.internal.metadata.location; -import org.hibernate.validator.internal.properties.javabean.JavaBeanField; +import org.hibernate.validator.internal.properties.Property; /** * Field property constraint location. * * @author Marko Bekhta */ -public class FieldPropertyConstraintLocation extends PropertyConstraintLocation { +public class FieldConstraintLocation extends PropertyConstraintLocation { - FieldPropertyConstraintLocation(JavaBeanField javaBeanGetter) { - super( javaBeanGetter ); + FieldConstraintLocation(Property field) { + super( field ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterPropertyConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java similarity index 63% rename from engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterPropertyConstraintLocation.java rename to engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java index 0f40edd9fe..07ab3ecbbd 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterPropertyConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java @@ -6,17 +6,17 @@ */ package org.hibernate.validator.internal.metadata.location; -import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; +import org.hibernate.validator.internal.properties.Property; /** * Getter property constraint location. * * @author Marko Bekhta */ -public class GetterPropertyConstraintLocation extends PropertyConstraintLocation { +public class GetterConstraintLocation extends PropertyConstraintLocation { - GetterPropertyConstraintLocation(JavaBeanGetter javaBeanGetter) { - super( javaBeanGetter ); + GetterConstraintLocation(Property getter) { + super( getter ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java index a9f0f17b64..907b03fbe0 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java @@ -18,14 +18,14 @@ * @author Marko Bekhta * @author Guillaume Smet */ -public abstract class PropertyConstraintLocation implements ConstraintLocation { +public abstract class PropertyConstraintLocation implements ConstraintLocation { /** * The member the constraint was defined on. */ - private final T property; + private final Property property; - PropertyConstraintLocation(T property) { + PropertyConstraintLocation(Property property) { this.property = property; } @@ -35,7 +35,7 @@ public Class getDeclaringClass() { } @Override - public T getConstrainable() { + public Property getConstrainable() { return property; } @@ -72,7 +72,7 @@ public boolean equals(Object o) { return false; } - PropertyConstraintLocation that = (PropertyConstraintLocation) o; + PropertyConstraintLocation that = (PropertyConstraintLocation) o; if ( !property.equals( that.property ) ) { return false; From 34af9db3d15ebd804086516697b217cd9bac27d5 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 8 Jun 2018 19:17:29 +0200 Subject: [PATCH 070/393] HV-1623 Rename a couple of classes to Abstract* --- ... => AbstractPropertyConstraintMappingContextImpl.java} | 6 +++--- .../cfg/context/FieldConstraintMappingContextImpl.java | 4 ++-- .../cfg/context/GetterConstraintMappingContextImpl.java | 4 ++-- .../cfg/context/TypeConstraintMappingContextImpl.java | 8 ++++---- .../validationcontext/PropertyValidationContext.java | 6 +++--- ...rtyCascadable.java => AbstractPropertyCascadable.java} | 6 +++--- .../internal/metadata/aggregated/FieldCascadable.java | 4 ++-- .../internal/metadata/aggregated/GetterCascadable.java | 4 ++-- .../internal/metadata/aggregated/PropertyMetaData.java | 2 +- ...ation.java => AbstractPropertyConstraintLocation.java} | 6 +++--- .../internal/metadata/location/ConstraintLocation.java | 2 +- .../metadata/location/FieldConstraintLocation.java | 2 +- .../metadata/location/GetterConstraintLocation.java | 2 +- 13 files changed, 28 insertions(+), 28 deletions(-) rename engine/src/main/java/org/hibernate/validator/internal/cfg/context/{PropertyConstraintMappingContextImpl.java => AbstractPropertyConstraintMappingContextImpl.java} (92%) rename engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/{PropertyCascadable.java => AbstractPropertyCascadable.java} (93%) rename engine/src/main/java/org/hibernate/validator/internal/metadata/location/{PropertyConstraintLocation.java => AbstractPropertyConstraintLocation.java} (88%) diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/AbstractPropertyConstraintMappingContextImpl.java similarity index 92% rename from engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java rename to engine/src/main/java/org/hibernate/validator/internal/cfg/context/AbstractPropertyConstraintMappingContextImpl.java index 61f65e2fd7..7d0e67ec4e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/PropertyConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/AbstractPropertyConstraintMappingContextImpl.java @@ -28,7 +28,7 @@ * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI * @author Marko Bekhta */ -abstract class PropertyConstraintMappingContextImpl +abstract class AbstractPropertyConstraintMappingContextImpl extends CascadableConstraintMappingContextImplBase implements PropertyConstraintMappingContext { @@ -38,7 +38,7 @@ abstract class PropertyConstraintMappingContextImpl private final T property; private final ConstraintLocation location; - protected PropertyConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, T property, ConstraintLocation location) { + protected AbstractPropertyConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, T property, ConstraintLocation location) { super( typeContext.getConstraintMapping(), property.getType() ); this.typeContext = typeContext; this.property = property; @@ -46,7 +46,7 @@ protected PropertyConstraintMappingContextImpl(TypeConstraintMappingContextImpl< } @Override - protected PropertyConstraintMappingContextImpl getThis() { + protected AbstractPropertyConstraintMappingContextImpl getThis() { return this; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldConstraintMappingContextImpl.java index 04cb100abc..bc77618fb6 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldConstraintMappingContextImpl.java @@ -19,13 +19,13 @@ import org.hibernate.validator.internal.util.TypeResolutionHelper; /** - * An implementation of {@link PropertyConstraintMappingContextImpl} for a field property. + * An implementation of {@link AbstractPropertyConstraintMappingContextImpl} for a field property. * Represents a constraint mapping creational context which allows to configure the constraints * for one of the bean's field properties. * * @author Marko Bekhta */ -final class FieldConstraintMappingContextImpl extends PropertyConstraintMappingContextImpl { +final class FieldConstraintMappingContextImpl extends AbstractPropertyConstraintMappingContextImpl { FieldConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, JavaBeanField javaBeanField) { super( typeContext, javaBeanField, ConstraintLocation.forField( javaBeanField ) ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterConstraintMappingContextImpl.java index ab749aba1f..e78c2534cc 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterConstraintMappingContextImpl.java @@ -18,13 +18,13 @@ import org.hibernate.validator.internal.util.TypeResolutionHelper; /** - * An implementation of {@link PropertyConstraintMappingContextImpl} for a getter property. + * An implementation of {@link AbstractPropertyConstraintMappingContextImpl} for a getter property. * Represents a constraint mapping creational context which allows to configure the constraints * for one of the bean's getter properties. * * @author Marko Bekhta */ -final class GetterConstraintMappingContextImpl extends PropertyConstraintMappingContextImpl { +final class GetterConstraintMappingContextImpl extends AbstractPropertyConstraintMappingContextImpl { GetterConstraintMappingContextImpl(TypeConstraintMappingContextImpl typeContext, JavaBeanGetter javaBeanGetter) { super( typeContext, javaBeanGetter, ConstraintLocation.forGetter( javaBeanGetter ) ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java index aa73b50aff..0b7b01d7a1 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java @@ -69,7 +69,7 @@ public final class TypeConstraintMappingContextImpl extends ConstraintMapping private final Class beanClass; private final Set executableContexts = newHashSet(); - private final Set propertyContexts = newHashSet(); + private final Set propertyContexts = newHashSet(); private final Set configuredMembers = newHashSet(); private List> defaultGroupSequence; @@ -146,7 +146,7 @@ public PropertyConstraintMappingContext field(String property) { throw LOG.getPropertyHasAlreadyBeConfiguredViaProgrammaticApiException( beanClass, property ); } - PropertyConstraintMappingContextImpl context = new FieldConstraintMappingContextImpl( this, javaBeanField ); + AbstractPropertyConstraintMappingContextImpl context = new FieldConstraintMappingContextImpl( this, javaBeanField ); configuredMembers.add( javaBeanField ); propertyContexts.add( context ); return context; @@ -166,7 +166,7 @@ public PropertyConstraintMappingContext getter(String property) { throw LOG.getPropertyHasAlreadyBeConfiguredViaProgrammaticApiException( beanClass, property ); } - PropertyConstraintMappingContextImpl context = new GetterConstraintMappingContextImpl( this, javaBeanGetter ); + AbstractPropertyConstraintMappingContextImpl context = new GetterConstraintMappingContextImpl( this, javaBeanGetter ); configuredMembers.add( javaBeanGetter ); propertyContexts.add( context ); return context; @@ -258,7 +258,7 @@ private Set buildConstraintElements(ConstraintHelper constra } //properties - for ( PropertyConstraintMappingContextImpl propertyContext : propertyContexts ) { + for ( AbstractPropertyConstraintMappingContextImpl propertyContext : propertyContexts ) { elements.add( propertyContext.build( constraintHelper, typeResolutionHelper, valueExtractorManager ) ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java index c16acc1deb..eabacdfc2d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java @@ -23,7 +23,7 @@ import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.metadata.location.PropertyConstraintLocation; +import org.hibernate.validator.internal.metadata.location.AbstractPropertyConstraintLocation; import org.hibernate.validator.internal.metadata.location.TypeArgumentConstraintLocation; /** @@ -71,8 +71,8 @@ private String getPropertyName(ConstraintLocation location) { location = ( (TypeArgumentConstraintLocation) location ).getOuterDelegate(); } - if ( location instanceof PropertyConstraintLocation ) { - return ( (PropertyConstraintLocation) location ).getPropertyName(); + if ( location instanceof AbstractPropertyConstraintLocation ) { + return ( (AbstractPropertyConstraintLocation) location ).getPropertyName(); } return null; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractPropertyCascadable.java similarity index 93% rename from engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyCascadable.java rename to engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractPropertyCascadable.java index a8acce09d0..3585f69cab 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyCascadable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractPropertyCascadable.java @@ -15,18 +15,18 @@ import org.hibernate.validator.internal.properties.Property; /** - * A {@link Cascadable} backed by a field of a Java bean. + * A {@link Cascadable} backed by a property of a Java bean. * * @author Gunnar Morling * @author Marko Bekhta */ -public abstract class PropertyCascadable implements Cascadable { +public abstract class AbstractPropertyCascadable implements Cascadable { private final Property property; private final Type cascadableType; private final CascadingMetaData cascadingMetaData; - PropertyCascadable(Property property, CascadingMetaData cascadingMetaData) { + AbstractPropertyCascadable(Property property, CascadingMetaData cascadingMetaData) { this.property = property; this.cascadableType = property.getType(); this.cascadingMetaData = cascadingMetaData; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java index 7021170530..e0d5fc48eb 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java @@ -17,7 +17,7 @@ * @author Gunnar Morling * @author Marko Bekhta */ -public class FieldCascadable extends PropertyCascadable { +public class FieldCascadable extends AbstractPropertyCascadable { FieldCascadable(Property property, CascadingMetaData cascadingMetaData) { super( property, cascadingMetaData ); @@ -28,7 +28,7 @@ public ConstraintLocationKind getConstraintLocationKind() { return ConstraintLocationKind.FIELD; } - public static class Builder extends PropertyCascadable.Builder { + public static class Builder extends AbstractPropertyCascadable.Builder { protected Builder(ValueExtractorManager valueExtractorManager, Property property, CascadingMetaDataBuilder cascadingMetaDataBuilder) { super( valueExtractorManager, property, cascadingMetaDataBuilder ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java index ea3a398349..8998a6ef1b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java @@ -17,7 +17,7 @@ * @author Gunnar Morling * @author Marko Bekhta */ -public class GetterCascadable extends PropertyCascadable { +public class GetterCascadable extends AbstractPropertyCascadable { GetterCascadable(Property property, CascadingMetaData cascadingMetaData) { super( property, cascadingMetaData ); @@ -28,7 +28,7 @@ public ConstraintLocationKind getConstraintLocationKind() { return ConstraintLocationKind.GETTER; } - public static class Builder extends PropertyCascadable.Builder { + public static class Builder extends AbstractPropertyCascadable.Builder { protected Builder(ValueExtractorManager valueExtractorManager, Property property, CascadingMetaDataBuilder cascadingMetaDataBuilder) { super( valueExtractorManager, property, cascadingMetaDataBuilder ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java index c630c6bfb8..8ca3acca2a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java @@ -198,7 +198,7 @@ public final void add(ConstrainedElement constrainedElement) { Property property = constrainable.get().as( Property.class ); Cascadable.Builder builder = cascadableBuilders.get( property ); if ( builder == null ) { - builder = PropertyCascadable.Builder.builder( constrainedElement.getKind(), valueExtractorManager, property, constrainedElement.getCascadingMetaDataBuilder() ); + builder = AbstractPropertyCascadable.Builder.builder( constrainedElement.getKind(), valueExtractorManager, property, constrainedElement.getCascadingMetaDataBuilder() ); cascadableBuilders.put( property, builder ); } else { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java similarity index 88% rename from engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java rename to engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java index 907b03fbe0..edaf2d2c95 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/PropertyConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java @@ -18,14 +18,14 @@ * @author Marko Bekhta * @author Guillaume Smet */ -public abstract class PropertyConstraintLocation implements ConstraintLocation { +public abstract class AbstractPropertyConstraintLocation implements ConstraintLocation { /** * The member the constraint was defined on. */ private final Property property; - PropertyConstraintLocation(Property property) { + AbstractPropertyConstraintLocation(Property property) { this.property = property; } @@ -72,7 +72,7 @@ public boolean equals(Object o) { return false; } - PropertyConstraintLocation that = (PropertyConstraintLocation) o; + AbstractPropertyConstraintLocation that = (AbstractPropertyConstraintLocation) o; if ( !property.equals( that.property ) ) { return false; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java index 2a9a90d283..d3337e6ca2 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java @@ -94,7 +94,7 @@ static ConstraintLocation forParameter(Callable callable, int index) { /** * Obtains the value of this location from the parent. The type of the passed parent depends on the location type, - * e.g. a bean would be passed for a {@link PropertyConstraintLocation} but an + * e.g. a bean would be passed for a {@link AbstractPropertyConstraintLocation} but an * object array for a {@link ParameterConstraintLocation}. */ Object getValue(Object parent); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java index 594ae9dbef..aa64c61f96 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java @@ -13,7 +13,7 @@ * * @author Marko Bekhta */ -public class FieldConstraintLocation extends PropertyConstraintLocation { +public class FieldConstraintLocation extends AbstractPropertyConstraintLocation { FieldConstraintLocation(Property field) { super( field ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java index 07ab3ecbbd..4327813096 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java @@ -13,7 +13,7 @@ * * @author Marko Bekhta */ -public class GetterConstraintLocation extends PropertyConstraintLocation { +public class GetterConstraintLocation extends AbstractPropertyConstraintLocation { GetterConstraintLocation(Property getter) { super( getter ); From 1355dceb2d024c962c2553c1c425ed73e0083c02 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 8 Jun 2018 20:05:23 +0200 Subject: [PATCH 071/393] HV-1623 Introduce Field and Getter as subclasses of Property --- ...tPropertyConstraintMappingContextImpl.java | 2 +- .../TypeConstraintMappingContextImpl.java | 8 +++--- .../PropertyValidationContext.java | 2 +- .../AbstractPropertyCascadable.java | 28 ++++++++++--------- .../metadata/aggregated/FieldCascadable.java | 18 ++++++------ .../metadata/aggregated/GetterCascadable.java | 18 ++++++------ .../metadata/aggregated/PropertyMetaData.java | 11 ++++---- .../AbstractPropertyConstraintLocation.java | 12 ++++---- .../metadata/location/ConstraintLocation.java | 8 +++--- .../location/FieldConstraintLocation.java | 6 ++-- .../location/GetterConstraintLocation.java | 6 ++-- .../metadata/raw/ConstrainedField.java | 20 ++++++------- .../internal/properties/Callable.java | 3 -- .../internal/properties/Constrainable.java | 4 +++ .../validator/internal/properties/Field.java | 20 +++++++++++++ .../validator/internal/properties/Getter.java | 20 +++++++++++++ .../properties/javabean/JavaBeanField.java | 3 +- .../properties/javabean/JavaBeanGetter.java | 4 +-- .../test/cfg/ConstraintMappingTest.java | 2 +- .../AnnotationMetaDataProviderTestBase.java | 2 +- 20 files changed, 120 insertions(+), 77 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/Field.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/Getter.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/AbstractPropertyConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/AbstractPropertyConstraintMappingContextImpl.java index 7d0e67ec4e..1cab16b832 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/AbstractPropertyConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/AbstractPropertyConstraintMappingContextImpl.java @@ -46,7 +46,7 @@ protected AbstractPropertyConstraintMappingContextImpl(TypeConstraintMappingCont } @Override - protected AbstractPropertyConstraintMappingContextImpl getThis() { + protected AbstractPropertyConstraintMappingContextImpl getThis() { return this; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java index 0b7b01d7a1..2b5c270ad4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java @@ -69,7 +69,7 @@ public final class TypeConstraintMappingContextImpl extends ConstraintMapping private final Class beanClass; private final Set executableContexts = newHashSet(); - private final Set propertyContexts = newHashSet(); + private final Set> propertyContexts = newHashSet(); private final Set configuredMembers = newHashSet(); private List> defaultGroupSequence; @@ -146,7 +146,7 @@ public PropertyConstraintMappingContext field(String property) { throw LOG.getPropertyHasAlreadyBeConfiguredViaProgrammaticApiException( beanClass, property ); } - AbstractPropertyConstraintMappingContextImpl context = new FieldConstraintMappingContextImpl( this, javaBeanField ); + FieldConstraintMappingContextImpl context = new FieldConstraintMappingContextImpl( this, javaBeanField ); configuredMembers.add( javaBeanField ); propertyContexts.add( context ); return context; @@ -166,7 +166,7 @@ public PropertyConstraintMappingContext getter(String property) { throw LOG.getPropertyHasAlreadyBeConfiguredViaProgrammaticApiException( beanClass, property ); } - AbstractPropertyConstraintMappingContextImpl context = new GetterConstraintMappingContextImpl( this, javaBeanGetter ); + GetterConstraintMappingContextImpl context = new GetterConstraintMappingContextImpl( this, javaBeanGetter ); configuredMembers.add( javaBeanGetter ); propertyContexts.add( context ); return context; @@ -258,7 +258,7 @@ private Set buildConstraintElements(ConstraintHelper constra } //properties - for ( AbstractPropertyConstraintMappingContextImpl propertyContext : propertyContexts ) { + for ( AbstractPropertyConstraintMappingContextImpl propertyContext : propertyContexts ) { elements.add( propertyContext.build( constraintHelper, typeResolutionHelper, valueExtractorManager ) ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java index eabacdfc2d..ba79e43a76 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java @@ -72,7 +72,7 @@ private String getPropertyName(ConstraintLocation location) { } if ( location instanceof AbstractPropertyConstraintLocation ) { - return ( (AbstractPropertyConstraintLocation) location ).getPropertyName(); + return ( (AbstractPropertyConstraintLocation) location ).getPropertyName(); } return null; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractPropertyCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractPropertyCascadable.java index 3585f69cab..6eaa887574 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractPropertyCascadable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractPropertyCascadable.java @@ -11,7 +11,8 @@ import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.facets.Cascadable; -import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; +import org.hibernate.validator.internal.properties.Field; +import org.hibernate.validator.internal.properties.Getter; import org.hibernate.validator.internal.properties.Property; /** @@ -20,13 +21,13 @@ * @author Gunnar Morling * @author Marko Bekhta */ -public abstract class AbstractPropertyCascadable implements Cascadable { +public abstract class AbstractPropertyCascadable implements Cascadable { - private final Property property; + private final T property; private final Type cascadableType; private final CascadingMetaData cascadingMetaData; - AbstractPropertyCascadable(Property property, CascadingMetaData cascadingMetaData) { + AbstractPropertyCascadable(T property, CascadingMetaData cascadingMetaData) { this.property = property; this.cascadableType = property.getType(); this.cascadingMetaData = cascadingMetaData; @@ -52,13 +53,13 @@ public CascadingMetaData getCascadingMetaData() { return cascadingMetaData; } - public abstract static class Builder implements Cascadable.Builder { + public abstract static class AbstractBuilder implements Cascadable.Builder { private final ValueExtractorManager valueExtractorManager; - private final Property property; + private final T property; private CascadingMetaDataBuilder cascadingMetaDataBuilder; - protected Builder(ValueExtractorManager valueExtractorManager, Property property, CascadingMetaDataBuilder cascadingMetaDataBuilder) { + protected AbstractBuilder(ValueExtractorManager valueExtractorManager, T property, CascadingMetaDataBuilder cascadingMetaDataBuilder) { this.valueExtractorManager = valueExtractorManager; this.property = property; this.cascadingMetaDataBuilder = cascadingMetaDataBuilder; @@ -74,14 +75,15 @@ public Cascadable build() { return create( property, cascadingMetaDataBuilder.build( valueExtractorManager, property ) ); } - protected abstract Cascadable create(Property property, CascadingMetaData build); + protected abstract Cascadable create(T property, CascadingMetaData build); - public static Cascadable.Builder builder(ConstrainedElementKind constrainedElementKind, ValueExtractorManager valueExtractorManager, Property property, CascadingMetaDataBuilder cascadingMetaDataBuilder) { - if ( ConstrainedElementKind.FIELD == constrainedElementKind ) { - return new FieldCascadable.Builder( valueExtractorManager, property, cascadingMetaDataBuilder ); + public static Cascadable.Builder builder(ValueExtractorManager valueExtractorManager, Property property, + CascadingMetaDataBuilder cascadingMetaDataBuilder) { + if ( property instanceof Field ) { + return new FieldCascadable.Builder( valueExtractorManager, (Field) property, cascadingMetaDataBuilder ); } - else if ( ConstrainedElementKind.GETTER == constrainedElementKind ) { - return new GetterCascadable.Builder( valueExtractorManager, property, cascadingMetaDataBuilder ); + else if ( property instanceof Getter ) { + return new GetterCascadable.Builder( valueExtractorManager, (Getter) property, cascadingMetaDataBuilder ); } throw new IllegalStateException( "It should be either a field or a getter." ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java index e0d5fc48eb..c8ebe21304 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/FieldCascadable.java @@ -9,7 +9,7 @@ import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.facets.Cascadable; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; -import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.Field; /** * A {@link Cascadable} backed by a field of a Java bean. @@ -17,10 +17,10 @@ * @author Gunnar Morling * @author Marko Bekhta */ -public class FieldCascadable extends AbstractPropertyCascadable { +public class FieldCascadable extends AbstractPropertyCascadable { - FieldCascadable(Property property, CascadingMetaData cascadingMetaData) { - super( property, cascadingMetaData ); + FieldCascadable(Field field, CascadingMetaData cascadingMetaData) { + super( field, cascadingMetaData ); } @Override @@ -28,15 +28,15 @@ public ConstraintLocationKind getConstraintLocationKind() { return ConstraintLocationKind.FIELD; } - public static class Builder extends AbstractPropertyCascadable.Builder { + public static class Builder extends AbstractPropertyCascadable.AbstractBuilder { - protected Builder(ValueExtractorManager valueExtractorManager, Property property, CascadingMetaDataBuilder cascadingMetaDataBuilder) { - super( valueExtractorManager, property, cascadingMetaDataBuilder ); + protected Builder(ValueExtractorManager valueExtractorManager, Field field, CascadingMetaDataBuilder cascadingMetaDataBuilder) { + super( valueExtractorManager, field, cascadingMetaDataBuilder ); } @Override - protected Cascadable create(Property property, CascadingMetaData cascadingMetaData) { - return new FieldCascadable( property, cascadingMetaData ); + protected Cascadable create(Field field, CascadingMetaData cascadingMetaData) { + return new FieldCascadable( field, cascadingMetaData ); } } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java index 8998a6ef1b..ab5da7d89f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/GetterCascadable.java @@ -9,7 +9,7 @@ import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.facets.Cascadable; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; -import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.Getter; /** * A {@link Cascadable} backed by a getter of a Java bean. @@ -17,10 +17,10 @@ * @author Gunnar Morling * @author Marko Bekhta */ -public class GetterCascadable extends AbstractPropertyCascadable { +public class GetterCascadable extends AbstractPropertyCascadable { - GetterCascadable(Property property, CascadingMetaData cascadingMetaData) { - super( property, cascadingMetaData ); + GetterCascadable(Getter getter, CascadingMetaData cascadingMetaData) { + super( getter, cascadingMetaData ); } @Override @@ -28,15 +28,15 @@ public ConstraintLocationKind getConstraintLocationKind() { return ConstraintLocationKind.GETTER; } - public static class Builder extends AbstractPropertyCascadable.Builder { + public static class Builder extends AbstractPropertyCascadable.AbstractBuilder { - protected Builder(ValueExtractorManager valueExtractorManager, Property property, CascadingMetaDataBuilder cascadingMetaDataBuilder) { - super( valueExtractorManager, property, cascadingMetaDataBuilder ); + protected Builder(ValueExtractorManager valueExtractorManager, Getter getter, CascadingMetaDataBuilder cascadingMetaDataBuilder) { + super( valueExtractorManager, getter, cascadingMetaDataBuilder ); } @Override - protected Cascadable create(Property property, CascadingMetaData cascadingMetaData) { - return new GetterCascadable( property, cascadingMetaData ); + protected Cascadable create(Getter getter, CascadingMetaData cascadingMetaData) { + return new GetterCascadable( getter, cascadingMetaData ); } } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java index 8ca3acca2a..36dd79ca76 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java @@ -162,8 +162,8 @@ public Builder(Class beanClass, ConstrainedField constrainedProperty, Constra ValueExtractorManager valueExtractorManager) { super( beanClass, constraintHelper, typeResolutionHelper, valueExtractorManager ); - this.propertyName = constrainedProperty.getProperty().getName(); - this.propertyType = constrainedProperty.getProperty().getType(); + this.propertyName = constrainedProperty.getField().getName(); + this.propertyType = constrainedProperty.getField().getType(); add( constrainedProperty ); } @@ -198,7 +198,8 @@ public final void add(ConstrainedElement constrainedElement) { Property property = constrainable.get().as( Property.class ); Cascadable.Builder builder = cascadableBuilders.get( property ); if ( builder == null ) { - builder = AbstractPropertyCascadable.Builder.builder( constrainedElement.getKind(), valueExtractorManager, property, constrainedElement.getCascadingMetaDataBuilder() ); + builder = AbstractPropertyCascadable.AbstractBuilder.builder( valueExtractorManager, property, + constrainedElement.getCascadingMetaDataBuilder() ); cascadableBuilders.put( property, builder ); } else { @@ -211,7 +212,7 @@ public final void add(ConstrainedElement constrainedElement) { private Optional getConstrainableFromConstrainedElement(ConstrainedElement constrainedElement) { if ( constrainedElement.getKind() == ConstrainedElementKind.FIELD ) { if ( constrainedElement instanceof ConstrainedField ) { - return Optional.of( ( (ConstrainedField) constrainedElement ).getProperty() ); + return Optional.of( ( (ConstrainedField) constrainedElement ).getField() ); } else { LOG.getUnexpectedConstraintElementType( ConstrainedField.class, constrainedElement.getClass() ); @@ -298,7 +299,7 @@ private MetaConstraint withGetterLocation(ConstraintLocation getterConstraint private String getPropertyName(ConstrainedElement constrainedElement) { if ( constrainedElement.getKind() == ConstrainedElementKind.FIELD ) { - return ( (ConstrainedField) constrainedElement ).getProperty().getPropertyName(); + return ( (ConstrainedField) constrainedElement ).getField().getPropertyName(); } else if ( constrainedElement.getKind() == ConstrainedElementKind.GETTER ) { return ( (ConstrainedExecutable) constrainedElement ).getCallable().as( Property.class ).getPropertyName(); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java index edaf2d2c95..d57de16325 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java @@ -18,14 +18,14 @@ * @author Marko Bekhta * @author Guillaume Smet */ -public abstract class AbstractPropertyConstraintLocation implements ConstraintLocation { +public abstract class AbstractPropertyConstraintLocation implements ConstraintLocation { /** - * The member the constraint was defined on. + * The property the constraint was defined on. */ - private final Property property; + private final T property; - AbstractPropertyConstraintLocation(Property property) { + AbstractPropertyConstraintLocation(T property) { this.property = property; } @@ -35,7 +35,7 @@ public Class getDeclaringClass() { } @Override - public Property getConstrainable() { + public T getConstrainable() { return property; } @@ -72,7 +72,7 @@ public boolean equals(Object o) { return false; } - AbstractPropertyConstraintLocation that = (AbstractPropertyConstraintLocation) o; + AbstractPropertyConstraintLocation that = (AbstractPropertyConstraintLocation) o; if ( !property.equals( that.property ) ) { return false; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java index d3337e6ca2..0084fbdde5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java @@ -15,8 +15,8 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Constrainable; -import org.hibernate.validator.internal.properties.javabean.JavaBeanField; -import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; +import org.hibernate.validator.internal.properties.Field; +import org.hibernate.validator.internal.properties.Getter; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; /** @@ -42,11 +42,11 @@ static ConstraintLocation forClass(Class declaringClass) { return new BeanConstraintLocation( declaringClass ); } - static ConstraintLocation forField(JavaBeanField field) { + static ConstraintLocation forField(Field field) { return new FieldConstraintLocation( field ); } - static ConstraintLocation forGetter(JavaBeanGetter getter) { + static ConstraintLocation forGetter(Getter getter) { return new GetterConstraintLocation( getter ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java index aa64c61f96..d7639c0646 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/FieldConstraintLocation.java @@ -6,16 +6,16 @@ */ package org.hibernate.validator.internal.metadata.location; -import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.Field; /** * Field property constraint location. * * @author Marko Bekhta */ -public class FieldConstraintLocation extends AbstractPropertyConstraintLocation { +public class FieldConstraintLocation extends AbstractPropertyConstraintLocation { - FieldConstraintLocation(Property field) { + FieldConstraintLocation(Field field) { super( field ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java index 4327813096..2dee31bf03 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/GetterConstraintLocation.java @@ -6,16 +6,16 @@ */ package org.hibernate.validator.internal.metadata.location; -import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.Getter; /** * Getter property constraint location. * * @author Marko Bekhta */ -public class GetterConstraintLocation extends AbstractPropertyConstraintLocation { +public class GetterConstraintLocation extends AbstractPropertyConstraintLocation { - GetterConstraintLocation(Property getter) { + GetterConstraintLocation(Getter getter) { super( getter ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedField.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedField.java index e9f996c89f..143ad0fcc0 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedField.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/raw/ConstrainedField.java @@ -10,7 +10,7 @@ import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; import org.hibernate.validator.internal.metadata.core.MetaConstraint; -import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.Field; /** * Represents a field of a Java type and all its associated meta-data relevant @@ -22,41 +22,41 @@ */ public class ConstrainedField extends AbstractConstrainedElement { - private final Property property; + private final Field field; /** * Creates a new field meta data object. * * @param source The source of meta data. - * @param property The represented field. + * @param field The represented field. * @param constraints The constraints of the represented field, if any. * @param typeArgumentConstraints Type arguments constraints, if any. * @param cascadingMetaDataBuilder The cascaded validation metadata for this element and its container elements. */ public ConstrainedField(ConfigurationSource source, - Property property, + Field field, Set> constraints, Set> typeArgumentConstraints, CascadingMetaDataBuilder cascadingMetaDataBuilder) { super( source, ConstrainedElementKind.FIELD, constraints, typeArgumentConstraints, cascadingMetaDataBuilder ); - this.property = property; + this.field = field; } - public Property getProperty() { - return property; + public Field getField() { + return field; } @Override public String toString() { - return "ConstrainedField [property=" + property.getName() + "]"; + return "ConstrainedField [field=" + field.getName() + "]"; } @Override public int hashCode() { int result = super.hashCode(); - result = 31 * result + this.property.hashCode(); + result = 31 * result + this.field.hashCode(); return result; } @@ -72,6 +72,6 @@ public boolean equals(Object obj) { return false; } ConstrainedField other = (ConstrainedField) obj; - return this.property.equals( other.property ); + return this.field.equals( other.field ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/Callable.java b/engine/src/main/java/org/hibernate/validator/internal/properties/Callable.java index 2e72191a1d..9ef259f46d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/Callable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/Callable.java @@ -8,7 +8,6 @@ import java.lang.reflect.Type; -import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; @@ -32,8 +31,6 @@ public interface Callable extends Constrainable { boolean isPrivate(); - ConstrainedElementKind getConstrainedElementKind(); - String getSignature(); boolean overrides(ExecutableHelper executableHelper, Callable superTypeMethod); diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/Constrainable.java b/engine/src/main/java/org/hibernate/validator/internal/properties/Constrainable.java index 871ef7f911..8e2be2e24a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/Constrainable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/Constrainable.java @@ -8,6 +8,8 @@ import java.lang.reflect.Type; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; + /** * An element on which it is possible to define constraints (e.g. a JavaBean property, a JavaBean method, a JSON * property). @@ -24,6 +26,8 @@ public interface Constrainable { Type getType(); + ConstrainedElementKind getConstrainedElementKind(); + @SuppressWarnings("unchecked") default T as(Class clazz) { return ( (T) this ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/Field.java b/engine/src/main/java/org/hibernate/validator/internal/properties/Field.java new file mode 100644 index 0000000000..65d72330da --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/Field.java @@ -0,0 +1,20 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.properties; + +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; + +/** + * @author Guillaume Smet + */ +public interface Field extends Property { + + @Override + default ConstrainedElementKind getConstrainedElementKind() { + return ConstrainedElementKind.FIELD; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/Getter.java b/engine/src/main/java/org/hibernate/validator/internal/properties/Getter.java new file mode 100644 index 0000000000..fede3102bd --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/Getter.java @@ -0,0 +1,20 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.properties; + +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; + +/** + * @author Guillaume Smet + */ +public interface Getter extends Property { + + @Override + default ConstrainedElementKind getConstrainedElementKind() { + return ConstrainedElementKind.GETTER; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java index c6013a8de0..d966cceb27 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java @@ -15,14 +15,13 @@ import java.security.PrivilegedAction; import org.hibernate.validator.HibernateValidatorPermission; -import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredField; /** * @author Marko Bekhta */ -public class JavaBeanField implements Property, JavaBeanAnnotatedConstrainable { +public class JavaBeanField implements org.hibernate.validator.internal.properties.Field, JavaBeanAnnotatedConstrainable { private final Field field; private final String name; diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java index 722da007d5..82f13915f0 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java @@ -12,7 +12,7 @@ import org.hibernate.validator.HibernateValidatorPermission; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; -import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.Getter; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethod; @@ -20,7 +20,7 @@ /** * @author Marko Bekhta */ -public class JavaBeanGetter extends JavaBeanMethod implements Property { +public class JavaBeanGetter extends JavaBeanMethod implements Getter { private final String name; diff --git a/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java b/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java index 73f9d1632b..d1924b6bfb 100644 --- a/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java @@ -579,7 +579,7 @@ private BeanConfiguration getBeanConfiguration(Class type) { private ConstrainedField getConstrainedField(BeanConfiguration beanConfiguration, String fieldName) { for ( ConstrainedElement constrainedElement : beanConfiguration.getConstrainedElements() ) { if ( constrainedElement.getKind() == ConstrainedElementKind.FIELD && - ( (ConstrainedField) constrainedElement ).getProperty().getPropertyName().equals( fieldName ) ) { + ( (ConstrainedField) constrainedElement ).getField().getPropertyName().equals( fieldName ) ) { return (ConstrainedField) constrainedElement; } } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTestBase.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTestBase.java index 7a9e68def8..bf6f716428 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTestBase.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTestBase.java @@ -77,7 +77,7 @@ protected ConstrainedElement findConstrainedElement(BeanConfiguration beanCon } } else if ( constrainedElement instanceof ConstrainedField ) { - if ( constrainable.equals( ( (ConstrainedField) constrainedElement ).getProperty() ) ) { + if ( constrainable.equals( ( (ConstrainedField) constrainedElement ).getField() ) ) { return constrainedElement; } } From 70f52adb38250083264a40863ea45a278659f415 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Sat, 9 Jun 2018 10:40:06 +0200 Subject: [PATCH 072/393] HV-1623 Throw exception in case of unexpected constrainedElement class in property metadata - need to throw an exception rather than just create it - removed the usage of Optional as it isn't needed anymore --- .../metadata/aggregated/PropertyMetaData.java | 59 +++++++++---------- .../validator/internal/util/logging/Log.java | 5 +- 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java index 36dd79ca76..fffa02635a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java @@ -16,7 +16,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -35,7 +34,7 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; -import org.hibernate.validator.internal.properties.Constrainable; +import org.hibernate.validator.internal.properties.Getter; import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; import org.hibernate.validator.internal.util.CollectionHelper; @@ -192,41 +191,39 @@ public final void add(ConstrainedElement constrainedElement) { if ( constrainedElement.getCascadingMetaDataBuilder().isMarkedForCascadingOnAnnotatedObjectOrContainerElements() || constrainedElement.getCascadingMetaDataBuilder().hasGroupConversionsOnAnnotatedObjectOrContainerElements() ) { - Optional constrainable = getConstrainableFromConstrainedElement( constrainedElement ); + Property property = getConstrainableFromConstrainedElement( constrainedElement ); - if ( constrainable.isPresent() ) { - Property property = constrainable.get().as( Property.class ); - Cascadable.Builder builder = cascadableBuilders.get( property ); - if ( builder == null ) { - builder = AbstractPropertyCascadable.AbstractBuilder.builder( valueExtractorManager, property, - constrainedElement.getCascadingMetaDataBuilder() ); - cascadableBuilders.put( property, builder ); - } - else { - builder.mergeCascadingMetaData( constrainedElement.getCascadingMetaDataBuilder() ); - } - } - } - } - - private Optional getConstrainableFromConstrainedElement(ConstrainedElement constrainedElement) { - if ( constrainedElement.getKind() == ConstrainedElementKind.FIELD ) { - if ( constrainedElement instanceof ConstrainedField ) { - return Optional.of( ( (ConstrainedField) constrainedElement ).getField() ); + Cascadable.Builder builder = cascadableBuilders.get( property ); + if ( builder == null ) { + builder = AbstractPropertyCascadable.AbstractBuilder.builder( valueExtractorManager, property, + constrainedElement.getCascadingMetaDataBuilder() ); + cascadableBuilders.put( property, builder ); } else { - LOG.getUnexpectedConstraintElementType( ConstrainedField.class, constrainedElement.getClass() ); + builder.mergeCascadingMetaData( constrainedElement.getCascadingMetaDataBuilder() ); } } - else if ( constrainedElement.getKind() == ConstrainedElementKind.GETTER ) { - if ( constrainedElement instanceof ConstrainedExecutable ) { - return Optional.of( ( (ConstrainedExecutable) constrainedElement ).getCallable() ); - } - else { - LOG.getUnexpectedConstraintElementType( ConstrainedExecutable.class, constrainedElement.getClass() ); - } + } + + private Property getConstrainableFromConstrainedElement(ConstrainedElement constrainedElement) { + switch ( constrainedElement.getKind() ) { + case FIELD: + if ( constrainedElement instanceof ConstrainedField ) { + return ( (ConstrainedField) constrainedElement ).getField(); + } + else { + throw LOG.getUnexpectedConstraintElementType( ConstrainedField.class, constrainedElement.getClass() ); + } + case GETTER: + if ( constrainedElement instanceof ConstrainedExecutable ) { + return ( (ConstrainedExecutable) constrainedElement ).getCallable().as( Getter.class ); + } + else { + throw LOG.getUnexpectedConstraintElementType( ConstrainedExecutable.class, constrainedElement.getClass() ); + } + default: + throw LOG.getUnsupportedConstraintElementType( constrainedElement.getKind() ); } - return Optional.empty(); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 4267ee49e0..7a0da1e309 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -48,6 +48,7 @@ import org.hibernate.validator.internal.engine.messageinterpolation.parser.MessageDescriptorFormatException; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.util.logging.formatter.ArrayOfClassesObjectFormatter; @@ -861,6 +862,6 @@ ConstraintDefinitionException getConstraintValidatorDefinitionConstraintMismatch @Message(id = 244, value = "ConstrainedElement expected class was %1$s, but instead received %2$s.") AssertionError getUnexpectedConstraintElementType(@FormatWith(ClassObjectFormatter.class) Class expecting, @FormatWith(ClassObjectFormatter.class) Class got); - @Message(id = 245, value = "Allowed ElementTypes are %2$s, but instead received %1$s.") - AssertionError getUnexpectedElementType(ElementType received, @FormatWith(ObjectArrayFormatter.class) ElementType... got); + @Message(id = 245, value = "Allowed constraint element types are FIELD and GETTER, but instead received %1$s.") + AssertionError getUnsupportedConstraintElementType(ConstrainedElement.ConstrainedElementKind kind); } From 8130f3923201cc73bff7fcf093cf7de54ba5737c Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Sat, 9 Jun 2018 14:17:11 +0200 Subject: [PATCH 073/393] HV-1623 Make the fields/getters accessible lazily --- .../AbstractPropertyCascadable.java | 5 +++- .../AbstractPropertyConstraintLocation.java | 6 +++- .../internal/properties/Property.java | 4 +-- .../internal/properties/PropertyAccessor.java | 15 ++++++++++ .../properties/javabean/JavaBeanField.java | 27 +++++++++++++---- .../properties/javabean/JavaBeanGetter.java | 29 ++++++++++++++----- 6 files changed, 69 insertions(+), 17 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/PropertyAccessor.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractPropertyCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractPropertyCascadable.java index 6eaa887574..1cb08aea79 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractPropertyCascadable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractPropertyCascadable.java @@ -14,6 +14,7 @@ import org.hibernate.validator.internal.properties.Field; import org.hibernate.validator.internal.properties.Getter; import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.PropertyAccessor; /** * A {@link Cascadable} backed by a property of a Java bean. @@ -24,11 +25,13 @@ public abstract class AbstractPropertyCascadable implements Cascadable { private final T property; + private final PropertyAccessor propertyAccessor; private final Type cascadableType; private final CascadingMetaData cascadingMetaData; AbstractPropertyCascadable(T property, CascadingMetaData cascadingMetaData) { this.property = property; + this.propertyAccessor = property.createAccessor(); this.cascadableType = property.getType(); this.cascadingMetaData = cascadingMetaData; } @@ -40,7 +43,7 @@ public Type getCascadableType() { @Override public Object getValue(Object parent) { - return property.getValueFrom( parent ); + return propertyAccessor.getValueFrom( parent ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java index d57de16325..3d7e105ea3 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java @@ -10,6 +10,7 @@ import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.PropertyAccessor; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; /** @@ -25,8 +26,11 @@ public abstract class AbstractPropertyConstraintLocation imp */ private final T property; + private final PropertyAccessor propertyAccessor; + AbstractPropertyConstraintLocation(T property) { this.property = property; + this.propertyAccessor = property.createAccessor(); } @Override @@ -55,7 +59,7 @@ public void appendTo(ExecutableParameterNameProvider parameterNameProvider, Path @Override public Object getValue(Object parent) { - return property.getValueFrom( parent ); + return propertyAccessor.getValueFrom( parent ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/Property.java b/engine/src/main/java/org/hibernate/validator/internal/properties/Property.java index f6f1d4c288..12018421e0 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/Property.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/Property.java @@ -11,7 +11,7 @@ */ public interface Property extends Constrainable { - Object getValueFrom(Object bean); - String getPropertyName(); + + PropertyAccessor createAccessor(); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/PropertyAccessor.java b/engine/src/main/java/org/hibernate/validator/internal/properties/PropertyAccessor.java new file mode 100644 index 0000000000..b269dbb778 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/PropertyAccessor.java @@ -0,0 +1,15 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.properties; + +/** + * @author Guillaume Smet + */ +public interface PropertyAccessor { + + Object getValueFrom(Object bean); +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java index d966cceb27..11b15d7542 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java @@ -15,6 +15,7 @@ import java.security.PrivilegedAction; import org.hibernate.validator.HibernateValidatorPermission; +import org.hibernate.validator.internal.properties.PropertyAccessor; import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredField; @@ -29,7 +30,7 @@ public class JavaBeanField implements org.hibernate.validator.internal.propertie private final Type type; public JavaBeanField(Field field) { - this.field = getAccessible( field ); + this.field = field; this.name = field.getName(); this.type = ReflectionHelper.typeOf( field ); this.typeForValidatorResolution = ReflectionHelper.boxedType( this.type ); @@ -55,11 +56,6 @@ public Type getTypeForValidatorResolution() { return typeForValidatorResolution; } - @Override - public Object getValueFrom(Object bean) { - return ReflectionHelper.getValue( field, bean ); - } - @Override public String getPropertyName() { return getName(); @@ -90,6 +86,11 @@ public TypeVariable[] getTypeParameters() { return field.getType().getTypeParameters(); } + @Override + public PropertyAccessor createAccessor() { + return new FieldAccessor( field ); + } + @Override public boolean equals(Object o) { if ( this == o ) { @@ -127,6 +128,20 @@ public String toString() { return getName(); } + private static class FieldAccessor implements PropertyAccessor { + + private Field accessibleField; + + private FieldAccessor(Field field) { + this.accessibleField = getAccessible( field ); + } + + @Override + public Object getValueFrom(Object bean) { + return ReflectionHelper.getValue( accessibleField, bean ); + } + } + /** * Returns an accessible copy of the given member. */ diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java index 82f13915f0..a7084b1f9e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java @@ -13,6 +13,7 @@ import org.hibernate.validator.HibernateValidatorPermission; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Getter; +import org.hibernate.validator.internal.properties.PropertyAccessor; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethod; @@ -33,22 +34,17 @@ public class JavaBeanGetter extends JavaBeanMethod implements Getter { private final Class declaringClass; public JavaBeanGetter(Method method) { - super( getAccessible( method ) ); + super( method ); this.name = ReflectionHelper.getPropertyName( method ); this.declaringClass = method.getDeclaringClass(); } public JavaBeanGetter(Class declaringClass, Method method) { - super( getAccessible( method ) ); + super( method ); this.name = ReflectionHelper.getPropertyName( method ); this.declaringClass = declaringClass; } - @Override - public Object getValueFrom(Object bean) { - return ReflectionHelper.getValue( executable, bean ); - } - @Override public String getPropertyName() { return name; @@ -81,6 +77,11 @@ public ConstrainedElementKind getConstrainedElementKind() { return ConstrainedElementKind.GETTER; } + @Override + public PropertyAccessor createAccessor() { + return new GetterAccessor( executable ); + } + @Override public boolean equals(Object o) { if ( this == o ) { @@ -105,6 +106,20 @@ public int hashCode() { return result; } + private static class GetterAccessor implements PropertyAccessor { + + private Method accessibleGetter; + + private GetterAccessor(Method getter) { + this.accessibleGetter = getAccessible( getter ); + } + + @Override + public Object getValueFrom(Object bean) { + return ReflectionHelper.getValue( accessibleGetter, bean ); + } + } + /** * Returns an accessible copy of the given method. */ From c0bc36ad88407a0c617935942e17f4a18e3fde2d Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 11 Jun 2018 10:17:11 +0200 Subject: [PATCH 074/393] HV-1623 Reduce the memory footprint of the new reflection abstraction --- .../provider/AnnotationMetaDataProvider.java | 9 +++++---- .../properties/javabean/JavaBeanExecutable.java | 12 +++--------- .../internal/properties/javabean/JavaBeanField.java | 8 +------- .../properties/javabean/JavaBeanParameter.java | 9 +-------- 4 files changed, 10 insertions(+), 28 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java index cac8cb06e7..bb78e18691 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java @@ -424,7 +424,7 @@ private List getParameterMetaData(JavaBeanExecutable ja } } - Set> typeArgumentsConstraints = findTypeAnnotationConstraintsForExecutableParameter( parameter ); + Set> typeArgumentsConstraints = findTypeAnnotationConstraintsForExecutableParameter( javaBeanExecutable, parameter ); CascadingMetaDataBuilder cascadingMetaData = findCascadingMetaData( parameter ); metaData.add( @@ -691,11 +691,12 @@ else if ( annotatedType instanceof AnnotatedParameterizedType ) { * * @return a set of type arguments constraints, or an empty set if no constrained type arguments are found */ - protected Set> findTypeAnnotationConstraintsForExecutableParameter(JavaBeanParameter javaBeanParameter) { + protected Set> findTypeAnnotationConstraintsForExecutableParameter(JavaBeanExecutable javaBeanExecutable, + JavaBeanParameter javaBeanParameter) { try { return findTypeArgumentsConstraints( - javaBeanParameter.getExecutable(), - new TypeArgumentExecutableParameterLocation( javaBeanParameter.getExecutable(), javaBeanParameter.getIndex() ), + javaBeanExecutable, + new TypeArgumentExecutableParameterLocation( javaBeanExecutable, javaBeanParameter.getIndex() ), javaBeanParameter.getAnnotatedType() ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java index 25e181ba23..baec5ef197 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java @@ -34,14 +34,12 @@ public abstract class JavaBeanExecutable implements Callab protected final T executable; private final Type typeForValidatorResolution; - private final String name; private final boolean hasReturnValue; private final Type type; private final List parameters; JavaBeanExecutable(T executable, boolean hasReturnValue) { this.executable = executable; - this.name = executable.getName(); this.type = ReflectionHelper.typeOf( executable ); this.typeForValidatorResolution = ReflectionHelper.boxedType( type ); this.hasReturnValue = hasReturnValue; @@ -54,7 +52,7 @@ public abstract class JavaBeanExecutable implements Callab Type[] genericParameterTypes = executable.getGenericParameterTypes(); for ( int i = 0; i < parameterArray.length; i++ ) { - parameters.add( new JavaBeanParameter( this, i, parameterArray[i], parameterTypes[i], + parameters.add( new JavaBeanParameter( i, parameterArray[i], parameterTypes[i], getParameterGenericType( parameterTypes, genericParameterTypes, i ) ) ); } this.parameters = CollectionHelper.toImmutableList( parameters ); @@ -92,7 +90,7 @@ public boolean hasParameters() { @Override public String getName() { - return name; + return executable.getName(); } @Override @@ -194,9 +192,6 @@ public boolean equals(Object o) { if ( !this.typeForValidatorResolution.equals( that.typeForValidatorResolution ) ) { return false; } - if ( !this.name.equals( that.name ) ) { - return false; - } return this.type.equals( that.type ); } @@ -204,7 +199,6 @@ public boolean equals(Object o) { public int hashCode() { int result = this.executable.hashCode(); result = 31 * result + this.typeForValidatorResolution.hashCode(); - result = 31 * result + this.name.hashCode(); result = 31 * result + ( this.hasReturnValue ? 1 : 0 ); result = 31 * result + this.type.hashCode(); return result; @@ -213,7 +207,7 @@ public int hashCode() { @Override public String toString() { return ExecutableHelper.getExecutableAsString( - getDeclaringClass().getSimpleName() + "#" + name, + getDeclaringClass().getSimpleName() + "#" + executable.getName(), executable.getParameterTypes() ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java index 11b15d7542..647a33a3de 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java @@ -25,20 +25,18 @@ public class JavaBeanField implements org.hibernate.validator.internal.properties.Field, JavaBeanAnnotatedConstrainable { private final Field field; - private final String name; private final Type typeForValidatorResolution; private final Type type; public JavaBeanField(Field field) { this.field = field; - this.name = field.getName(); this.type = ReflectionHelper.typeOf( field ); this.typeForValidatorResolution = ReflectionHelper.boxedType( this.type ); } @Override public String getName() { - return name; + return field.getName(); } @Override @@ -105,9 +103,6 @@ public boolean equals(Object o) { if ( !this.field.equals( that.field ) ) { return false; } - if ( !this.name.equals( that.name ) ) { - return false; - } if ( !this.typeForValidatorResolution.equals( that.typeForValidatorResolution ) ) { return false; } @@ -117,7 +112,6 @@ public boolean equals(Object o) { @Override public int hashCode() { int result = this.field.hashCode(); - result = 31 * result + this.name.hashCode(); result = 31 * result + this.typeForValidatorResolution.hashCode(); result = 31 * result + this.type.hashCode(); return result; diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanParameter.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanParameter.java index 416b842c79..aae74c8e8d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanParameter.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanParameter.java @@ -17,8 +17,6 @@ */ public class JavaBeanParameter implements JavaBeanAnnotatedElement { - private final JavaBeanExecutable executable; - private final int index; private final Parameter parameter; @@ -27,18 +25,13 @@ public class JavaBeanParameter implements JavaBeanAnnotatedElement { private final Type genericType; - JavaBeanParameter(JavaBeanExecutable executable, int index, Parameter parameter, Class type, Type genericType) { - this.executable = executable; + JavaBeanParameter(int index, Parameter parameter, Class type, Type genericType) { this.index = index; this.parameter = parameter; this.type = type; this.genericType = genericType; } - public JavaBeanExecutable getExecutable() { - return executable; - } - public int getIndex() { return index; } From 20a8b1b1f8372c29a49f0bacfbdf672b1aed30ab Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 11 Jun 2018 11:44:50 +0200 Subject: [PATCH 075/393] HV-1631 Avoid doing two lookups in the read methods of AnnotationProcessingOptionsImpl --- .../core/AnnotationProcessingOptionsImpl.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/AnnotationProcessingOptionsImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/AnnotationProcessingOptionsImpl.java index b0746a0bdd..74576e24e1 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/AnnotationProcessingOptionsImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/AnnotationProcessingOptionsImpl.java @@ -60,8 +60,9 @@ public class AnnotationProcessingOptionsImpl implements AnnotationProcessingOpti @Override public boolean areMemberConstraintsIgnoredFor(Constrainable constrainable) { Class clazz = constrainable.getDeclaringClass(); - if ( annotationIgnoredForMembers.containsKey( constrainable ) ) { - return annotationIgnoredForMembers.get( constrainable ); + Boolean annotationIgnoredForMember = annotationIgnoredForMembers.get( constrainable ); + if ( annotationIgnoredForMember != null ) { + return annotationIgnoredForMember; } else { return areAllConstraintAnnotationsIgnoredFor( clazz ); @@ -70,8 +71,9 @@ public boolean areMemberConstraintsIgnoredFor(Constrainable constrainable) { @Override public boolean areReturnValueConstraintsIgnoredFor(Constrainable constrainable) { - if ( annotationIgnoresForReturnValues.containsKey( constrainable ) ) { - return annotationIgnoresForReturnValues.get( constrainable ); + Boolean annotationIgnoreForReturnValue = annotationIgnoresForReturnValues.get( constrainable ); + if ( annotationIgnoreForReturnValue != null ) { + return annotationIgnoreForReturnValue; } else { return areMemberConstraintsIgnoredFor( constrainable ); @@ -80,8 +82,9 @@ public boolean areReturnValueConstraintsIgnoredFor(Constrainable constrainable) @Override public boolean areCrossParameterConstraintsIgnoredFor(Constrainable constrainable) { - if ( annotationIgnoresForCrossParameter.containsKey( constrainable ) ) { - return annotationIgnoresForCrossParameter.get( constrainable ); + Boolean annotationIgnoreForCrossParameter = annotationIgnoresForCrossParameter.get( constrainable ); + if ( annotationIgnoreForCrossParameter != null ) { + return annotationIgnoreForCrossParameter; } else { return areMemberConstraintsIgnoredFor( constrainable ); @@ -91,8 +94,9 @@ public boolean areCrossParameterConstraintsIgnoredFor(Constrainable constrainabl @Override public boolean areParameterConstraintsIgnoredFor(Constrainable constrainable, int index) { ExecutableParameterKey key = new ExecutableParameterKey( constrainable, index ); - if ( annotationIgnoresForMethodParameter.containsKey( key ) ) { - return annotationIgnoresForMethodParameter.get( key ); + Boolean annotationIgnoreForMethodParameter = annotationIgnoresForMethodParameter.get( key ); + if ( annotationIgnoreForMethodParameter != null ) { + return annotationIgnoreForMethodParameter; } else { return areMemberConstraintsIgnoredFor( constrainable ); @@ -102,8 +106,9 @@ public boolean areParameterConstraintsIgnoredFor(Constrainable constrainable, in @Override public boolean areClassLevelConstraintsIgnoredFor(Class clazz) { boolean ignoreAnnotation; - if ( annotationIgnoresForClasses.containsKey( clazz ) ) { - ignoreAnnotation = annotationIgnoresForClasses.get( clazz ); + Boolean annotationIgnoreForClass = annotationIgnoresForClasses.get( clazz ); + if ( annotationIgnoreForClass != null ) { + ignoreAnnotation = annotationIgnoreForClass; } else { ignoreAnnotation = areAllConstraintAnnotationsIgnoredFor( clazz ); From 2bf7f6373786805250d849b87c5741fae18826dd Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 11 Jun 2018 12:44:21 +0200 Subject: [PATCH 076/393] HV-1623 Remove a useless usage of getDeclaringClass() --- .../internal/metadata/aggregated/ExecutableMetaData.java | 2 +- .../internal/properties/javabean/JavaBeanConstructor.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java index cd86946d31..6c8ab7705f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java @@ -383,7 +383,7 @@ public ExecutableMetaData build() { assertCorrectnessOfConfiguration(); return new ExecutableMetaData( - kind == ConstrainedElementKind.CONSTRUCTOR ? callable.getDeclaringClass().getSimpleName() : callable.getName(), + callable.getName(), callable.getType(), callable.getParameterTypes(), kind == ConstrainedElementKind.CONSTRUCTOR ? ElementKind.CONSTRUCTOR : ElementKind.METHOD, diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanConstructor.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanConstructor.java index 2ffbce8677..8b4b257b36 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanConstructor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanConstructor.java @@ -20,6 +20,11 @@ public JavaBeanConstructor(Constructor executable) { super( executable, true ); } + @Override + public String getName() { + return getDeclaringClass().getSimpleName(); + } + @Override public ConstrainedElementKind getConstrainedElementKind() { return ConstrainedElementKind.CONSTRUCTOR; From e007a3e3ae6482fd811b8ee266737465addcc4af Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 6 Jun 2018 12:16:06 +0200 Subject: [PATCH 077/393] HV-1624 Remove the StaticFieldELResolver --- .../engine/messageinterpolation/el/SimpleELContext.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/SimpleELContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/SimpleELContext.java index c4d2518b53..8647e34837 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/SimpleELContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/SimpleELContext.java @@ -15,7 +15,6 @@ import javax.el.MapELResolver; import javax.el.ResourceBundleELResolver; import javax.el.StandardELContext; -import javax.el.StaticFieldELResolver; /** * @author Hardy Ferentschik @@ -25,7 +24,6 @@ public class SimpleELContext extends StandardELContext { private static final ELResolver DEFAULT_RESOLVER = new CompositeELResolver() { { add( new RootResolver() ); - add( new StaticFieldELResolver() ); add( new ArrayELResolver( true ) ); add( new ListELResolver( true ) ); add( new MapELResolver( true ) ); From de8d2e652fc32c2b3bec6b950196439d9f190243 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 6 Jun 2018 15:20:51 +0200 Subject: [PATCH 078/393] HV-1624 Add a warning about injecting user input into a custom message template --- documentation/src/main/asciidoc/ch06.asciidoc | 14 ++++++ documentation/src/main/asciidoc/ch12.asciidoc | 32 +++++++++++--- .../chapter12/context/MyFutureValidator.java | 3 +- .../MyFutureValidatorMessageParameter.java | 44 +++++++++++++++++++ 4 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/context/MyFutureValidatorMessageParameter.java diff --git a/documentation/src/main/asciidoc/ch06.asciidoc b/documentation/src/main/asciidoc/ch06.asciidoc index f32bb7964a..afb53c4b5a 100644 --- a/documentation/src/main/asciidoc/ch06.asciidoc +++ b/documentation/src/main/asciidoc/ch06.asciidoc @@ -173,6 +173,20 @@ It is important to add each configured constraint violation by calling `addConst Only after that the new constraint violation will be created. ==== +[WARNING] +==== +Note that the custom message template is passed directly to the Expression Language engine. + +Thus, you should be very careful when integrating user input in a custom message template as it will be interpreted +by the Expression Language engine, which is usually not the behavior you expect and could allow malicious users to leak +sensitive data. + +If you need to integrate user input, you should: + + * either escape it by using the http://beanvalidation.org/2.0/spec/#validationapi-message-defaultmessageinterpolation[Bean Validation message interpolation escaping rules]; + * or, even better, <> by unwrapping the context to `HibernateConstraintValidatorContext`. +==== + Refer to <> to learn how to use the `ConstraintValidatorContext` API to control the property path of constraint violations for class-level constraints. diff --git a/documentation/src/main/asciidoc/ch12.asciidoc b/documentation/src/main/asciidoc/ch12.asciidoc index 22ad182f53..143b8f9544 100644 --- a/documentation/src/main/asciidoc/ch12.asciidoc +++ b/documentation/src/main/asciidoc/ch12.asciidoc @@ -456,10 +456,11 @@ custom extensions for both of these interfaces. `HibernateConstraintValidatorContext` is a subtype of `ConstraintValidatorContext` which allows you to: * set arbitrary parameters for interpolation via the Expression Language message interpolation -facility using `HibernateConstraintValidatorContext#addExpressionVariable(String, Object)`. +facility using `HibernateConstraintValidatorContext#addExpressionVariable(String, Object)` +or `HibernateConstraintValidatorContext#addMessageParameter(String, Object)`. + -[[example-custom-message-parameter]] -.Custom `@Future` validator with message parameters +[[example-custom-expression-variable]] +.Custom `@Future` validator injecting an expression variable ==== [source, JAVA, indent=0] ---- @@ -467,12 +468,29 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/context/My ---- ==== + +[[example-custom-message-parameter]] +.Custom `@Future` validator injecting a message parameter +==== +[source, JAVA, indent=0] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/context/MyFutureValidatorMessageParameter.java[tags=include] +---- +==== ++ +[NOTE] +==== +Apart from the syntax, the main difference between message parameters and expression variables is that message parameters +are simply interpolated whereas expression variables are interpreted using the expression language engine. +In practice, it should not change anything. +==== ++ [NOTE] ==== -Note that the parameters specified via `addExpressionVariable(String, Object)` are global and apply -to all constraint violations created by this `isValid()` invocation. This includes the default -constraint violation, but also all violations created by the `ConstraintViolationBuilder`. You can, -however, update the parameters between invocations of +Note that the parameters specified via `addExpressionVariable(String, Object)` and +`addMessageParameter(String, Object)` are global and apply to all constraint violations created by +this `isValid()` invocation. +This includes the default constraint violation, but also all violations created by the `ConstraintViolationBuilder`. +You can, however, update the parameters between invocations of `ConstraintViolationBuilder#addConstraintViolation()`. ==== * set an arbitrary dynamic payload - see <> diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/context/MyFutureValidator.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/context/MyFutureValidator.java index 9cfad74d1f..1f5736a44e 100644 --- a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/context/MyFutureValidator.java +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/context/MyFutureValidator.java @@ -30,7 +30,8 @@ public boolean isValid(Instant value, ConstraintValidatorContext context) { if ( !value.isAfter( now ) ) { hibernateContext.disableDefaultConstraintViolation(); - hibernateContext.addExpressionVariable( "now", now ) + hibernateContext + .addExpressionVariable( "now", now ) .buildConstraintViolationWithTemplate( "Must be after ${now}" ) .addConstraintViolation(); diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/context/MyFutureValidatorMessageParameter.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/context/MyFutureValidatorMessageParameter.java new file mode 100644 index 0000000000..7a6c4c681e --- /dev/null +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/context/MyFutureValidatorMessageParameter.java @@ -0,0 +1,44 @@ +//tag::include[] +package org.hibernate.validator.referenceguide.chapter12.context; + +import java.time.Instant; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import javax.validation.constraints.Future; + +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorContext; + +//tag::include[] +public class MyFutureValidatorMessageParameter implements ConstraintValidator { + + @Override + public void initialize(Future constraintAnnotation) { + } + + @Override + public boolean isValid(Instant value, ConstraintValidatorContext context) { + if ( value == null ) { + return true; + } + + HibernateConstraintValidatorContext hibernateContext = context.unwrap( + HibernateConstraintValidatorContext.class + ); + + Instant now = Instant.now( context.getClockProvider().getClock() ); + + if ( !value.isAfter( now ) ) { + hibernateContext.disableDefaultConstraintViolation(); + hibernateContext + .addMessageParameter( "now", now ) + .buildConstraintViolationWithTemplate( "Must be after {now}" ) + .addConstraintViolation(); + + return false; + } + + return true; + } +} +//end::include[] From 0013c46ba926d3bf6c5bd609443f4c01bcc3239d Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 12 Jun 2018 15:53:26 +0200 Subject: [PATCH 079/393] HV-1630 Introduce StringHelper.format() --- .../validator/ap/internal/util/Configuration.java | 7 ++----- .../validator/ap/internal/util/StringHelper.java | 3 +++ .../validator/ap/testutil/CompilerTestHelper.java | 13 +++++++------ .../metadata/aggregated/BeanMetaDataImpl.java | 6 +++--- .../metadata/location/ConstraintLocation.java | 4 ++-- .../validator/internal/util/Contracts.java | 5 ++--- .../validator/internal/util/StringHelper.java | 4 ++++ .../constraintvalidators/hv/EmailValidatorTest.java | 5 +++-- 8 files changed, 26 insertions(+), 21 deletions(-) diff --git a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/Configuration.java b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/Configuration.java index feae0d53f8..52861f67a7 100644 --- a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/Configuration.java +++ b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/Configuration.java @@ -6,7 +6,6 @@ */ package org.hibernate.validator.ap.internal.util; -import java.util.Locale; import java.util.Map; import javax.annotation.processing.Messager; @@ -98,8 +97,7 @@ private Kind getDiagnosticKindOption(Map options, Messager messa } catch (IllegalArgumentException e) { messager.printMessage( - Kind.WARNING, String.format( - Locale.ROOT, + Kind.WARNING, StringHelper.format( "The given value %1$s is no valid diagnostic kind. %2$s will be used.", diagnosticKindFromOptions, DEFAULT_DIAGNOSTIC_KIND @@ -120,8 +118,7 @@ private boolean getVerboseOption(Map options, Messager messager) if ( theValue ) { messager.printMessage( - Kind.NOTE, String.format( - Locale.ROOT, + Kind.NOTE, StringHelper.format( "Verbose reporting is activated. Some processing information will be displayed using diagnostic kind %1$s.", Kind.NOTE ) diff --git a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/StringHelper.java b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/StringHelper.java index ea30a1486b..eb95e5c10d 100644 --- a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/StringHelper.java +++ b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/StringHelper.java @@ -102,4 +102,7 @@ private static boolean startsWithSeveralUpperCaseLetters(String string) { Character.isUpperCase( string.charAt( 1 ) ); } + public static String format(String format, Object... args) { + return String.format( Locale.ROOT, format, args ); + } } diff --git a/annotation-processor/src/test/java/org/hibernate/validator/ap/testutil/CompilerTestHelper.java b/annotation-processor/src/test/java/org/hibernate/validator/ap/testutil/CompilerTestHelper.java index c123f0080f..21f16327fc 100644 --- a/annotation-processor/src/test/java/org/hibernate/validator/ap/testutil/CompilerTestHelper.java +++ b/annotation-processor/src/test/java/org/hibernate/validator/ap/testutil/CompilerTestHelper.java @@ -6,6 +6,9 @@ */ package org.hibernate.validator.ap.testutil; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.fail; + import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -28,11 +31,9 @@ import org.hibernate.validator.ap.internal.util.CollectionHelper; import org.hibernate.validator.ap.internal.util.Configuration; +import org.hibernate.validator.ap.internal.util.StringHelper; import org.hibernate.validator.ap.util.DiagnosticExpectation; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.fail; - /** * Infrastructure for unit tests based on the Java Compiler API. * @@ -180,16 +181,16 @@ public boolean compile(Processor annotationProcessor, List options = new ArrayList(); if ( diagnosticKind != null ) { - options.add( String.format( "-A%s=%s", Configuration.DIAGNOSTIC_KIND_PROCESSOR_OPTION, diagnosticKind ) ); + options.add( StringHelper.format( "-A%s=%s", Configuration.DIAGNOSTIC_KIND_PROCESSOR_OPTION, diagnosticKind ) ); } if ( verbose != null ) { - options.add( String.format( "-A%s=%b", Configuration.VERBOSE_PROCESSOR_OPTION, verbose ) ); + options.add( StringHelper.format( "-A%s=%b", Configuration.VERBOSE_PROCESSOR_OPTION, verbose ) ); } if ( allowMethodConstraints != null ) { options.add( - String.format( + StringHelper.format( "-A%s=%b", Configuration.METHOD_CONSTRAINTS_SUPPORTED_PROCESSOR_OPTION, allowMethodConstraints diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java index c9619bde27..3926d11e81 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java @@ -15,7 +15,6 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; @@ -43,14 +42,15 @@ import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; import org.hibernate.validator.internal.metadata.raw.ConstrainedType; -import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; +import org.hibernate.validator.internal.util.StringHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper; import org.hibernate.validator.internal.util.classhierarchy.Filters; @@ -778,7 +778,7 @@ public BuilderDelegate( break; default: throw new IllegalStateException( - String.format( Locale.ROOT, "Constrained element kind '%1$s' not supported here.", constrainedElement.getKind() ) ); + StringHelper.format( "Constrained element kind '%1$s' not supported here.", constrainedElement.getKind() ) ); } this.hashCode = buildHashCode(); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java index 0084fbdde5..20a53feee4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/ConstraintLocation.java @@ -9,7 +9,6 @@ import java.lang.annotation.ElementType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; -import java.util.Locale; import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; @@ -18,6 +17,7 @@ import org.hibernate.validator.internal.properties.Field; import org.hibernate.validator.internal.properties.Getter; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; +import org.hibernate.validator.internal.util.StringHelper; /** * Represents the location (e.g. a bean, field or method parameter) of a constraint and provides logic related to it, @@ -147,7 +147,7 @@ public static ConstraintLocationKind of(ConstrainedElementKind constrainedElemen return ConstraintLocationKind.GETTER; default: throw new IllegalArgumentException( - String.format( Locale.ROOT, "Constrained element kind '%1$s' not supported.", constrainedElementKind ) ); + StringHelper.format( "Constrained element kind '%1$s' not supported.", constrainedElementKind ) ); } } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/Contracts.java b/engine/src/main/java/org/hibernate/validator/internal/util/Contracts.java index b7164465c6..35ec6fd7b2 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/Contracts.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/Contracts.java @@ -10,7 +10,6 @@ import java.lang.invoke.MethodHandles; import java.util.Collection; -import java.util.Locale; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -70,7 +69,7 @@ public static void assertTrue(boolean condition, String message) { public static void assertTrue(boolean condition, String message, Object... messageParameters) { if ( !condition ) { - throw LOG.getIllegalArgumentException( String.format( Locale.ROOT, message, messageParameters ) ); + throw LOG.getIllegalArgumentException( StringHelper.format( message, messageParameters ) ); } } @@ -88,7 +87,7 @@ public static void assertNotEmpty(Collection collection, String message) { public static void assertNotEmpty(Collection collection, String message, Object... messageParameters) { if ( collection.size() == 0 ) { - throw LOG.getIllegalArgumentException( String.format( Locale.ROOT, message, messageParameters ) ); + throw LOG.getIllegalArgumentException( StringHelper.format( message, messageParameters ) ); } } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/StringHelper.java b/engine/src/main/java/org/hibernate/validator/internal/util/StringHelper.java index 875033a11b..320e70938d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/StringHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/StringHelper.java @@ -192,4 +192,8 @@ private static boolean startsWithSeveralUpperCaseLetters(String string) { Character.isUpperCase( string.charAt( 1 ) ); } + public static String format(String format, Object... args) { + return String.format( Locale.ROOT, format, args ); + } + } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/EmailValidatorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/EmailValidatorTest.java index 804e36658c..3028742a02 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/EmailValidatorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/EmailValidatorTest.java @@ -25,6 +25,7 @@ import org.hibernate.validator.cfg.ConstraintMapping; import org.hibernate.validator.cfg.defs.EmailDef; import org.hibernate.validator.internal.constraintvalidators.hv.EmailValidator; +import org.hibernate.validator.internal.util.StringHelper; import org.hibernate.validator.testutil.MyCustomStringImpl; import org.hibernate.validator.testutil.TestForIssue; import org.hibernate.validator.testutils.ValidatorUtil; @@ -255,7 +256,7 @@ private void assertOrgAddressesAreNotValid(Set Date: Wed, 13 Jun 2018 17:01:09 +0200 Subject: [PATCH 080/393] HV-1635 Remove specific instructions for building with JDK 9 from the README --- README.md | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/README.md b/README.md index e7a515586e..36455f7a48 100644 --- a/README.md +++ b/README.md @@ -75,21 +75,6 @@ You will also need a JDK 8 and Maven 3 (>= 3.3.1). With these prerequisites in p There are more build options available as well. For more information refer to [Contributing to Hibernate Validator](http://hibernate.org/validator/contribute/). -### Build on JDK 9 - -To build Hibernate Validator with JDK 9, export the following environment variable: - - export MAVEN_OPTS="--add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED" - -Then the build can be started like this: - - mvn -s settings-example.xml clean install - -Here are the reasons why we added the various build options: - - * add-opens java.security: required by wildfly-maven-plugin:execute-commands (for the WildFly integration tests and the TCK runner running in container mode) - * add-opens java.lang: required by JRuby for Asciidoc processing - ## Continuous Integration The official Continuous Integration service for the project is hosted on [ci.hibernate.org](http://ci.hibernate.org/view/Validator/). From c9050d795379fb31d3f741739001f15bb0eb8bd7 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 13 Jun 2018 17:04:45 +0200 Subject: [PATCH 081/393] HV-1608 Add a dependency to javax-annotation-api to the documentation It is needed for a few tests from the documentation. --- documentation/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/documentation/pom.xml b/documentation/pom.xml index 03553c86f7..5b2b1c74c9 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -98,6 +98,11 @@ assertj-core test + + javax.annotation + javax.annotation-api + test + From c7525f49aea6a356e93a6e59bbee49b2ef20a4f3 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 13 Jun 2018 17:05:53 +0200 Subject: [PATCH 082/393] HV-1608 Test the presence of a class included in javafx.base.jar It is counter productive to test the presence of a class we don't really need and that might not be present. --- .../engine/valueextraction/ValueExtractorManager.java | 2 +- .../engine/valueextraction/JavaFXClassLoadingTest.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorManager.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorManager.java index 4532c0b7ad..e872ac57ab 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorManager.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorManager.java @@ -178,7 +178,7 @@ public boolean equals(Object obj) { } private static boolean isJavaFxInClasspath() { - return isClassPresent( "javafx.application.Application", false ); + return isClassPresent( "javafx.beans.value.ObservableValue", false ); } private static boolean isClassPresent(String className, boolean fallbackOnTCCL) { diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/valueextraction/JavaFXClassLoadingTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/valueextraction/JavaFXClassLoadingTest.java index 4aef341306..d9e95139cb 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/valueextraction/JavaFXClassLoadingTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/valueextraction/JavaFXClassLoadingTest.java @@ -27,9 +27,9 @@ public class JavaFXClassLoadingTest { /** - * This class will be present in the TCCL because is part of JDK 8 + * This class will be present in the TCCL because it is either part of the JDK (JDK 10-) or in the classpath (JDK 11+). */ - private static final String JAVAFX_APPLICATION_CLASS = "javafx.application.Application"; + private static final String JAVAFX_APPLICATION_CLASS = "javafx.beans.value.ObservableValue"; @Test public void shouldBeAbleToFindTheClassInTCCL() throws Exception { From 63623af002c24bee2f4dc9ee9af4b9bd155a7e69 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 13 Jun 2018 17:08:05 +0200 Subject: [PATCH 083/393] HV-1608 When testing with JDK 11, download the JavaFX jars It is not pretty but it will do for now while we wait for them to be available on Maven Central. --- engine/pom.xml | 17 ++++++++++++++++- pom.xml | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/engine/pom.xml b/engine/pom.xml index 6163f950a4..01a82c5d41 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -274,7 +274,7 @@ - jdk9 + jdk9+ [9,) @@ -282,6 +282,21 @@ --illegal-access=deny + + jdk11+ + + [11,) + + + + net.java + javafx-core + 11-ea+13 + system + ${maven.multiModuleProjectDirectory}/target/javafx/javafx-sdk-11/lib/javafx.base.jar + + + sigtest diff --git a/pom.xml b/pom.xml index 21d92ea0f8..39246b4139 100644 --- a/pom.xml +++ b/pom.xml @@ -156,7 +156,7 @@ 1.0.1 1.1 - + 1.2 @@ -208,6 +208,7 @@ 3.0.2 1.4.0 2.8.2 + 1.4.0 3.0.0-M1 2.5 1.6 @@ -960,6 +961,11 @@ sigtest-maven-plugin ${version.sigtest.plugin} + + com.googlecode.maven-download-plugin + download-maven-plugin + ${version.download.plugin} + org.eclipse.m2e @@ -1217,6 +1223,35 @@ + + jdk11+ + + [11,) + + + + + com.googlecode.maven-download-plugin + download-maven-plugin + false + + + install-javafx + validate + + wget + + + https://download.java.net/java/early_access/openjfx11/13/binaries/openjfx-11-ea+13_linux-x64_bin-sdk.zip + true + ${maven.multiModuleProjectDirectory}/target/javafx + + + + + + + jqassistant - 6.0.9.Final + 6.0.10.Final From 4d99b1c56ffb2e9043f3765664c11be1aeba8e2f Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 15 Jun 2018 11:36:56 +0200 Subject: [PATCH 093/393] HV-1628 Fix a hidden usage of String.format() --- .../performance/multilevel/MultiLevelContainerValidation.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/performance/src/main/java-bv2/org/hibernate/validator/performance/multilevel/MultiLevelContainerValidation.java b/performance/src/main/java-bv2/org/hibernate/validator/performance/multilevel/MultiLevelContainerValidation.java index 636a4d4205..fb5175b625 100644 --- a/performance/src/main/java-bv2/org/hibernate/validator/performance/multilevel/MultiLevelContainerValidation.java +++ b/performance/src/main/java-bv2/org/hibernate/validator/performance/multilevel/MultiLevelContainerValidation.java @@ -13,6 +13,7 @@ import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.Random; @@ -189,7 +190,7 @@ public EmailAddress(String value) { public static EmailAddress generate() { return new EmailAddress( - String.format( "%s@%s.com", RandomDataGenerator.randomString(), RandomDataGenerator.randomString() ) + String.format( Locale.ROOT, "%s@%s.com", RandomDataGenerator.randomString(), RandomDataGenerator.randomString() ) ); } From b6f9f6d2498ddd697ac8120066c684580b6f6fbd Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 19 Jun 2018 16:42:28 +0200 Subject: [PATCH 094/393] HV-1637 Fix variable name in @DecimalMax error message for German and Dutch --- .../org/hibernate/validator/ValidationMessages_de.properties | 2 +- .../org/hibernate/validator/ValidationMessages_nl.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties index c802fec1a1..46d5fba48d 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties @@ -1,6 +1,6 @@ javax.validation.constraints.AssertFalse.message = muss falsch sein javax.validation.constraints.AssertTrue.message = muss wahr sein -javax.validation.constraints.DecimalMax.message = muss kleiner ${strict == false ? 'oder gleich ' : ''}{value} sein +javax.validation.constraints.DecimalMax.message = muss kleiner ${inclusive == true ? 'oder gleich ' : ''}{value} sein javax.validation.constraints.DecimalMin.message = muss gr\u00F6\u00DFer ${inclusive == true ? 'oder gleich ' : ''}{value} sein javax.validation.constraints.Digits.message = numerischer Wert au\u00DFerhalb erlaubten Wertebereichs (<{integer} Ziffern>,<{fraction} Ziffern> erwartet) javax.validation.constraints.Email.message = keine g\u00FCltige E-Mail-Adresse diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties index dffd8c049d..4007586ebb 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties @@ -1,6 +1,6 @@ javax.validation.constraints.AssertFalse.message = moet onwaar zijn javax.validation.constraints.AssertTrue.message = moet waar zijn -javax.validation.constraints.DecimalMax.message = moet kleiner dan ${strict == false ? 'of gelijk aan ' : ''}{value} zijn +javax.validation.constraints.DecimalMax.message = moet kleiner dan ${inclusive == true ? 'of gelijk aan ' : ''}{value} zijn javax.validation.constraints.DecimalMin.message = moet groter dan ${inclusive == true ? 'of gelijk aan ' : ''}{value} zijn javax.validation.constraints.Digits.message = numerieke waarde ligt buiten het toegestane bereik (<{integer} cijfers>,<{fraction} cijfers> verwacht) javax.validation.constraints.Email.message = het e-mailadres is ongeldig From 6ebba4fd8aae836d34fe4cc5cd6642f6048dec3d Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Sun, 11 Mar 2018 21:18:40 +0100 Subject: [PATCH 095/393] HV-1363 Move getter detection logic to separate class and allow users to configure it --- .../validator/cdi/ValidationExtension.java | 8 +- ...GetterPropertySelectionStrategyHelper.java | 74 +++++ .../HibernateValidatorConfiguration.java | 22 ++ .../validator/HibernateValidatorFactory.java | 11 + .../cfg/context/DefaultConstraintMapping.java | 7 +- .../TypeConstraintMappingContextImpl.java | 63 ++-- .../internal/engine/ConfigurationImpl.java | 26 +- .../internal/engine/ValidatorFactoryImpl.java | 62 +++- .../metadata/BeanMetaDataManager.java | 3 + .../provider/AnnotationMetaDataProvider.java | 6 +- .../provider/XmlMetaDataProvider.java | 4 +- ...efaultGetterPropertySelectionStrategy.java | 77 +++++ .../properties/javabean/JavaBean.java | 37 --- .../javabean/JavaBeanExecutable.java | 17 -- .../properties/javabean/JavaBeanGetter.java | 18 +- .../properties/javabean/JavaBeanHelper.java | 161 ++++++++++ .../internal/util/ReflectionHelper.java | 95 ------ .../validator/internal/util/logging/Log.java | 19 +- .../GetMethodFromPropertyName.java | 49 ---- .../internal/xml/mapping/BeanStaxBuilder.java | 19 +- .../ConstrainedConstructorStaxBuilder.java | 40 +-- .../mapping/ConstrainedFieldStaxBuilder.java | 32 +- .../mapping/ConstrainedGetterStaxBuilder.java | 35 +-- .../mapping/ConstrainedMethodStaxBuilder.java | 53 +--- .../ConstraintMappingsStaxBuilder.java | 7 +- .../xml/mapping/MappingXmlParser.java | 8 +- .../properties/ConstrainableExecutable.java | 34 +++ .../GetterPropertySelectionStrategy.java | 53 ++++ .../properties/package-info.java} | 10 +- .../internal/engine/path/PathImplTest.java | 3 + .../metadata/BeanMetaDataManagerTest.java | 3 + .../aggregated/ExecutableMetaDataTest.java | 3 + .../aggregated/ParameterMetaDataTest.java | 4 + .../aggregated/PropertyMetaDataTest.java | 3 + .../metadata/core/MetaConstraintTest.java | 8 +- .../location/ConstraintLocationTest.java | 4 +- .../AnnotationMetaDataProviderTest.java | 14 +- .../AnnotationMetaDataProviderTestBase.java | 18 +- .../TypeAnnotationMetaDataRetrievalTest.java | 3 + .../internal/util/ReflectionHelperTest.java | 13 +- .../internal/xml/MappingXmlParserTest.java | 4 +- .../GetterPropertySelectionStrategyTest.java | 275 ++++++++++++++++++ 42 files changed, 956 insertions(+), 449 deletions(-) create mode 100644 cdi/src/main/java/org/hibernate/validator/cdi/internal/util/GetterPropertySelectionStrategyHelper.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/DefaultGetterPropertySelectionStrategy.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBean.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetMethodFromPropertyName.java create mode 100644 engine/src/main/java/org/hibernate/validator/spi/properties/ConstrainableExecutable.java create mode 100644 engine/src/main/java/org/hibernate/validator/spi/properties/GetterPropertySelectionStrategy.java rename engine/src/main/java/org/hibernate/validator/{internal/properties/ConstrainableType.java => spi/properties/package-info.java} (50%) create mode 100644 engine/src/test/java/org/hibernate/validator/test/properties/GetterPropertySelectionStrategyTest.java diff --git a/cdi/src/main/java/org/hibernate/validator/cdi/ValidationExtension.java b/cdi/src/main/java/org/hibernate/validator/cdi/ValidationExtension.java index cc092fe17b..858222caa9 100644 --- a/cdi/src/main/java/org/hibernate/validator/cdi/ValidationExtension.java +++ b/cdi/src/main/java/org/hibernate/validator/cdi/ValidationExtension.java @@ -51,9 +51,9 @@ import org.hibernate.validator.cdi.internal.ValidatorFactoryBean; import org.hibernate.validator.cdi.internal.interceptor.ValidationEnabledAnnotatedType; import org.hibernate.validator.cdi.internal.interceptor.ValidationInterceptor; +import org.hibernate.validator.cdi.internal.util.GetterPropertySelectionStrategyHelper; import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.ExecutableHelper; -import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -99,6 +99,7 @@ public class ValidationExtension implements Extension { */ private final Validator validator; private final ValidatorFactory validatorFactory; + private final GetterPropertySelectionStrategyHelper getterPropertySelectionStrategyHelper; private final Set globalExecutableTypes; private final boolean isExecutableValidationEnabled; @@ -119,6 +120,7 @@ public ValidationExtension() { isExecutableValidationEnabled = bootstrap.isExecutableValidationEnabled(); validatorFactory = config.buildValidatorFactory(); validator = validatorFactory.getValidator(); + getterPropertySelectionStrategyHelper = GetterPropertySelectionStrategyHelper.forValidationFactory( validatorFactory ); executableHelper = new ExecutableHelper( new TypeResolutionHelper() ); } @@ -263,7 +265,7 @@ private void determineConstrainedMethods(AnnotatedType type, BeanDescript for ( AnnotatedMethod annotatedMethod : type.getMethods() ) { Method method = annotatedMethod.getJavaMember(); - boolean isGetter = ReflectionHelper.isGetterMethod( method ); + boolean isGetter = getterPropertySelectionStrategyHelper.isGetter( method ); // obtain @ValidateOnExecution from the top-most method in the hierarchy Method methodForExecutableTypeRetrieval = replaceWithOverriddenOrInterfaceMethod( method, overriddenAndImplementedMethods ); @@ -316,7 +318,7 @@ private boolean isNonGetterConstrained(Method method, BeanDescriptor beanDescrip } private boolean isGetterConstrained(Method method, BeanDescriptor beanDescriptor) { - String propertyName = ReflectionHelper.getPropertyName( method ); + String propertyName = getterPropertySelectionStrategyHelper.getPropertyName( method ); PropertyDescriptor propertyDescriptor = beanDescriptor.getConstraintsForProperty( propertyName ); return propertyDescriptor != null && propertyDescriptor.findConstraints() .declaredOn( ElementType.METHOD ) diff --git a/cdi/src/main/java/org/hibernate/validator/cdi/internal/util/GetterPropertySelectionStrategyHelper.java b/cdi/src/main/java/org/hibernate/validator/cdi/internal/util/GetterPropertySelectionStrategyHelper.java new file mode 100644 index 0000000000..edbda53e39 --- /dev/null +++ b/cdi/src/main/java/org/hibernate/validator/cdi/internal/util/GetterPropertySelectionStrategyHelper.java @@ -0,0 +1,74 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.cdi.internal.util; + +import java.lang.reflect.Method; +import java.lang.reflect.Type; + +import javax.validation.ValidatorFactory; + +import org.hibernate.validator.HibernateValidatorFactory; +import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; +import org.hibernate.validator.spi.properties.ConstrainableExecutable; +import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; + +/** + * A wrapper around {@link GetterPropertySelectionStrategy}. + * + * @author Marko Bekhta + */ +public class GetterPropertySelectionStrategyHelper { + + private final GetterPropertySelectionStrategy getterPropertySelectionStrategy; + + private GetterPropertySelectionStrategyHelper(GetterPropertySelectionStrategy getterPropertySelectionStrategy) { + this.getterPropertySelectionStrategy = getterPropertySelectionStrategy; + } + + public boolean isGetter(Method method) { + return getterPropertySelectionStrategy.isGetter( new ConstrainableMethod( method ) ); + } + + public String getPropertyName(Method method) { + return getterPropertySelectionStrategy.getPropertyName( new ConstrainableMethod( method ) ); + } + + public static GetterPropertySelectionStrategyHelper forValidationFactory(ValidatorFactory factory) { + GetterPropertySelectionStrategy getterPropertySelectionStrategy; + if ( factory instanceof HibernateValidatorFactory ) { + getterPropertySelectionStrategy = factory.unwrap( HibernateValidatorFactory.class ).getGetterPropertySelectionStrategy(); + } + else { + getterPropertySelectionStrategy = new DefaultGetterPropertySelectionStrategy(); + } + return new GetterPropertySelectionStrategyHelper( getterPropertySelectionStrategy ); + } + + private static class ConstrainableMethod implements ConstrainableExecutable { + + private final Method method; + + private ConstrainableMethod(Method method) { + this.method = method; + } + + @Override + public Class getReturnType() { + return method.getReturnType(); + } + + @Override + public String getName() { + return method.getName(); + } + + @Override + public Type[] getParameterTypes() { + return method.getParameterTypes(); + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/HibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/HibernateValidatorConfiguration.java index 45773d3949..4de05535e7 100644 --- a/engine/src/main/java/org/hibernate/validator/HibernateValidatorConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/HibernateValidatorConfiguration.java @@ -20,6 +20,7 @@ import org.hibernate.validator.cfg.ConstraintMapping; import org.hibernate.validator.constraints.ParameterScriptAssert; import org.hibernate.validator.constraints.ScriptAssert; +import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; import org.hibernate.validator.spi.scripting.ScriptEvaluator; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; @@ -107,6 +108,15 @@ public interface HibernateValidatorConfiguration extends Configuration * Returns the {@link ResourceBundleLocator} used by the @@ -311,4 +321,16 @@ public interface HibernateValidatorConfiguration extends Configuration> configuredTypes; private final Set> typeContexts; private final Set> definedConstraints; private final Set> constraintContexts; - public DefaultConstraintMapping() { + public DefaultConstraintMapping(JavaBeanHelper javaBeanHelper) { + this.javaBeanHelper = javaBeanHelper; this.annotationProcessingOptions = new AnnotationProcessingOptionsImpl(); this.configuredTypes = newHashSet(); this.typeContexts = newHashSet(); @@ -62,7 +65,7 @@ public final TypeConstraintMappingContext type(Class type) { throw LOG.getBeanClassHasAlreadyBeConfiguredViaProgrammaticApiException( type ); } - TypeConstraintMappingContextImpl typeContext = new TypeConstraintMappingContextImpl<>( this, type ); + TypeConstraintMappingContextImpl typeContext = new TypeConstraintMappingContextImpl<>( this, type, javaBeanHelper ); typeContexts.add( typeContext ); configuredTypes.add( type ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java index 9e41540308..4fc7c9c869 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java @@ -11,14 +11,11 @@ import java.lang.annotation.ElementType; import java.lang.invoke.MethodHandles; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Arrays; import java.util.List; -import java.util.Locale; +import java.util.Optional; import java.util.Set; import org.hibernate.validator.cfg.ConstraintDef; @@ -35,20 +32,15 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedType; import org.hibernate.validator.internal.properties.Constrainable; import org.hibernate.validator.internal.properties.javabean.JavaBeanConstructor; -import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.properties.javabean.JavaBeanMethod; import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.ExecutableHelper; -import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; -import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredConstructor; -import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredField; -import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethod; -import org.hibernate.validator.internal.util.privilegedactions.GetMethod; import org.hibernate.validator.internal.util.privilegedactions.NewInstance; import org.hibernate.validator.spi.group.DefaultGroupSequenceProvider; @@ -60,12 +52,15 @@ * @author Hardy Ferentschik * @author Gunnar Morling * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI + * @author Marko Bekhta */ public final class TypeConstraintMappingContextImpl extends ConstraintMappingContextImplBase implements TypeConstraintMappingContext { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + private final JavaBeanHelper javaBeanHelper; + private final Class beanClass; private final Set executableContexts = newHashSet(); @@ -75,8 +70,9 @@ public final class TypeConstraintMappingContextImpl extends ConstraintMapping private List> defaultGroupSequence; private Class> defaultGroupSequenceProviderClass; - TypeConstraintMappingContextImpl(DefaultConstraintMapping mapping, Class beanClass) { + TypeConstraintMappingContextImpl(DefaultConstraintMapping mapping, Class beanClass, JavaBeanHelper javaBeanHelper) { super( mapping ); + this.javaBeanHelper = javaBeanHelper; this.beanClass = beanClass; mapping.getAnnotationProcessingOptions().ignoreAnnotationConstraintForClass( beanClass, Boolean.FALSE ); } @@ -138,12 +134,14 @@ public PropertyConstraintMappingContext property(String property, ElementType el public PropertyConstraintMappingContext field(String property) { Contracts.assertNotEmpty( property, MESSAGES.propertyNameMustNotBeEmpty() ); - JavaBeanField javaBeanField = getFieldProperty( beanClass, property ); + Optional foundField = javaBeanHelper.findDeclaredField( beanClass, property ); - if ( javaBeanField == null || javaBeanField.getDeclaringClass() != beanClass ) { + if ( !foundField.isPresent() ) { throw LOG.getUnableToFindPropertyWithAccessException( beanClass, property, ElementType.FIELD ); } + JavaBeanField javaBeanField = foundField.get(); + if ( configuredMembers.contains( javaBeanField ) ) { throw LOG.getPropertyHasAlreadyBeConfiguredViaProgrammaticApiException( beanClass, property ); } @@ -158,12 +156,14 @@ public PropertyConstraintMappingContext field(String property) { public PropertyConstraintMappingContext getter(String property) { Contracts.assertNotEmpty( property, MESSAGES.propertyNameMustNotBeEmpty() ); - JavaBeanGetter javaBeanGetter = getGetterProperty( beanClass, property ); + Optional foundGetter = javaBeanHelper.findDeclaredGetter( beanClass, property ); - if ( javaBeanGetter == null || javaBeanGetter.getDeclaringClass() != beanClass ) { + if ( !foundGetter.isPresent() ) { throw LOG.getUnableToFindPropertyWithAccessException( beanClass, property, ElementType.METHOD ); } + JavaBeanGetter javaBeanGetter = foundGetter.get(); + if ( configuredMembers.contains( javaBeanGetter ) ) { throw LOG.getPropertyHasAlreadyBeConfiguredViaProgrammaticApiException( beanClass, property ); } @@ -178,13 +178,13 @@ public PropertyConstraintMappingContext getter(String property) { public MethodConstraintMappingContext method(String name, Class... parameterTypes) { Contracts.assertNotNull( name, MESSAGES.methodNameMustNotBeNull() ); - Method method = run( GetDeclaredMethod.action( beanClass, name, parameterTypes ) ); + Optional foundMethod = javaBeanHelper.findDeclaredMethod( beanClass, name, parameterTypes ); - if ( method == null || method.getDeclaringClass() != beanClass ) { + if ( !foundMethod.isPresent() ) { throw LOG.getBeanDoesNotContainMethodException( beanClass, name, parameterTypes ); } - JavaBeanMethod javaBeanMethod = JavaBeanExecutable.of( method ); + JavaBeanMethod javaBeanMethod = foundMethod.get(); if ( configuredMembers.contains( javaBeanMethod ) ) { throw LOG.getMethodHasAlreadyBeenConfiguredViaProgrammaticApiException( @@ -202,16 +202,16 @@ public MethodConstraintMappingContext method(String name, Class... parameterT @Override public ConstructorConstraintMappingContext constructor(Class... parameterTypes) { - Constructor constructor = run( GetDeclaredConstructor.action( beanClass, parameterTypes ) ); + Optional foundConstructor = javaBeanHelper.findDeclaredConstructor( beanClass, parameterTypes ); - if ( constructor == null || constructor.getDeclaringClass() != beanClass ) { + if ( !foundConstructor.isPresent() ) { throw LOG.getBeanDoesNotContainConstructorException( beanClass, parameterTypes ); } - JavaBeanConstructor javaBeanConstructor = new JavaBeanConstructor( constructor ); + JavaBeanConstructor javaBeanConstructor = foundConstructor.get(); if ( configuredMembers.contains( javaBeanConstructor ) ) { throw LOG.getConstructorHasAlreadyBeConfiguredViaProgrammaticApiException( @@ -285,27 +285,6 @@ protected ConstraintType getConstraintType() { return ConstraintType.GENERIC; } - private JavaBeanField getFieldProperty(Class clazz, String property) { - Contracts.assertNotNull( clazz, MESSAGES.classCannotBeNull() ); - - Field field = run( GetDeclaredField.action( clazz, property ) ); - return field == null ? null : new JavaBeanField( field ); - } - - private JavaBeanGetter getGetterProperty(Class clazz, String property) { - Contracts.assertNotNull( clazz, MESSAGES.classCannotBeNull() ); - - Method method = null; - String methodName = property.substring( 0, 1 ).toUpperCase( Locale.ROOT ) + property.substring( 1 ); - for ( String prefix : ReflectionHelper.PROPERTY_ACCESSOR_PREFIXES ) { - method = run( GetMethod.action( clazz, prefix + methodName ) ); - if ( method != null ) { - break; - } - } - return method == null ? null : new JavaBeanGetter( method ); - } - /** * Runs the given privileged action, using a privileged block if required. *

diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java index 863467d48a..986bbe5b51 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java @@ -42,6 +42,8 @@ import org.hibernate.validator.internal.engine.resolver.TraversableResolvers; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorDescriptor; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.Version; import org.hibernate.validator.internal.util.logging.Log; @@ -53,6 +55,7 @@ import org.hibernate.validator.internal.xml.config.ValidationXmlParser; import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; import org.hibernate.validator.resourceloading.PlatformResourceBundleLocator; +import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; @@ -103,6 +106,7 @@ public class ConfigurationImpl implements HibernateValidatorConfiguration, Confi private ScriptEvaluatorFactory scriptEvaluatorFactory; private Duration temporalValidationTolerance; private Object constraintValidatorPayload; + private GetterPropertySelectionStrategy getterPropertySelectionStrategy; public ConfigurationImpl(BootstrapState state) { this(); @@ -294,6 +298,14 @@ public HibernateValidatorConfiguration constraintValidatorPayload(Object constra return this; } + @Override + public HibernateValidatorConfiguration getterPropertySelectionStrategy(GetterPropertySelectionStrategy getterPropertySelectionStrategy) { + Contracts.assertNotNull( getterPropertySelectionStrategy, MESSAGES.parameterMustNotBeNull( "getterPropertySelectionStrategy" ) ); + + this.getterPropertySelectionStrategy = getterPropertySelectionStrategy; + return this; + } + public boolean isAllowParallelMethodsDefineParameterConstraints() { return this.methodValidationConfigurationBuilder.isAllowParallelMethodsDefineParameterConstraints(); } @@ -304,7 +316,15 @@ public MethodValidationConfiguration getMethodValidationConfiguration() { @Override public final DefaultConstraintMapping createConstraintMapping() { - return new DefaultConstraintMapping(); + GetterPropertySelectionStrategy getterPropertySelectionStrategyToUse = null; + if ( getterPropertySelectionStrategy == null ) { + getterPropertySelectionStrategyToUse = new DefaultGetterPropertySelectionStrategy(); + } + else { + getterPropertySelectionStrategyToUse = getterPropertySelectionStrategy; + } + + return new DefaultConstraintMapping( new JavaBeanHelper( getterPropertySelectionStrategyToUse ) ); } @Override @@ -450,6 +470,10 @@ public Object getConstraintValidatorPayload() { return constraintValidatorPayload; } + public GetterPropertySelectionStrategy getGetterPropertySelectionStrategy() { + return getterPropertySelectionStrategy; + } + @Override public Set> getValueExtractors() { return validationBootstrapParameters.getValueExtractorDescriptors() diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java index a112b42cab..5eac4bc7e4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java @@ -47,6 +47,8 @@ import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; import org.hibernate.validator.internal.metadata.provider.ProgrammaticMetaDataProvider; import org.hibernate.validator.internal.metadata.provider.XmlMetaDataProvider; +import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; @@ -60,6 +62,7 @@ import org.hibernate.validator.internal.util.stereotypes.Immutable; import org.hibernate.validator.internal.util.stereotypes.ThreadSafe; import org.hibernate.validator.spi.cfg.ConstraintMappingContributor; +import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; /** @@ -132,6 +135,8 @@ public class ValidatorFactoryImpl implements HibernateValidatorFactory { private final ValueExtractorManager valueExtractorManager; + private final JavaBeanHelper javaBeanHelper; + private final ValidationOrderGenerator validationOrderGenerator; public ValidatorFactoryImpl(ConfigurationState configurationState) { @@ -148,13 +153,17 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { hibernateSpecificConfig = (ConfigurationImpl) configurationState; } + Map properties = configurationState.getProperties(); + + this.javaBeanHelper = new JavaBeanHelper( getterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ) ); + // HV-302; don't load XmlMappingParser if not necessary if ( configurationState.getMappingStreams().isEmpty() ) { this.xmlMetaDataProvider = null; } else { this.xmlMetaDataProvider = new XmlMetaDataProvider( - constraintHelper, typeResolutionHelper, valueExtractorManager, configurationState.getMappingStreams(), externalClassLoader + constraintHelper, typeResolutionHelper, valueExtractorManager, javaBeanHelper, configurationState.getMappingStreams(), externalClassLoader ); } @@ -162,14 +171,13 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { getConstraintMappings( typeResolutionHelper, configurationState, + javaBeanHelper, externalClassLoader ) ); registerCustomConstraintValidators( constraintMappings, constraintHelper ); - Map properties = configurationState.getProperties(); - this.methodValidationConfiguration = new MethodValidationConfiguration.Builder() .allowOverridingMethodAlterParameterConstraint( getAllowOverridingMethodAlterParameterConstraint( hibernateSpecificConfig, properties ) @@ -208,7 +216,7 @@ private static ClassLoader getExternalClassLoader(ConfigurationState configurati } private static Set getConstraintMappings(TypeResolutionHelper typeResolutionHelper, - ConfigurationState configurationState, ClassLoader externalClassLoader) { + ConfigurationState configurationState, JavaBeanHelper javaBeanHelper, ClassLoader externalClassLoader) { Set constraintMappings = newHashSet(); if ( configurationState instanceof ConfigurationImpl ) { @@ -224,7 +232,7 @@ private static Set getConstraintMappings(TypeResolutio ConstraintMappingContributor serviceLoaderBasedContributor = new ServiceLoaderBasedConstraintMappingContributor( typeResolutionHelper, externalClassLoader != null ? externalClassLoader : run( GetClassLoader.fromContext() ) ); - DefaultConstraintMappingBuilder builder = new DefaultConstraintMappingBuilder( constraintMappings ); + DefaultConstraintMappingBuilder builder = new DefaultConstraintMappingBuilder( javaBeanHelper, constraintMappings ); serviceLoaderBasedContributor.createConstraintMappings( builder ); } @@ -233,7 +241,7 @@ private static Set getConstraintMappings(TypeResolutio externalClassLoader ); for ( ConstraintMappingContributor contributor : contributors ) { - DefaultConstraintMappingBuilder builder = new DefaultConstraintMappingBuilder( constraintMappings ); + DefaultConstraintMappingBuilder builder = new DefaultConstraintMappingBuilder( javaBeanHelper, constraintMappings ); contributor.createConstraintMappings( builder ); } @@ -289,6 +297,11 @@ public Duration getTemporalValidationTolerance() { return validatorFactoryScopedContext.getTemporalValidationTolerance(); } + @Override + public GetterPropertySelectionStrategy getGetterPropertySelectionStrategy() { + return javaBeanHelper.getGetterPropertySelectionStrategy(); + } + public boolean isFailFast() { return validatorFactoryScopedContext.isFailFast(); } @@ -347,11 +360,12 @@ Validator createValidator(ConstraintValidatorFactory constraintValidatorFactory, typeResolutionHelper, validatorFactoryScopedContext.getParameterNameProvider(), valueExtractorManager, + javaBeanHelper, validationOrderGenerator, buildDataProviders(), methodValidationConfiguration ) - ); + ); return new ValidatorImpl( constraintValidatorFactory, @@ -550,6 +564,32 @@ private Object getConstraintValidatorPayload(ConfigurationState configurationSta return null; } + private static GetterPropertySelectionStrategy getterPropertySelectionStrategy(ConfigurationImpl hibernateSpecificConfig, Map properties, ClassLoader externalClassLoader) { + if ( hibernateSpecificConfig.getGetterPropertySelectionStrategy() != null ) { + LOG.usingGetterPropertySelectionStrategy( hibernateSpecificConfig.getGetterPropertySelectionStrategy().getClass() ); + return hibernateSpecificConfig.getGetterPropertySelectionStrategy(); + } + + String getterPropertySelectionStrategyFqcn = properties.get( HibernateValidatorConfiguration.GETTER_PROPERTY_SELECTION_STRATEGY_CLASSNAME ); + if ( getterPropertySelectionStrategyFqcn != null ) { + try { + @SuppressWarnings("unchecked") + Class clazz = (Class) run( + LoadClass.action( getterPropertySelectionStrategyFqcn, externalClassLoader ) + ); + GetterPropertySelectionStrategy getterPropertySelectionStrategy = run( NewInstance.action( clazz, "getter property selection strategy class" ) ); + LOG.usingGetterPropertySelectionStrategy( clazz ); + + return getterPropertySelectionStrategy; + } + catch (Exception e) { + throw LOG.getUnableToInstantiateGetterPropertySelectionStrategyClassException( getterPropertySelectionStrategyFqcn, e ); + } + } + + return new DefaultGetterPropertySelectionStrategy(); + } + private static void registerCustomConstraintValidators(Set constraintMappings, ConstraintHelper constraintHelper) { Set> definedConstraints = newHashSet(); @@ -598,16 +638,18 @@ private static T run(PrivilegedAction action) { */ private static class DefaultConstraintMappingBuilder implements ConstraintMappingContributor.ConstraintMappingBuilder { + + private final JavaBeanHelper javaBeanHelper; private final Set mappings; - public DefaultConstraintMappingBuilder(Set mappings) { - super(); + public DefaultConstraintMappingBuilder(JavaBeanHelper javaBeanHelper, Set mappings) { + this.javaBeanHelper = javaBeanHelper; this.mappings = mappings; } @Override public ConstraintMapping addConstraintMapping() { - DefaultConstraintMapping mapping = new DefaultConstraintMapping(); + DefaultConstraintMapping mapping = new DefaultConstraintMapping( javaBeanHelper ); mappings.add( mapping ); return mapping; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java index 197a3232c4..d1908005e3 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java @@ -29,6 +29,7 @@ import org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.ConcurrentReferenceHashMap; import org.hibernate.validator.internal.util.Contracts; @@ -121,6 +122,7 @@ public BeanMetaDataManager(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ExecutableParameterNameProvider parameterNameProvider, ValueExtractorManager valueExtractorManager, + JavaBeanHelper javaBeanHelper, ValidationOrderGenerator validationOrderGenerator, List optionalMetaDataProviders, MethodValidationConfiguration methodValidationConfiguration) { @@ -147,6 +149,7 @@ public BeanMetaDataManager(ConstraintHelper constraintHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, + javaBeanHelper, annotationProcessingOptions ); List tmpMetaDataProviders = new ArrayList<>( optionalMetaDataProviders.size() + 1 ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java index d3e0a42cf0..0f68ebf22c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java @@ -65,6 +65,7 @@ import org.hibernate.validator.internal.properties.javabean.JavaBeanAnnotatedElement; import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.properties.javabean.JavaBeanParameter; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.ReflectionHelper; @@ -94,16 +95,19 @@ public class AnnotationMetaDataProvider implements MetaDataProvider { private final TypeResolutionHelper typeResolutionHelper; private final AnnotationProcessingOptions annotationProcessingOptions; private final ValueExtractorManager valueExtractorManager; + private final JavaBeanHelper javaBeanHelper; private final BeanConfiguration objectBeanConfiguration; public AnnotationMetaDataProvider(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + JavaBeanHelper javaBeanHelper, AnnotationProcessingOptions annotationProcessingOptions) { this.constraintHelper = constraintHelper; this.typeResolutionHelper = typeResolutionHelper; this.valueExtractorManager = valueExtractorManager; + this.javaBeanHelper = javaBeanHelper; this.annotationProcessingOptions = annotationProcessingOptions; this.objectBeanConfiguration = retrieveBeanConfiguration( Object.class ); @@ -301,7 +305,7 @@ private Set getMetaData(Executable[] executableElements) * given element. */ private ConstrainedExecutable findExecutableMetaData(Executable executable) { - JavaBeanExecutable javaBeanExecutable = JavaBeanExecutable.of( executable ); + JavaBeanExecutable javaBeanExecutable = javaBeanHelper.executable( executable ); List parameterConstraints = getParameterMetaData( javaBeanExecutable ); Map>> executableConstraints = findConstraints( diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlMetaDataProvider.java index 9cef432d79..12f51ddb4e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlMetaDataProvider.java @@ -17,6 +17,7 @@ import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.stereotypes.Immutable; @@ -40,11 +41,12 @@ public class XmlMetaDataProvider implements MetaDataProvider { public XmlMetaDataProvider(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + JavaBeanHelper javaBeanHelper, Set mappingStreams, ClassLoader externalClassLoader) { MappingXmlParser mappingParser = new MappingXmlParser( constraintHelper, typeResolutionHelper, valueExtractorManager, - externalClassLoader ); + javaBeanHelper, externalClassLoader ); mappingParser.parse( mappingStreams ); configuredBeans = CollectionHelper.toImmutableMap( createBeanConfigurations( mappingParser ) ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/DefaultGetterPropertySelectionStrategy.java b/engine/src/main/java/org/hibernate/validator/internal/properties/DefaultGetterPropertySelectionStrategy.java new file mode 100644 index 0000000000..31c3e767a0 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/DefaultGetterPropertySelectionStrategy.java @@ -0,0 +1,77 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.properties; + +import org.hibernate.validator.internal.util.StringHelper; +import org.hibernate.validator.spi.properties.ConstrainableExecutable; +import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; + +/** + * @author Marko Bekhta + */ +public class DefaultGetterPropertySelectionStrategy implements GetterPropertySelectionStrategy { + + private static final String GETTER_PREFIX_GET = "get"; + private static final String GETTER_PREFIX_IS = "is"; + private static final String GETTER_PREFIX_HAS = "has"; + private static final String[] GETTER_PREFIXES = { + GETTER_PREFIX_GET, + GETTER_PREFIX_IS, + GETTER_PREFIX_HAS + }; + + /** + * Checks whether the given executable is a valid JavaBean getter method, which + * is the case if + *
    + *
  • its name starts with "get" and it has a return type but no parameter or
  • + *
  • its name starts with "is", it has no parameter and is returning + * {@code boolean} or
  • + *
  • its name starts with "has", it has no parameter and is returning + * {@code boolean} (HV-specific, not mandated by the JavaBeans spec).
  • + *
+ * + * @param executable The executable of interest. + * + * @return {@code true}, if the given executable is a JavaBean getter method, + * {@code false} otherwise. + */ + @Override + public boolean isGetter(ConstrainableExecutable executable) { + if ( executable.getParameterTypes().length != 0 ) { + return false; + } + + String methodName = executable.getName(); + + // get() + if ( methodName.startsWith( GETTER_PREFIX_GET ) && executable.getReturnType() != void.class ) { + return true; + } + //boolean is() + else if ( methodName.startsWith( GETTER_PREFIX_IS ) && executable.getReturnType() == boolean.class ) { + return true; + } + //boolean has() + else if ( methodName.startsWith( GETTER_PREFIX_HAS ) && executable.getReturnType() == boolean.class ) { + return true; + } + + return false; + } + + @Override + public String getPropertyName(ConstrainableExecutable executable) { + String methodName = executable.getName(); + for ( String prefix : GETTER_PREFIXES ) { + if ( methodName.startsWith( prefix ) ) { + return StringHelper.decapitalize( methodName.substring( prefix.length() ) ); + } + } + return null; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBean.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBean.java deleted file mode 100644 index ff9dd436dc..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBean.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.properties.javabean; - -import java.util.Arrays; -import java.util.stream.Stream; - -import org.hibernate.validator.internal.properties.Property; -import org.hibernate.validator.internal.properties.ConstrainableType; -import org.hibernate.validator.internal.util.ReflectionHelper; - -/** - * @author Marko Bekhta - */ -public class JavaBean implements ConstrainableType { - - private final Class clazz; - - public JavaBean(Class clazz) { - this.clazz = clazz; - } - - public Stream getFieldProperties() { - return Arrays.stream( clazz.getDeclaredFields() ) - .map( JavaBeanField::new ); - } - - public Stream getGetterProperties() { - return Arrays.stream( clazz.getDeclaredMethods() ) - .filter( ReflectionHelper::isGetterMethod ) - .map( JavaBeanGetter::new ); - } -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java index 0c307ef696..3e6b90c764 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java @@ -8,7 +8,6 @@ import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -46,22 +45,6 @@ public abstract class JavaBeanExecutable implements Callab this.parameters = getParameters( executable ); } - public static JavaBeanExecutable of(Executable executable) { - if ( executable instanceof Constructor ) { - return new JavaBeanConstructor( (Constructor) executable ); - } - - return of( ( (Method) executable ) ); - } - - public static JavaBeanMethod of(Method method) { - if ( ReflectionHelper.isGetterMethod( method ) ) { - return new JavaBeanGetter( method ); - } - - return new JavaBeanMethod( method ); - } - @Override public boolean hasReturnValue() { return hasReturnValue; diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java index a7084b1f9e..63ee3de9b5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java @@ -23,7 +23,7 @@ */ public class JavaBeanGetter extends JavaBeanMethod implements Getter { - private final String name; + private final String propertyName; /** * The class of the method for which the constraint was defined. @@ -33,21 +33,15 @@ public class JavaBeanGetter extends JavaBeanMethod implements Getter { */ private final Class declaringClass; - public JavaBeanGetter(Method method) { + public JavaBeanGetter(Class declaringClass, Method method, String propertyName) { super( method ); - this.name = ReflectionHelper.getPropertyName( method ); - this.declaringClass = method.getDeclaringClass(); - } - - public JavaBeanGetter(Class declaringClass, Method method) { - super( method ); - this.name = ReflectionHelper.getPropertyName( method ); this.declaringClass = declaringClass; + this.propertyName = propertyName; } @Override public String getPropertyName() { - return name; + return propertyName; } @Override @@ -96,13 +90,13 @@ public boolean equals(Object o) { JavaBeanGetter that = (JavaBeanGetter) o; - return this.name.equals( that.name ); + return this.propertyName.equals( that.propertyName ); } @Override public int hashCode() { int result = super.hashCode(); - result = 31 * result + this.name.hashCode(); + result = 31 * result + this.propertyName.hashCode(); return result; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java new file mode 100644 index 0000000000..c71882ca15 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java @@ -0,0 +1,161 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.properties.javabean; + +import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Optional; + +import org.hibernate.validator.internal.properties.Constrainable; +import org.hibernate.validator.internal.util.Contracts; +import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredConstructor; +import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredField; +import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethod; +import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethods; +import org.hibernate.validator.internal.util.privilegedactions.GetMethods; +import org.hibernate.validator.spi.properties.ConstrainableExecutable; +import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; + +/** + * Helper class that gives ability to find {@link Constrainable} versions + * of JavaBean's fields, getters, constructors and methods. + * + * @author Marko Bekhta + */ +public class JavaBeanHelper { + + private final GetterPropertySelectionStrategy getterPropertySelectionStrategy; + + public JavaBeanHelper(GetterPropertySelectionStrategy getterPropertySelectionStrategy) { + this.getterPropertySelectionStrategy = getterPropertySelectionStrategy; + } + + public GetterPropertySelectionStrategy getGetterPropertySelectionStrategy() { + return getterPropertySelectionStrategy; + } + + public Optional findDeclaredField(Class declaringClass, String property) { + Contracts.assertNotNull( declaringClass, MESSAGES.classCannotBeNull() ); + + Field field = run( GetDeclaredField.action( declaringClass, property ) ); + return Optional.ofNullable( field ).map( JavaBeanField::new ); + } + + public Optional findDeclaredGetter(Class declaringClass, String property) { + Contracts.assertNotNull( declaringClass, MESSAGES.classCannotBeNull() ); + + return findGetter( declaringClass, run( GetDeclaredMethods.action( declaringClass ) ), property ); + } + + private Optional findGetter(Class declaringClass, Method[] methods, String property) { + for ( Method method : methods ) { + JavaBeanConstrainableExecutable executable = new JavaBeanConstrainableExecutable( method ); + if ( getterPropertySelectionStrategy.isGetter( executable ) + && property.equals( getterPropertySelectionStrategy.getPropertyName( executable ) ) ) { + return Optional.of( new JavaBeanGetter( declaringClass, method, getterPropertySelectionStrategy.getPropertyName( executable ) ) ); + } + } + return Optional.empty(); + } + + + public Optional findGetter(Class declaringClass, String property) { + Contracts.assertNotNull( declaringClass, MESSAGES.classCannotBeNull() ); + + Optional declaredGetterProperty = findDeclaredGetter( declaringClass, property ); + + if ( declaredGetterProperty.isPresent() ) { + return declaredGetterProperty; + } + else { + // look for getters from the superclasses and interfaces + return findGetter( declaringClass, run( GetMethods.action( declaringClass ) ), property ); + } + } + + public Optional findDeclaredMethod(Class declaringClass, String methodName, Class... parameterTypes) { + Method method = run( GetDeclaredMethod.action( declaringClass, methodName, parameterTypes ) ); + if ( method == null ) { + return Optional.empty(); + } + else { + return Optional.of( executable( declaringClass, method ) ); + } + } + + public Optional findDeclaredConstructor(Class declaringClass, Class... parameterTypes) { + Constructor constructor = run( GetDeclaredConstructor.action( declaringClass, parameterTypes ) ); + if ( constructor == null ) { + return Optional.empty(); + } + else { + return Optional.of( new JavaBeanConstructor( constructor ) ); + } + } + + public JavaBeanExecutable executable(Executable executable) { + return executable( executable.getDeclaringClass(), executable ); + } + + public JavaBeanExecutable executable(Class declaringClass, Executable executable) { + if ( executable instanceof Constructor ) { + return new JavaBeanConstructor( (Constructor) executable ); + } + + return executable( declaringClass, ( (Method) executable ) ); + } + + public JavaBeanMethod executable(Class declaringClass, Method method) { + JavaBeanConstrainableExecutable executable = new JavaBeanConstrainableExecutable( method ); + if ( getterPropertySelectionStrategy.isGetter( executable ) ) { + return new JavaBeanGetter( declaringClass, method, getterPropertySelectionStrategy.getPropertyName( executable ) ); + } + + return new JavaBeanMethod( method ); + } + + /** + * Runs the given privileged action, using a privileged block if required. + * + * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary + * privileged actions within HV's protection domain. + */ + private T run(PrivilegedAction action) { + return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); + } + + private static class JavaBeanConstrainableExecutable implements ConstrainableExecutable { + + private final Method method; + + private JavaBeanConstrainableExecutable(Method method) { + this.method = method; + } + + @Override + public Class getReturnType() { + return method.getReturnType(); + } + + @Override + public String getName() { + return method.getName(); + } + + @Override + public Type[] getParameterTypes() { + return method.getParameterTypes(); + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/ReflectionHelper.java b/engine/src/main/java/org/hibernate/validator/internal/util/ReflectionHelper.java index b9e3d0597d..c968bb0af5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/ReflectionHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/ReflectionHelper.java @@ -10,7 +10,6 @@ import java.lang.invoke.MethodHandles; import java.lang.reflect.Constructor; -import java.lang.reflect.Executable; import java.lang.reflect.Field; import java.lang.reflect.GenericArrayType; import java.lang.reflect.InvocationTargetException; @@ -38,15 +37,6 @@ */ public final class ReflectionHelper { - private static final String PROPERTY_ACCESSOR_PREFIX_GET = "get"; - private static final String PROPERTY_ACCESSOR_PREFIX_IS = "is"; - private static final String PROPERTY_ACCESSOR_PREFIX_HAS = "has"; - public static final String[] PROPERTY_ACCESSOR_PREFIXES = { - PROPERTY_ACCESSOR_PREFIX_GET, - PROPERTY_ACCESSOR_PREFIX_IS, - PROPERTY_ACCESSOR_PREFIX_HAS - }; - private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); private static final Map, Class> PRIMITIVE_TO_WRAPPER_TYPES; @@ -91,91 +81,6 @@ public final class ReflectionHelper { private ReflectionHelper() { } - /** - * Returns the JavaBeans property name of the given member. - *

- * For fields, the field name will be returned. For getter methods, the - * decapitalized property name will be returned, with the "get", "is" or "has" - * prefix stripped off. Getter methods are methods - *

- *
    - *
  • whose name start with "get" and who have a return type but no parameter - * or
  • - *
  • whose name starts with "is" and who have no parameter and return - * {@code boolean} or
  • - *
  • whose name starts with "has" and who have no parameter and return - * {@code boolean} (HV-specific, not mandated by JavaBeans spec).
  • - *
- * - * @param member The member for which to get the property name. - * - * @return The property name for the given member or {@code null} if the - * member is neither a field nor a getter method according to the - * JavaBeans standard. - */ - public static String getPropertyName(Member member) { - String name = null; - - if ( member instanceof Field ) { - name = member.getName(); - } - - if ( member instanceof Method ) { - String methodName = member.getName(); - for ( String prefix : PROPERTY_ACCESSOR_PREFIXES ) { - if ( methodName.startsWith( prefix ) ) { - name = StringHelper.decapitalize( methodName.substring( prefix.length() ) ); - } - } - } - return name; - } - - /** - * Checks whether the given executable is a valid JavaBeans getter method, which - * is the case if - *
    - *
  • its name starts with "get" and it has a return type but no parameter or
  • - *
  • its name starts with "is", it has no parameter and is returning - * {@code boolean} or
  • - *
  • its name starts with "has", it has no parameter and is returning - * {@code boolean} (HV-specific, not mandated by JavaBeans spec).
  • - *
- * - * @param executable The executable of interest. - * - * @return {@code true}, if the given executable is a JavaBeans getter method, - * {@code false} otherwise. - */ - public static boolean isGetterMethod(Executable executable) { - if ( !( executable instanceof Method ) ) { - return false; - } - - Method method = (Method) executable; - - if ( method.getParameterTypes().length != 0 ) { - return false; - } - - String methodName = method.getName(); - - // get() - if ( methodName.startsWith( PROPERTY_ACCESSOR_PREFIX_GET ) && method.getReturnType() != void.class ) { - return true; - } - //boolean is() - else if ( methodName.startsWith( PROPERTY_ACCESSOR_PREFIX_IS ) && method.getReturnType() == boolean.class ) { - return true; - } - //boolean has() - else if ( methodName.startsWith( PROPERTY_ACCESSOR_PREFIX_HAS ) && method.getReturnType() == boolean.class ) { - return true; - } - - return false; - } - /** * @param member The {@code Member} instance for which to retrieve the type. * diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 7a0da1e309..3410782855 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -13,10 +13,8 @@ import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.invoke.MethodHandles.Lookup; -import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Member; -import java.lang.reflect.Method; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.time.Duration; @@ -51,6 +49,8 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Constrainable; +import org.hibernate.validator.internal.properties.javabean.JavaBeanConstructor; +import org.hibernate.validator.internal.properties.javabean.JavaBeanMethod; import org.hibernate.validator.internal.util.logging.formatter.ArrayOfClassesObjectFormatter; import org.hibernate.validator.internal.util.logging.formatter.ClassObjectFormatter; import org.hibernate.validator.internal.util.logging.formatter.CollectionOfClassesObjectFormatter; @@ -60,6 +60,7 @@ import org.hibernate.validator.internal.util.logging.formatter.ObjectArrayFormatter; import org.hibernate.validator.internal.util.logging.formatter.TypeFormatter; import org.hibernate.validator.internal.xml.mapping.ContainerElementTypePath; +import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; import org.hibernate.validator.spi.scripting.ScriptEvaluationException; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; import org.hibernate.validator.spi.scripting.ScriptEvaluatorNotFoundException; @@ -485,10 +486,10 @@ ValidationException getBeanDoesNotContainMethodException(@FormatWith(ClassObject ValidationException getUnableToLoadConstraintAnnotationClassException(String constraintAnnotationClassName, @Cause Exception e); @Message(id = 137, value = "The method '%1$s' is defined twice in the mapping xml for bean %2$s.") - ValidationException getMethodIsDefinedTwiceInMappingXmlForBeanException(Method name, @FormatWith(ClassObjectFormatter.class) Class beanClass); + ValidationException getMethodIsDefinedTwiceInMappingXmlForBeanException(JavaBeanMethod javaBeanMethod, @FormatWith(ClassObjectFormatter.class) Class beanClass); @Message(id = 138, value = "The constructor '%1$s' is defined twice in the mapping xml for bean %2$s.") - ValidationException getConstructorIsDefinedTwiceInMappingXmlForBeanException(Constructor name, @FormatWith(ClassObjectFormatter.class) Class beanClass); + ValidationException getConstructorIsDefinedTwiceInMappingXmlForBeanException(JavaBeanConstructor javaBeanConstructor, @FormatWith(ClassObjectFormatter.class) Class beanClass); @Message(id = 139, value = "The constraint '%1$s' defines multiple cross parameter validators. Only one is allowed.") @@ -864,4 +865,14 @@ ConstraintDefinitionException getConstraintValidatorDefinitionConstraintMismatch @Message(id = 245, value = "Allowed constraint element types are FIELD and GETTER, but instead received %1$s.") AssertionError getUnsupportedConstraintElementType(ConstrainedElement.ConstrainedElementKind kind); + + @LogMessage(level = INFO) + @Message(id = 246, value = "Using %s as getter property selection strategy.") + void usingGetterPropertySelectionStrategy(@FormatWith(ClassObjectFormatter.class) Class getterPropertySelectionStrategyClass); + + @Message(id = 247, value = "Unable to instantiate getter property selection strategy class %s.") + ValidationException getUnableToInstantiateGetterPropertySelectionStrategyClassException(String getterPropertySelectionStrategyClassName, @Cause Exception e); + + @Message(id = 248, value = "Unable to access field %3$s of class %2$s using lookup %1$s.") + ValidationException getUnableToAccessFieldException(Lookup lookup, @FormatWith(ClassObjectFormatter.class) Class clazz, String property, @Cause Throwable e); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetMethodFromPropertyName.java b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetMethodFromPropertyName.java deleted file mode 100644 index 359f617837..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetMethodFromPropertyName.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.util.privilegedactions; - -import java.lang.reflect.Method; -import java.security.PrivilegedAction; - -/** - * Returns the method with the specified property name or {@code null} if it does not exist. This method will prepend - * 'is' and 'get' to the property name and capitalize the first letter. - * - * @author Emmanuel Bernard - * @author Hardy Ferentschik - */ -public final class GetMethodFromPropertyName implements PrivilegedAction { - private final Class clazz; - private final String property; - - public static GetMethodFromPropertyName action(Class clazz, String property) { - return new GetMethodFromPropertyName( clazz, property ); - } - - private GetMethodFromPropertyName(Class clazz, String property) { - this.clazz = clazz; - this.property = property; - } - - @Override - public Method run() { - try { - char[] string = property.toCharArray(); - string[0] = Character.toUpperCase( string[0] ); - String fullMethodName = new String( string ); - try { - return clazz.getMethod( "get" + fullMethodName ); - } - catch (NoSuchMethodException e) { - return clazz.getMethod( "is" + fullMethodName ); - } - } - catch (NoSuchMethodException e) { - return null; - } - } -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/BeanStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/BeanStaxBuilder.java index e551a46485..475148542f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/BeanStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/BeanStaxBuilder.java @@ -9,8 +9,6 @@ import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; import java.lang.invoke.MethodHandles; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -29,6 +27,9 @@ import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; +import org.hibernate.validator.internal.properties.javabean.JavaBeanConstructor; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; +import org.hibernate.validator.internal.properties.javabean.JavaBeanMethod; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -140,7 +141,7 @@ private ConstrainedConstructorStaxBuilder getNewConstrainedConstructorStaxBuilde return new ConstrainedConstructorStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); } - void build(Set> processedClasses, Map, Set> constrainedElementsByType) { + void build(JavaBeanHelper javaBeanHelper, Set> processedClasses, Map, Set> constrainedElementsByType) { Class beanClass = classLoadingHelper.loadClass( className, defaultPackageStaxBuilder.build().orElse( "" ) ); checkClassHasNotBeenProcessed( processedClasses, beanClass ); @@ -165,7 +166,7 @@ void build(Set> processedClasses, Map, Set addConstrainedElements( constrainedElementsByType, beanClass, constrainedFieldStaxBuilders.stream() - .map( builder -> builder.build( beanClass, alreadyProcessedFieldNames ) ) + .map( builder -> builder.build( javaBeanHelper, beanClass, alreadyProcessedFieldNames ) ) .collect( Collectors.toList() ) ); @@ -174,25 +175,25 @@ void build(Set> processedClasses, Map, Set constrainedElementsByType, beanClass, constrainedGetterStaxBuilders.stream() - .map( builder -> builder.build( beanClass, alreadyProcessedGetterNames ) ) + .map( builder -> builder.build( javaBeanHelper, beanClass, alreadyProcessedGetterNames ) ) .collect( Collectors.toList() ) ); - List alreadyProcessedMethods = new ArrayList<>( constrainedMethodStaxBuilders.size() ); + List alreadyProcessedMethods = new ArrayList<>( constrainedMethodStaxBuilders.size() ); addConstrainedElements( constrainedElementsByType, beanClass, constrainedMethodStaxBuilders.stream() - .map( builder -> builder.build( beanClass, alreadyProcessedMethods ) ) + .map( builder -> builder.build( javaBeanHelper, beanClass, alreadyProcessedMethods ) ) .collect( Collectors.toList() ) ); - List> alreadyProcessedConstructors = new ArrayList<>( constrainedConstructorStaxBuilders.size() ); + List alreadyProcessedConstructors = new ArrayList<>( constrainedConstructorStaxBuilders.size() ); addConstrainedElements( constrainedElementsByType, beanClass, constrainedConstructorStaxBuilders.stream() - .map( builder -> builder.build( beanClass, alreadyProcessedConstructors ) ) + .map( builder -> builder.build( javaBeanHelper, beanClass, alreadyProcessedConstructors ) ) .collect( Collectors.toList() ) ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java index dd8da3e3e3..d7f56ab36f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java @@ -7,9 +7,6 @@ package org.hibernate.validator.internal.xml.mapping; import java.lang.invoke.MethodHandles; -import java.lang.reflect.Constructor; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -27,11 +24,11 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; import org.hibernate.validator.internal.properties.javabean.JavaBeanConstructor; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; -import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredConstructor; /** * Builder for constrained constructors. @@ -67,32 +64,18 @@ public String getMethodName() { return mainAttributeValue; } - ConstrainedExecutable build(Class beanClass, List> alreadyProcessedConstructors) { + ConstrainedExecutable build(JavaBeanHelper javaBeanHelper, Class beanClass, List alreadyProcessedConstructors) { Class[] parameterTypes = constrainedParameterStaxBuilders.stream() .map( builder -> builder.getParameterType( beanClass ) ) .toArray( Class[]::new ); - final Constructor constructor = run( - GetDeclaredConstructor.action( - beanClass, - parameterTypes - ) - ); - - if ( constructor == null ) { - throw LOG.getBeanDoesNotContainConstructorException( - beanClass, - parameterTypes - ); - } - - JavaBeanConstructor javaBeanConstructor = new JavaBeanConstructor( constructor ); + final JavaBeanConstructor javaBeanConstructor = findConstructor( javaBeanHelper, beanClass, parameterTypes ); - if ( alreadyProcessedConstructors.contains( constructor ) ) { - throw LOG.getConstructorIsDefinedTwiceInMappingXmlForBeanException( constructor, beanClass ); + if ( alreadyProcessedConstructors.contains( javaBeanConstructor ) ) { + throw LOG.getConstructorIsDefinedTwiceInMappingXmlForBeanException( javaBeanConstructor, beanClass ); } else { - alreadyProcessedConstructors.add( constructor ); + alreadyProcessedConstructors.add( javaBeanConstructor ); } // ignore annotations @@ -130,13 +113,8 @@ ConstrainedExecutable build(Class beanClass, List> alreadyProc ); } - /** - * Runs the given privileged action, using a privileged block if required. - * - * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary - * privileged actions within HV's protection domain. - */ - private static T run(PrivilegedAction action) { - return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); + private JavaBeanConstructor findConstructor(JavaBeanHelper javaBeanHelper, Class beanClass, Class[] parameterTypes) { + return javaBeanHelper.findDeclaredConstructor( beanClass, parameterTypes ) + .orElseThrow( () -> LOG.getBeanDoesNotContainConstructorException( beanClass, parameterTypes ) ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java index bb0a350084..ded9e7b06d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java @@ -7,9 +7,6 @@ package org.hibernate.validator.internal.xml.mapping; import java.lang.invoke.MethodHandles; -import java.lang.reflect.Field; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.List; import java.util.Optional; import java.util.Set; @@ -25,12 +22,11 @@ import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; -import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; -import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredField; import org.hibernate.validator.internal.xml.mapping.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; /** @@ -63,15 +59,14 @@ protected String getAcceptableQName() { return FIELD_QNAME_LOCAL_PART; } - ConstrainedField build(Class beanClass, List alreadyProcessedFieldNames) { + ConstrainedField build(JavaBeanHelper javaBeanHelper, Class beanClass, List alreadyProcessedFieldNames) { if ( alreadyProcessedFieldNames.contains( mainAttributeValue ) ) { throw LOG.getIsDefinedTwiceInMappingXmlForBeanException( mainAttributeValue, beanClass ); } else { alreadyProcessedFieldNames.add( mainAttributeValue ); } - Field field = findField( beanClass, mainAttributeValue ); - JavaBeanField javaBeanField = new JavaBeanField( field ); + JavaBeanField javaBeanField = findField( javaBeanHelper, beanClass, mainAttributeValue ); ConstraintLocation constraintLocation = ConstraintLocation.forField( javaBeanField ); Set> metaConstraints = constraintTypeStaxBuilders.stream() @@ -86,7 +81,7 @@ ConstrainedField build(Class beanClass, List alreadyProcessedFieldNam javaBeanField, metaConstraints, containerElementTypeConfiguration.getMetaConstraints(), - getCascadingMetaData( containerElementTypeConfiguration.getTypeParametersCascadingMetaData(), ReflectionHelper.typeOf( field ) ) + getCascadingMetaData( containerElementTypeConfiguration.getTypeParametersCascadingMetaData(), javaBeanField.getType() ) ); // ignore annotations @@ -100,21 +95,8 @@ ConstrainedField build(Class beanClass, List alreadyProcessedFieldNam return constrainedField; } - private static Field findField(Class beanClass, String fieldName) { - final Field field = run( GetDeclaredField.action( beanClass, fieldName ) ); - if ( field == null ) { - throw LOG.getBeanDoesNotContainTheFieldException( beanClass, fieldName ); - } - return field; - } - - /** - * Runs the given privileged action, using a privileged block if required. - * - * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary - * privileged actions within HV's protection domain. - */ - private static T run(PrivilegedAction action) { - return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); + private static JavaBeanField findField(JavaBeanHelper javaBeanHelper, Class beanClass, String fieldName) { + return javaBeanHelper.findDeclaredField( beanClass, fieldName ) + .orElseThrow( () -> LOG.getBeanDoesNotContainTheFieldException( beanClass, fieldName ) ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java index 3969c10577..617a1be254 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java @@ -7,9 +7,6 @@ package org.hibernate.validator.internal.xml.mapping; import java.lang.invoke.MethodHandles; -import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -27,12 +24,11 @@ import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; -import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; -import org.hibernate.validator.internal.util.privilegedactions.GetMethodFromPropertyName; import org.hibernate.validator.internal.xml.mapping.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; /** @@ -65,15 +61,14 @@ protected String getAcceptableQName() { return GETTER_QNAME_LOCAL_PART; } - ConstrainedExecutable build(Class beanClass, List alreadyProcessedGetterNames) { + ConstrainedExecutable build(JavaBeanHelper javaBeanHelper, Class beanClass, List alreadyProcessedGetterNames) { if ( alreadyProcessedGetterNames.contains( mainAttributeValue ) ) { throw LOG.getIsDefinedTwiceInMappingXmlForBeanException( mainAttributeValue, beanClass ); } else { alreadyProcessedGetterNames.add( mainAttributeValue ); } - Method getter = findGetter( beanClass, mainAttributeValue ); - JavaBeanGetter javaBeanGetter = new JavaBeanGetter( beanClass, getter ); + JavaBeanGetter javaBeanGetter = findGetter( javaBeanHelper, beanClass, mainAttributeValue ); ConstraintLocation constraintLocation = ConstraintLocation.forGetter( javaBeanGetter ); Set> metaConstraints = constraintTypeStaxBuilders.stream() @@ -81,7 +76,7 @@ ConstrainedExecutable build(Class beanClass, List alreadyProcessedGet .collect( Collectors.toSet() ); ContainerElementTypeConfiguration containerElementTypeConfiguration = getContainerElementTypeConfiguration( - ReflectionHelper.typeOf( getter ), constraintLocation ); + javaBeanGetter.getType(), constraintLocation ); ConstrainedExecutable constrainedGetter = new ConstrainedExecutable( ConfigurationSource.XML, @@ -90,7 +85,7 @@ ConstrainedExecutable build(Class beanClass, List alreadyProcessedGet Collections.>emptySet(), metaConstraints, containerElementTypeConfiguration.getMetaConstraints(), - getCascadingMetaData( containerElementTypeConfiguration.getTypeParametersCascadingMetaData(), ReflectionHelper.typeOf( getter ) ) + getCascadingMetaData( containerElementTypeConfiguration.getTypeParametersCascadingMetaData(), javaBeanGetter.getType() ) ); // ignore annotations @@ -104,23 +99,9 @@ ConstrainedExecutable build(Class beanClass, List alreadyProcessedGet return constrainedGetter; } - private static Method findGetter(Class beanClass, String getterName) { - final Method method = run( GetMethodFromPropertyName.action( beanClass, getterName ) ); - if ( method == null ) { - throw LOG.getBeanDoesNotContainThePropertyException( beanClass, getterName ); - } - - return method; - } + private static JavaBeanGetter findGetter(JavaBeanHelper javaBeanHelper, Class beanClass, String getterName) { + Optional property = javaBeanHelper.findGetter( beanClass, getterName ); - /** - * Runs the given privileged action, using a privileged block if required. - * - * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary - * privileged actions within HV's protection domain. - */ - private static T run(PrivilegedAction action) { - return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); + return property.orElseThrow( () -> LOG.getBeanDoesNotContainThePropertyException( beanClass, getterName ) ); } - } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java index 4a78d244bc..658ea6d07b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java @@ -7,9 +7,6 @@ package org.hibernate.validator.internal.xml.mapping; import java.lang.invoke.MethodHandles; -import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -26,12 +23,12 @@ import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; -import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; +import org.hibernate.validator.internal.properties.javabean.JavaBeanMethod; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; -import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethod; /** * Builder for constrained methods. @@ -68,41 +65,26 @@ public String getMethodName() { return mainAttributeValue; } - ConstrainedExecutable build(Class beanClass, List alreadyProcessedMethods) { + ConstrainedExecutable build(JavaBeanHelper javaBeanHelper, Class beanClass, List alreadyProcessedMethods) { Class[] parameterTypes = constrainedParameterStaxBuilders.stream() .map( builder -> builder.getParameterType( beanClass ) ) .toArray( Class[]::new ); String methodName = getMethodName(); - final Method method = run( - GetDeclaredMethod.action( - beanClass, - methodName, - parameterTypes - ) - ); - - if ( method == null ) { - throw LOG.getBeanDoesNotContainMethodException( - beanClass, - methodName, - parameterTypes - ); - } + JavaBeanMethod javaBeanMethod = findMethod( javaBeanHelper, beanClass, methodName, parameterTypes ); - if ( alreadyProcessedMethods.contains( method ) ) { - throw LOG.getMethodIsDefinedTwiceInMappingXmlForBeanException( method, beanClass ); + if ( alreadyProcessedMethods.contains( javaBeanMethod ) ) { + throw LOG.getMethodIsDefinedTwiceInMappingXmlForBeanException( javaBeanMethod, beanClass ); } else { - alreadyProcessedMethods.add( method ); + alreadyProcessedMethods.add( javaBeanMethod ); } - JavaBeanExecutable executable = JavaBeanExecutable.of( method ); // ignore annotations if ( ignoreAnnotations.isPresent() ) { annotationProcessingOptions.ignoreConstraintAnnotationsOnMember( - executable, + javaBeanMethod, ignoreAnnotations.get() ); } @@ -110,21 +92,21 @@ ConstrainedExecutable build(Class beanClass, List alreadyProcessedMet List constrainedParameters = CollectionHelper.newArrayList( constrainedParameterStaxBuilders.size() ); for ( int index = 0; index < constrainedParameterStaxBuilders.size(); index++ ) { ConstrainedParameterStaxBuilder builder = constrainedParameterStaxBuilders.get( index ); - constrainedParameters.add( builder.build( executable, index ) ); + constrainedParameters.add( builder.build( javaBeanMethod, index ) ); } Set> crossParameterConstraints = getCrossParameterStaxBuilder() - .map( builder -> builder.build( executable ) ).orElse( Collections.emptySet() ); + .map( builder -> builder.build( javaBeanMethod ) ).orElse( Collections.emptySet() ); // parse the return value Set> returnValueConstraints = new HashSet<>(); Set> returnValueTypeArgumentConstraints = new HashSet<>(); - CascadingMetaDataBuilder cascadingMetaDataBuilder = getReturnValueStaxBuilder().map( builder -> builder.build( executable, returnValueConstraints, returnValueTypeArgumentConstraints ) ) + CascadingMetaDataBuilder cascadingMetaDataBuilder = getReturnValueStaxBuilder().map( builder -> builder.build( javaBeanMethod, returnValueConstraints, returnValueTypeArgumentConstraints ) ) .orElse( CascadingMetaDataBuilder.nonCascading() ); return new ConstrainedExecutable( ConfigurationSource.XML, - executable, + javaBeanMethod, constrainedParameters, crossParameterConstraints, returnValueConstraints, @@ -133,13 +115,8 @@ ConstrainedExecutable build(Class beanClass, List alreadyProcessedMet ); } - /** - * Runs the given privileged action, using a privileged block if required. - * - * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary - * privileged actions within HV's protection domain. - */ - private static T run(PrivilegedAction action) { - return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); + private JavaBeanMethod findMethod(JavaBeanHelper javaBeanHelper, Class beanClass, String methodName, Class[] parameterTypes) { + return javaBeanHelper.findDeclaredMethod( beanClass, methodName, parameterTypes ) + .orElseThrow( () -> LOG.getBeanDoesNotContainMethodException( beanClass, methodName, parameterTypes ) ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintMappingsStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintMappingsStaxBuilder.java index 50ac58eeb8..f97862513c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintMappingsStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintMappingsStaxBuilder.java @@ -19,6 +19,7 @@ import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.xml.AbstractStaxBuilder; @@ -37,6 +38,7 @@ class ConstraintMappingsStaxBuilder extends AbstractStaxBuilder { private final TypeResolutionHelper typeResolutionHelper; private final ValueExtractorManager valueExtractorManager; private final AnnotationProcessingOptionsImpl annotationProcessingOptions; + private final JavaBeanHelper javaBeanHelper; private final Map, List>> defaultSequences; private final DefaultPackageStaxBuilder defaultPackageStaxBuilder; @@ -44,12 +46,13 @@ class ConstraintMappingsStaxBuilder extends AbstractStaxBuilder { private final List constraintDefinitionStaxBuilders; public ConstraintMappingsStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, - AnnotationProcessingOptionsImpl annotationProcessingOptions, Map, List>> defaultSequences) { + AnnotationProcessingOptionsImpl annotationProcessingOptions, JavaBeanHelper javaBeanHelper, Map, List>> defaultSequences) { this.classLoadingHelper = classLoadingHelper; this.constraintHelper = constraintHelper; this.typeResolutionHelper = typeResolutionHelper; this.valueExtractorManager = valueExtractorManager; this.annotationProcessingOptions = annotationProcessingOptions; + this.javaBeanHelper = javaBeanHelper; this.defaultSequences = defaultSequences; this.defaultPackageStaxBuilder = new DefaultPackageStaxBuilder(); @@ -91,6 +94,6 @@ private ConstraintDefinitionStaxBuilder getNewConstraintDefinitionStaxBuilder() public void build(Set> processedClasses, Map, Set> constrainedElementsByType, Set alreadyProcessedConstraintDefinitions) { constraintDefinitionStaxBuilders.forEach( builder -> builder.build( alreadyProcessedConstraintDefinitions ) ); - beanStaxBuilders.forEach( builder -> builder.build( processedClasses, constrainedElementsByType ) ); + beanStaxBuilders.forEach( builder -> builder.build( javaBeanHelper, processedClasses, constrainedElementsByType ) ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java index 75cbb1bd59..3c70c66e50 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java @@ -31,6 +31,7 @@ import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -38,6 +39,7 @@ import org.hibernate.validator.internal.util.privilegedactions.SetContextClassLoader; import org.hibernate.validator.internal.xml.CloseIgnoringInputStream; import org.hibernate.validator.internal.xml.XmlParserHelper; + import org.xml.sax.SAXException; /** @@ -55,6 +57,7 @@ public class MappingXmlParser { private final TypeResolutionHelper typeResolutionHelper; private final ValueExtractorManager valueExtractorManager; private final AnnotationProcessingOptionsImpl annotationProcessingOptions; + private final JavaBeanHelper javaBeanHelper; private final Map, List>> defaultSequences; private final Map, Set> constrainedElements; @@ -75,11 +78,12 @@ private static Map getSchemasByVersion() { } public MappingXmlParser(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, - ClassLoader externalClassLoader) { + JavaBeanHelper javaBeanHelper, ClassLoader externalClassLoader) { this.constraintHelper = constraintHelper; this.typeResolutionHelper = typeResolutionHelper; this.valueExtractorManager = valueExtractorManager; this.annotationProcessingOptions = new AnnotationProcessingOptionsImpl(); + this.javaBeanHelper = javaBeanHelper; this.defaultSequences = newHashMap(); this.constrainedElements = newHashMap(); this.xmlParserHelper = new XmlParserHelper(); @@ -120,7 +124,7 @@ public final void parse(Set mappingStreams) { ConstraintMappingsStaxBuilder constraintMappingsStaxBuilder = new ConstraintMappingsStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, - annotationProcessingOptions, defaultSequences + annotationProcessingOptions, javaBeanHelper, defaultSequences ); xmlEventReader = xmlParserHelper.createXmlEventReader( "constraint mapping file", new CloseIgnoringInputStream( in ) ); diff --git a/engine/src/main/java/org/hibernate/validator/spi/properties/ConstrainableExecutable.java b/engine/src/main/java/org/hibernate/validator/spi/properties/ConstrainableExecutable.java new file mode 100644 index 0000000000..888b1284f0 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/spi/properties/ConstrainableExecutable.java @@ -0,0 +1,34 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.spi.properties; + +import java.lang.reflect.Type; + +/** + * A class that describes JavaBeans method. Is used for determining if a given + * JavaBeans method is a property or not. + * + * @author Marko Bekhta + * @since 6.1.0 + */ +public interface ConstrainableExecutable { + + /** + * @return the return type for the method this object represents + */ + Class getReturnType(); + + /** + * @return the name of the method represented by this {@code ConstrainableExecutable} object + */ + String getName(); + + /** + * @return the parameter types for the executable this object represents + */ + Type[] getParameterTypes(); +} diff --git a/engine/src/main/java/org/hibernate/validator/spi/properties/GetterPropertySelectionStrategy.java b/engine/src/main/java/org/hibernate/validator/spi/properties/GetterPropertySelectionStrategy.java new file mode 100644 index 0000000000..24aa059d96 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/spi/properties/GetterPropertySelectionStrategy.java @@ -0,0 +1,53 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.spi.properties; + +import org.hibernate.validator.Incubating; +import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; + +/** + * Used to define JavaBeans property detection algorithm. The default + * implementation ({@link DefaultGetterPropertySelectionStrategy}) uses next definition + * of JavaBeans property: + *

+ * A JavaBeans method is considered to be a valid getter method (property), if + * one of the next rules can be applied to it: + *

+ *
    + *
  • its name starts with "get" and it has a return type but no parameters
  • + *
  • its name starts with "is", it has no parameters and is returning {@code boolean}
  • + *
  • its name starts with "has", it has no parameters and is returning {@code boolean}.
  • + *
+ *

+ * The last rule is Hibernate Validator specific one and is not mandated by the JavaBeans spec. + * + * @author Marko Bekhta + * @since 6.1.0 + */ +@Incubating +public interface GetterPropertySelectionStrategy { + + /** + * Determines if a given {@link ConstrainableExecutable} is a valid JavaBeans getter method (property). + * + * @param executable the {@link ConstrainableExecutable} under test + * + * @return {@code true} if given executable is a valid JavaBeans property, {@code false} otherwise + */ + boolean isGetter(ConstrainableExecutable executable); + + /** + * Performs a transformation of JavaBeans method name to its corresponding property name. + * For example by removing the prefixes like {@code get}/{@code is} etc. + * + * @param method the {@link ConstrainableExecutable} which methods name should be transformed + * + * @return a property name of a given executable + */ + String getPropertyName(ConstrainableExecutable method); + +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/ConstrainableType.java b/engine/src/main/java/org/hibernate/validator/spi/properties/package-info.java similarity index 50% rename from engine/src/main/java/org/hibernate/validator/internal/properties/ConstrainableType.java rename to engine/src/main/java/org/hibernate/validator/spi/properties/package-info.java index 9f0f0b3a00..284e7972a9 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/ConstrainableType.java +++ b/engine/src/main/java/org/hibernate/validator/spi/properties/package-info.java @@ -4,13 +4,9 @@ * License: Apache License, Version 2.0 * See the license.txt file in the root directory or . */ -package org.hibernate.validator.internal.properties; /** - * A type that can be constrained. Will represent a Java class for a JavaBean or a named type for JSON. - * - * @author Marko Bekhta + *

This package provides support for customization of the JavaBeans property detection logic.

+ *

This package is part of the public Hibernate Validator SPI.

*/ -public interface ConstrainableType { - -} +package org.hibernate.validator.spi.properties; diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java index 1153454aa4..257eef802a 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java @@ -36,6 +36,8 @@ import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; +import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.TypeResolutionHelper; @@ -197,6 +199,7 @@ public void testCreationOfExecutablePath() throws Exception { new TypeResolutionHelper(), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), new ValueExtractorManager( Collections.emptySet() ), + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java index 9b402186b8..e66c711745 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java @@ -29,6 +29,8 @@ import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; +import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.TypeResolutionHelper; @@ -56,6 +58,7 @@ public void setUpBeanMetaDataManager() { new TypeResolutionHelper(), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), new ValueExtractorManager( Collections.emptySet() ), + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java index 170e8a64d2..67d2e47713 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java @@ -32,6 +32,8 @@ import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; +import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.TypeResolutionHelper; @@ -61,6 +63,7 @@ public void setupBeanMetaData() { new TypeResolutionHelper(), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), new ValueExtractorManager( Collections.emptySet() ), + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java index bccf0c208b..adf433af8c 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java @@ -33,6 +33,8 @@ import org.hibernate.validator.internal.metadata.aggregated.ParameterMetaData; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; +import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.TypeResolutionHelper; @@ -61,6 +63,7 @@ public void setupBeanMetaData() { new TypeResolutionHelper(), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), new ValueExtractorManager( Collections.emptySet() ), + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() @@ -131,6 +134,7 @@ public void parameterNameInInheritanceHierarchy() throws Exception { new TypeResolutionHelper(), new ExecutableParameterNameProvider( new SkewedParameterNameProvider() ), new ValueExtractorManager( Collections.emptySet() ), + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java index fe2577ea2e..4f3c2616aa 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java @@ -24,6 +24,8 @@ import org.hibernate.validator.internal.metadata.aggregated.PropertyMetaData; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; +import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.TypeResolutionHelper; @@ -45,6 +47,7 @@ public void setupBeanMetaDataManager() { new TypeResolutionHelper(), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), new ValueExtractorManager( Collections.emptySet() ), + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java index 436f7e8b3a..ce5e9f0708 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java @@ -20,7 +20,7 @@ import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; -import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; +import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.testutil.TestForIssue; @@ -50,15 +50,15 @@ public void setUp() throws Exception { @Test @TestForIssue(jiraKey = "HV-930") public void two_meta_constraints_for_the_same_constraint_should_be_equal() throws Exception { + JavaBeanGetter javaBeanGetter = new JavaBeanGetter( Foo.class, Foo.class.getDeclaredMethod( "getBar" ), "bar" ); ConstraintDescriptorImpl constraintDescriptor1 = new ConstraintDescriptorImpl<>( - constraintHelper, JavaBeanExecutable.of( barMethod ), constraintAnnotationDescriptor, ConstraintLocationKind.METHOD + constraintHelper, javaBeanGetter, constraintAnnotationDescriptor, ConstraintLocationKind.METHOD ); ConstraintLocation location1 = ConstraintLocation.forClass( Foo.class ); MetaConstraint metaConstraint1 = MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor1, location1 ); - ConstraintDescriptorImpl constraintDescriptor2 = new ConstraintDescriptorImpl<>( - constraintHelper, JavaBeanExecutable.of( barMethod ), constraintAnnotationDescriptor, ConstraintLocationKind.METHOD + constraintHelper, javaBeanGetter, constraintAnnotationDescriptor, ConstraintLocationKind.METHOD ); ConstraintLocation location2 = ConstraintLocation.forClass( Foo.class ); MetaConstraint metaConstraint2 = MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor2, location2 ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/location/ConstraintLocationTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/location/ConstraintLocationTest.java index 0bbca776e3..7cb7424737 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/location/ConstraintLocationTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/location/ConstraintLocationTest.java @@ -33,8 +33,8 @@ public void two_constraint_locations_for_the_same_type_should_be_equal() { @TestForIssue(jiraKey = "HV-930") public void two_constraint_locations_for_the_same_member_should_be_equal() throws Exception { Method getter = Foo.class.getMethod( "getBar" ); - ConstraintLocation location1 = ConstraintLocation.forGetter( new JavaBeanGetter( getter ) ); - ConstraintLocation location2 = ConstraintLocation.forGetter( new JavaBeanGetter( getter ) ); + ConstraintLocation location1 = ConstraintLocation.forGetter( new JavaBeanGetter( Foo.class, getter, "bar" ) ); + ConstraintLocation location2 = ConstraintLocation.forGetter( new JavaBeanGetter( Foo.class, getter, "bar" ) ); assertEquals( location1, location2, "Two constraint locations for the same type should be equal" ); } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java index 9693602727..cd7fce3d4e 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java @@ -41,7 +41,8 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; import org.hibernate.validator.internal.metadata.raw.ConstrainedType; -import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; +import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.testutil.TestForIssue; @@ -63,6 +64,7 @@ public void setUpProvider() { new ConstraintHelper(), new TypeResolutionHelper(), new ValueExtractorManager( Collections.emptySet() ), + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), new AnnotationProcessingOptionsImpl() ); } @@ -104,13 +106,9 @@ public void testGetCrossParameterMetaData() throws Exception { assertThat( createEvent.getCrossParameterConstraints() ).hasSize( 1 ); assertThat( createEvent.getCallable() ).isEqualTo( - JavaBeanExecutable.of( - Calendar.class.getMethod( - "createEvent", - LocalDate.class, - LocalDate.class - ) - ) + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ) + .findDeclaredMethod( Calendar.class, "createEvent", LocalDate.class, LocalDate.class ) + .get() ); MetaConstraint constraint = createEvent.getCrossParameterConstraints().iterator().next(); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTestBase.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTestBase.java index bf6f716428..d4f430f361 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTestBase.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTestBase.java @@ -6,6 +6,7 @@ */ package org.hibernate.validator.test.internal.metadata.provider; +import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Field; import java.lang.reflect.Member; @@ -17,8 +18,8 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedField; import org.hibernate.validator.internal.metadata.raw.ConstrainedType; import org.hibernate.validator.internal.properties.Constrainable; -import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; -import org.hibernate.validator.internal.properties.javabean.JavaBeanField; +import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; /** * @author Gunnar Morling @@ -59,15 +60,18 @@ protected ConstrainedType findConstrainedType(BeanConfiguration beanConfi throw new RuntimeException( "Found no constrained element for type " + type ); } - protected ConstrainedElement findConstrainedElement(BeanConfiguration beanConfiguration, - Member member) { - + protected ConstrainedElement findConstrainedElement(BeanConfiguration beanConfiguration, Member member) { + JavaBeanHelper javaBeanHelper = new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ); Constrainable constrainable; if ( member instanceof Field ) { - constrainable = new JavaBeanField( (Field) member ); + constrainable = javaBeanHelper.findDeclaredField( member.getDeclaringClass(), member.getName() ).get(); + } + else if ( member instanceof Constructor ) { + constrainable = javaBeanHelper.findDeclaredConstructor( member.getDeclaringClass(), ( (Constructor) member ).getParameterTypes() ).get(); } else { - constrainable = JavaBeanExecutable.of( (Executable) member ); + Executable executable = (Executable) member; + constrainable = javaBeanHelper.findDeclaredMethod( member.getDeclaringClass(), executable.getName(), executable.getParameterTypes() ).get(); } for ( ConstrainedElement constrainedElement : beanConfiguration.getConstrainedElements() ) { diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/TypeAnnotationMetaDataRetrievalTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/TypeAnnotationMetaDataRetrievalTest.java index 3d7721ca77..5dc4c74d87 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/TypeAnnotationMetaDataRetrievalTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/TypeAnnotationMetaDataRetrievalTest.java @@ -27,6 +27,8 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; +import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -46,6 +48,7 @@ public void setup() { new ConstraintHelper(), new TypeResolutionHelper(), new ValueExtractorManager( Collections.emptySet() ), + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), new AnnotationProcessingOptionsImpl() ); } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/util/ReflectionHelperTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/util/ReflectionHelperTest.java index 784a47a9b9..d50b9046ee 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/util/ReflectionHelperTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/util/ReflectionHelperTest.java @@ -12,7 +12,6 @@ import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; -import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; @@ -25,7 +24,7 @@ import java.util.TreeSet; import org.hibernate.validator.internal.util.ReflectionHelper; -import org.hibernate.validator.testutil.TestForIssue; + import org.testng.annotations.Test; /** @@ -161,16 +160,6 @@ public void testGetIndexedValueForNull() { assertNull( value ); } - @Test - @TestForIssue(jiraKey = "HV-622") - public void testIsGetterMethod() throws Exception { - Method method = Bar.class.getMethod( "getBar" ); - assertTrue( ReflectionHelper.isGetterMethod( method ) ); - - method = Bar.class.getMethod( "getBar", String.class ); - assertFalse( ReflectionHelper.isGetterMethod( method ) ); - } - private void doTestGetIndexedValueForArray(Object array, Object firstValue, Object secondValue) { Object value = ReflectionHelper.getIndexedValue( array, 0 ); assertEquals( value, firstValue, "We should be able to retrieve the indexed object" ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/xml/MappingXmlParserTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/xml/MappingXmlParserTest.java index 0ef2a724f0..56d1d341c1 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/xml/MappingXmlParserTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/xml/MappingXmlParserTest.java @@ -25,6 +25,8 @@ import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorDescriptor; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.xml.mapping.MappingXmlParser; import org.hibernate.validator.testutil.TestForIssue; @@ -43,7 +45,7 @@ public class MappingXmlParserTest { public void setupParserHelper() { constraintHelper = new ConstraintHelper(); xmlMappingParser = new MappingXmlParser( - constraintHelper, new TypeResolutionHelper(), new ValueExtractorManager( Collections.emptySet() ), null + constraintHelper, new TypeResolutionHelper(), new ValueExtractorManager( Collections.emptySet() ), new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), null ); } diff --git a/engine/src/test/java/org/hibernate/validator/test/properties/GetterPropertySelectionStrategyTest.java b/engine/src/test/java/org/hibernate/validator/test/properties/GetterPropertySelectionStrategyTest.java new file mode 100644 index 0000000000..49c5c68632 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/properties/GetterPropertySelectionStrategyTest.java @@ -0,0 +1,275 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.properties; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; + +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.constraints.AssertTrue; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import org.hibernate.validator.HibernateValidator; +import org.hibernate.validator.HibernateValidatorConfiguration; +import org.hibernate.validator.spi.properties.ConstrainableExecutable; +import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; +import org.hibernate.validator.testutil.ConstraintViolationAssert; +import org.hibernate.validator.testutil.TestForIssue; +import org.hibernate.validator.testutils.ValidatorUtil; + +import org.testng.annotations.Test; + +/** + * @author Marko Bekhta + */ +public class GetterPropertySelectionStrategyTest { + + @Test + public void testGetterPropertySelectionStrategy() throws Exception { + GetterPropertySelectionStrategy filter = new FooGetterPropertySelectionStrategy(); + + ConstrainableExecutableImpl fooMethod = new ConstrainableExecutableImpl( Foo.class.getDeclaredMethod( "fooMethod" ) ); + ConstrainableExecutableImpl getMethod = new ConstrainableExecutableImpl( Foo.class.getDeclaredMethod( "getMethod" ) ); + + assertThat( filter.isGetter( fooMethod ) ).isTrue(); + assertThat( filter.isGetter( getMethod ) ).isFalse(); + + assertThat( filter.getPropertyName( fooMethod ) ).isEqualTo( "method" ); + } + + @Test + public void testConfigureGetterPropertySelectionStrategy() throws Exception { + Validator validator = Validation.byProvider( HibernateValidator.class ) + .configure() + .getterPropertySelectionStrategy( new FooGetterPropertySelectionStrategy() ) + .buildValidatorFactory() + .getValidator(); + Set> violations = validator.validate( new Foo() ); + + ConstraintViolationAssert.assertThat( violations ).containsOnlyViolations( + violationOf( Min.class ) + ); + } + + @Test + public void testConfigureGetterPropertySelectionStrategyWithProperty() throws Exception { + Validator validator = Validation.byProvider( HibernateValidator.class ) + .configure() + .addProperty( HibernateValidatorConfiguration.GETTER_PROPERTY_SELECTION_STRATEGY_CLASSNAME, FooGetterPropertySelectionStrategy.class.getName() ) + .buildValidatorFactory() + .getValidator(); + Set> violations = validator.validate( new Foo() ); + + ConstraintViolationAssert.assertThat( violations ).containsOnlyViolations( + violationOf( Min.class ) + ); + } + + @Test + public void testNoPrefixGetterPropertySelectionStrategy() { + Validator validator = Validation.byProvider( HibernateValidator.class ) + .configure() + .getterPropertySelectionStrategy( new NoPrefixGetterPropertySelectionStrategy() ) + .buildValidatorFactory() + .getValidator(); + Set> violations = validator.validate( new NoPrefixFoo() ); + + ConstraintViolationAssert.assertThat( violations ).containsOnlyViolations( + violationOf( Min.class ).withProperty( "test" ), + violationOf( NotBlank.class ).withProperty( "name" ) + ); + } + + @Test + public void testGetterAndFieldWithSamePropertyNameButDifferentTypes() { + Validator validator = ValidatorUtil.getValidator(); + + Set> violations = validator.validate( new Bar() ); + + ConstraintViolationAssert.assertThat( violations ).containsOnlyViolations( + violationOf( NotEmpty.class ).withProperty( "tags" ), + violationOf( Size.class ).withProperty( "tags" ) + ); + } + + @Test + public void testStrangePropertyNames() { + class StrangeProeprties { + @AssertTrue + public boolean isHasGet() { + return false; + } + + @AssertTrue + public boolean hasIsGet() { + return false; + } + + @NotNull + public String getHasIs() { + return null; + } + } + + Validator validator = ValidatorUtil.getValidator(); + + Set> violations = validator.validate( new StrangeProeprties() ); + + ConstraintViolationAssert.assertThat( violations ).containsOnlyViolations( + violationOf( AssertTrue.class ).withProperty( "hasGet" ), + violationOf( AssertTrue.class ).withProperty( "isGet" ), + violationOf( NotNull.class ).withProperty( "hasIs" ) + ); + } + + @Test + @TestForIssue(jiraKey = "HV-622") + public void testIsGetterMethod() throws Exception { + class Bar { + @NotNull + public String getBar() { + return null; + } + + @NotEmpty + public String getBar(String param) { + return null; + } + } + Validator validator = ValidatorUtil.getValidator(); + + Set> violations = validator.validate( new Bar() ); + + ConstraintViolationAssert.assertThat( violations ).containsOnlyViolations( + violationOf( NotNull.class ).withProperty( "bar" ) + ); + } + + private static class Bar { + + @Size(min = 10, max = 100) + private final String tags = ""; + + @NotEmpty + public List getTags() { + return Arrays.stream( tags.split( "," ) ) + .filter( tag -> !tag.trim().isEmpty() ) + .collect( Collectors.toList() ); + } + } + + private static class Foo { + + @Min(10) + public int fooMethod() { + return 1; + } + + @Max(-10) + public int getMethod() { + return 1; + } + } + + private static class NoPrefixFoo { + + @Min(10) + public int test() { + return 1; + } + + @NotBlank + public String name() { + return ""; + } + + @NotBlank + public String getName() { + return ""; + } + + @AssertTrue + public boolean isTest() { + return false; + } + + @Max(-10) + public int getTest() { + return 1; + } + } + + public static class NoPrefixGetterPropertySelectionStrategy implements GetterPropertySelectionStrategy { + + @Override + public boolean isGetter(ConstrainableExecutable executable) { + String name = executable.getName(); + return executable.getParameterTypes().length == 0 + && !name.startsWith( "is" ) + && !name.startsWith( "get" ); + } + + @Override + public String getPropertyName(ConstrainableExecutable method) { + return method.getName(); + } + } + + public static class FooGetterPropertySelectionStrategy implements GetterPropertySelectionStrategy { + + @Override + public boolean isGetter(ConstrainableExecutable executable) { + return executable.getParameterTypes().length == 0 + && executable.getName().startsWith( "foo" ); + } + + @Override + public String getPropertyName(ConstrainableExecutable method) { + char[] chars = method.getName().substring( 3 ).toCharArray(); + chars[0] = Character.toLowerCase( chars[0] ); + return new String( chars ); + } + } + + private static class ConstrainableExecutableImpl implements ConstrainableExecutable { + + private final Method method; + + private ConstrainableExecutableImpl(Method method) { + this.method = method; + } + + @Override + public Class getReturnType() { + return method.getReturnType(); + } + + @Override + public String getName() { + return method.getName(); + } + + @Override + public Type[] getParameterTypes() { + return method.getParameterTypes(); + } + } +} From 12afdbb19bb7783075c0ce4931546ac94d721e80 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Fri, 15 Jun 2018 17:47:26 +0200 Subject: [PATCH 096/393] HV-1363 Limit the number of methods search when looking for getters --- ...efaultGetterPropertySelectionStrategy.java | 15 ++++ .../properties/javabean/JavaBeanHelper.java | 37 +++++----- .../GetMethodFromPropertyNameCandidates.java | 70 +++++++++++++++++++ .../GetterPropertySelectionStrategy.java | 12 ++++ .../GetterPropertySelectionStrategyTest.java | 11 +++ 5 files changed, 125 insertions(+), 20 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetMethodFromPropertyNameCandidates.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/DefaultGetterPropertySelectionStrategy.java b/engine/src/main/java/org/hibernate/validator/internal/properties/DefaultGetterPropertySelectionStrategy.java index 31c3e767a0..e24c38dc38 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/DefaultGetterPropertySelectionStrategy.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/DefaultGetterPropertySelectionStrategy.java @@ -6,6 +6,10 @@ */ package org.hibernate.validator.internal.properties; +import java.util.Set; + +import org.hibernate.validator.internal.util.CollectionHelper; +import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.StringHelper; import org.hibernate.validator.spi.properties.ConstrainableExecutable; import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; @@ -74,4 +78,15 @@ public String getPropertyName(ConstrainableExecutable executable) { } return null; } + + @Override + public Set getGetterMethodNameCandidates(String propertyName) { + Contracts.assertNotEmpty( propertyName, "Name of a property must not be empty" ); + + Set nameCandidates = CollectionHelper.newHashSet( GETTER_PREFIXES.length ); + for ( String prefix : GETTER_PREFIXES ) { + nameCandidates.add( prefix + Character.toUpperCase( propertyName.charAt( 0 ) ) + propertyName.substring( 1 ) ); + } + return nameCandidates; + } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java index c71882ca15..0a978f478d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java @@ -22,8 +22,7 @@ import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredConstructor; import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredField; import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethod; -import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethods; -import org.hibernate.validator.internal.util.privilegedactions.GetMethods; +import org.hibernate.validator.internal.util.privilegedactions.GetMethodFromPropertyNameCandidates; import org.hibernate.validator.spi.properties.ConstrainableExecutable; import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; @@ -55,32 +54,30 @@ public Optional findDeclaredField(Class declaringClass, String public Optional findDeclaredGetter(Class declaringClass, String property) { Contracts.assertNotNull( declaringClass, MESSAGES.classCannotBeNull() ); - return findGetter( declaringClass, run( GetDeclaredMethods.action( declaringClass ) ), property ); + return findGetter( declaringClass, property, false ); } - private Optional findGetter(Class declaringClass, Method[] methods, String property) { - for ( Method method : methods ) { - JavaBeanConstrainableExecutable executable = new JavaBeanConstrainableExecutable( method ); - if ( getterPropertySelectionStrategy.isGetter( executable ) - && property.equals( getterPropertySelectionStrategy.getPropertyName( executable ) ) ) { - return Optional.of( new JavaBeanGetter( declaringClass, method, getterPropertySelectionStrategy.getPropertyName( executable ) ) ); - } - } - return Optional.empty(); - } - - public Optional findGetter(Class declaringClass, String property) { Contracts.assertNotNull( declaringClass, MESSAGES.classCannotBeNull() ); - Optional declaredGetterProperty = findDeclaredGetter( declaringClass, property ); + return findGetter( declaringClass, property, true ); + } - if ( declaredGetterProperty.isPresent() ) { - return declaredGetterProperty; + private Optional findGetter(Class declaringClass, String property, boolean lookForMethodsOnSuperClass) { + Method getter = run( + GetMethodFromPropertyNameCandidates.action( + declaringClass, + getterPropertySelectionStrategy.getGetterMethodNameCandidates( property ), + lookForMethodsOnSuperClass + ) + ); + if ( getter == null ) { + return Optional.empty(); } else { - // look for getters from the superclasses and interfaces - return findGetter( declaringClass, run( GetMethods.action( declaringClass ) ), property ); + return Optional.of( + new JavaBeanGetter( declaringClass, getter, getterPropertySelectionStrategy.getPropertyName( new JavaBeanConstrainableExecutable( getter ) ) ) + ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetMethodFromPropertyNameCandidates.java b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetMethodFromPropertyNameCandidates.java new file mode 100644 index 0000000000..add89fa4da --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetMethodFromPropertyNameCandidates.java @@ -0,0 +1,70 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.util.privilegedactions; + +import java.lang.reflect.Method; +import java.security.PrivilegedAction; +import java.util.Set; + +/** + * Returns the method with the specified property name or {@code null} if it does not exist. This action will + * iterate through getter name candidates and return the first found method. + *

+ * {@code GetMethodFromPropertyName#lookForMethodsOnSuperClass} parameter controls if we need to check for methods on + * superclasses/implemented interfaces or not, if equals to {@code false} it will use + * {@link Class#getDeclaredMethod(String, Class[])}, and {@link Class#getMethod(String, Class[])} otherwise. + * + * @author Emmanuel Bernard + * @author Hardy Ferentschik + * @author Marko Bekhta + */ +public final class GetMethodFromPropertyNameCandidates implements PrivilegedAction { + + private final Class clazz; + private final Set getterNameCandidates; + private final boolean lookForMethodsOnSuperClass; + + private GetMethodFromPropertyNameCandidates(Class clazz, Set getterNameCandidates, boolean lookForMethodsOnSuperClass) { + this.clazz = clazz; + this.getterNameCandidates = getterNameCandidates; + this.lookForMethodsOnSuperClass = lookForMethodsOnSuperClass; + } + + public static GetMethodFromPropertyNameCandidates action(Class clazz, Set getterNameCandidates) { + return new GetMethodFromPropertyNameCandidates( clazz, getterNameCandidates, false ); + } + + public static GetMethodFromPropertyNameCandidates action(Class clazz, Set possibleMethodNames, boolean lookForMethodsOnSuperClass) { + return new GetMethodFromPropertyNameCandidates( clazz, possibleMethodNames, lookForMethodsOnSuperClass ); + } + + + @Override + public Method run() { + for ( String methodName : getterNameCandidates ) { + try { + return clazz.getDeclaredMethod( methodName ); + } + catch (NoSuchMethodException e) { + // just ignore the exception + } + } + + if ( lookForMethodsOnSuperClass ) { + for ( String methodName : getterNameCandidates ) { + try { + return clazz.getMethod( methodName ); + } + catch (NoSuchMethodException e) { + // just ignore the exception + } + } + } + + return null; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/spi/properties/GetterPropertySelectionStrategy.java b/engine/src/main/java/org/hibernate/validator/spi/properties/GetterPropertySelectionStrategy.java index 24aa059d96..d48aa88f4e 100644 --- a/engine/src/main/java/org/hibernate/validator/spi/properties/GetterPropertySelectionStrategy.java +++ b/engine/src/main/java/org/hibernate/validator/spi/properties/GetterPropertySelectionStrategy.java @@ -6,6 +6,8 @@ */ package org.hibernate.validator.spi.properties; +import java.util.Set; + import org.hibernate.validator.Incubating; import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; @@ -50,4 +52,14 @@ public interface GetterPropertySelectionStrategy { */ String getPropertyName(ConstrainableExecutable method); + /** + * Gives a set of possible method names from based on a getter property name. Usually it means + * a property name prefixed with something like "get", "is", "has" etc. + * + * @param propertyName getter property name + * + * @return {@link Set} of possible method names + */ + Set getGetterMethodNameCandidates(String propertyName); + } diff --git a/engine/src/test/java/org/hibernate/validator/test/properties/GetterPropertySelectionStrategyTest.java b/engine/src/test/java/org/hibernate/validator/test/properties/GetterPropertySelectionStrategyTest.java index 49c5c68632..05fdffee89 100644 --- a/engine/src/test/java/org/hibernate/validator/test/properties/GetterPropertySelectionStrategyTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/properties/GetterPropertySelectionStrategyTest.java @@ -12,6 +12,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -231,6 +232,11 @@ public boolean isGetter(ConstrainableExecutable executable) { public String getPropertyName(ConstrainableExecutable method) { return method.getName(); } + + @Override + public Set getGetterMethodNameCandidates(String propertyName) { + return Collections.singleton( propertyName ); + } } public static class FooGetterPropertySelectionStrategy implements GetterPropertySelectionStrategy { @@ -247,6 +253,11 @@ public String getPropertyName(ConstrainableExecutable method) { chars[0] = Character.toLowerCase( chars[0] ); return new String( chars ); } + + @Override + public Set getGetterMethodNameCandidates(String propertyName) { + return Collections.singleton( "foo" + Character.toUpperCase( propertyName.charAt( 0 ) ) + propertyName.substring( 1 ) ); + } } private static class ConstrainableExecutableImpl implements ConstrainableExecutable { From d0c58dfa1ec45f8b1aabd04ef651aac1a566b568 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Fri, 15 Jun 2018 18:10:09 +0200 Subject: [PATCH 097/393] HV-1363 Throw an exception if the property name cannot be constructed --- .../DefaultGetterPropertySelectionStrategy.java | 9 ++++++++- .../internal/properties/javabean/JavaBeanGetter.java | 3 +++ .../spi/properties/GetterPropertySelectionStrategy.java | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/DefaultGetterPropertySelectionStrategy.java b/engine/src/main/java/org/hibernate/validator/internal/properties/DefaultGetterPropertySelectionStrategy.java index e24c38dc38..57588c5d1e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/DefaultGetterPropertySelectionStrategy.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/DefaultGetterPropertySelectionStrategy.java @@ -6,11 +6,14 @@ */ package org.hibernate.validator.internal.properties; +import java.lang.invoke.MethodHandles; import java.util.Set; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.StringHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.spi.properties.ConstrainableExecutable; import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; @@ -19,6 +22,8 @@ */ public class DefaultGetterPropertySelectionStrategy implements GetterPropertySelectionStrategy { + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + private static final String GETTER_PREFIX_GET = "get"; private static final String GETTER_PREFIX_IS = "is"; private static final String GETTER_PREFIX_HAS = "has"; @@ -70,13 +75,15 @@ else if ( methodName.startsWith( GETTER_PREFIX_HAS ) && executable.getReturnType @Override public String getPropertyName(ConstrainableExecutable executable) { + Contracts.assertNotNull( executable, "executable cannot be null" ); + String methodName = executable.getName(); for ( String prefix : GETTER_PREFIXES ) { if ( methodName.startsWith( prefix ) ) { return StringHelper.decapitalize( methodName.substring( prefix.length() ) ); } } - return null; + throw LOG.getIllegalArgumentException( "Property name cannot be constructed for a given method " + executable.getName() ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java index 63ee3de9b5..f4993ec2ba 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java @@ -14,6 +14,7 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Getter; import org.hibernate.validator.internal.properties.PropertyAccessor; +import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethod; @@ -35,6 +36,8 @@ public class JavaBeanGetter extends JavaBeanMethod implements Getter { public JavaBeanGetter(Class declaringClass, Method method, String propertyName) { super( method ); + Contracts.assertNotNull( propertyName, "Property name cannot be null." ); + this.declaringClass = declaringClass; this.propertyName = propertyName; } diff --git a/engine/src/main/java/org/hibernate/validator/spi/properties/GetterPropertySelectionStrategy.java b/engine/src/main/java/org/hibernate/validator/spi/properties/GetterPropertySelectionStrategy.java index d48aa88f4e..b00628c955 100644 --- a/engine/src/main/java/org/hibernate/validator/spi/properties/GetterPropertySelectionStrategy.java +++ b/engine/src/main/java/org/hibernate/validator/spi/properties/GetterPropertySelectionStrategy.java @@ -49,6 +49,8 @@ public interface GetterPropertySelectionStrategy { * @param method the {@link ConstrainableExecutable} which methods name should be transformed * * @return a property name of a given executable + * + * @throws IllegalArgumentException If a propert name cannot be constructed */ String getPropertyName(ConstrainableExecutable method); From c8700bc291e705b6ec26b4d4248a445fc7b0d2d2 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Sat, 16 Jun 2018 20:56:21 +0200 Subject: [PATCH 098/393] HV-1363 Add documentation section on getter property selection strategy --- documentation/src/main/asciidoc/ch12.asciidoc | 78 +++++++++++++++++++ .../GetterPropertySelectionStrategyTest.java | 51 ++++++++++++ ...PrefixGetterPropertySelectionStrategy.java | 33 ++++++++ .../getterselectionstrategy/User.java | 38 +++++++++ ...property-selection-strategy-validation.xml | 12 +++ 5 files changed, 212 insertions(+) create mode 100644 documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/GetterPropertySelectionStrategyTest.java create mode 100644 documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/NoPrefixGetterPropertySelectionStrategy.java create mode 100644 documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/User.java create mode 100644 documentation/src/test/resources/org/hibernate/validator/referenceguide/chapter12/getter-property-selection-strategy-validation.xml diff --git a/documentation/src/main/asciidoc/ch12.asciidoc b/documentation/src/main/asciidoc/ch12.asciidoc index 9837d1f7da..3a5a7b8940 100644 --- a/documentation/src/main/asciidoc/ch12.asciidoc +++ b/documentation/src/main/asciidoc/ch12.asciidoc @@ -675,3 +675,81 @@ Call `ValidatorFactory#close()` if a given validator factory instance is not nee Failure to do so may result in a class loader leak in cases where applications/bundles are re-deployed and a non-closed validator factory still is referenced by application code. ==== + +[[section-getter-property-selection-strategy]] +=== Getter property selection strategy configuration + +When a regular validation operation is performed on an object it's properties get validated. Per +JavaBean specification, a property can either be a field or a getter. Hibernate Validator uses +next set of rules to determine if a method is a getter or not: + +- a method name starts with `get`, it has a nonvoid return type and has no parameters +- a method name starts with `is`, has a return type of `boolean` and has no parameters +- a method name starts with `has`, has a return type of `boolean` and has no parameters (this +is a Hibernate Validator specific rule and is not mandated by the JavaBeans specification) + +If any of the statements above are true - method is considered a getter. + +When working with objects that do not follow JavaBean specification rules on getters. These rules +should either be redefined or extended, in order to be able to fully validate the object. An example +of such objects can be the ones constructed from classes that follow fluent design pattern (i.e. <> ). + +[[example-using-fluent-api-pattern]] +.A data class that uses nonstandard getters +==== +[source, JAVA, indent=0] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/User.java[tags=include] +---- +==== + +If such object gets validated no validation will be performed on the methods: + +.Validating a class with nonstandard getters and default getter property selection strategy +==== +[source, JAVA, indent=0] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/GetterPropertySelectionStrategyTest.java[tags=no-strategy] +---- +==== + +To make Hibernate Validator treat such methods as getter properties a custom `GetterPropertySelectionStrategy` +should be configured. In particular case the strategy can be implemeted like: + +.Custom GetterPropertySelectionStrategy implementation +==== +[source, JAVA, indent=0] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/NoPrefixGetterPropertySelectionStrategy.java[tags=include] +---- +==== + +There are multiple ways to configuring Hibernate Validator to use such strategy. It can either be done +programmatically (<>) or via the +`hibernate.validator.getter_property_selection_strategy` property using XML configuration (<>). + +[[custom-getter-strategy-programmatically]] +.Configuring the custom `GetterPropertySelectionStrategy` programmatically +==== +[source, JAVA, indent=0] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/GetterPropertySelectionStrategyTest.java[tags=custom-strategy] +---- +==== + +[[custom-getter-strategy-xml]] +.Configuring the custom `GetterPropertySelectionStrategy` using XML property +==== +[source, XML, indent=0] +---- +include::{resourcesdir}/org/hibernate/validator/referenceguide/chapter12/getter-property-selection-strategy-validation.xml[] +---- +==== + +[WARNING] +==== +It is important to mention that in cases when any programmatic constraints are added using +`HibernateValidatorConfiguration#addMapping(ConstraintMapping)` it should be done after the +required getter property selection strategy is configured. Otherwise, the default one will be +used. +==== \ No newline at end of file diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/GetterPropertySelectionStrategyTest.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/GetterPropertySelectionStrategyTest.java new file mode 100644 index 0000000000..ac3041ce2d --- /dev/null +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/GetterPropertySelectionStrategyTest.java @@ -0,0 +1,51 @@ +package org.hibernate.validator.referenceguide.chapter12.getterselectionstrategy; + +import static org.junit.Assert.assertEquals; + +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; + +import org.hibernate.validator.HibernateValidator; + +import org.junit.Test; + +public class GetterPropertySelectionStrategyTest { + + @Test + public void defaultStrategyUsed() { + //tag::no-strategy[] + Validator validator = Validation.byProvider( HibernateValidator.class ) + .configure() + .buildValidatorFactory() + .getValidator(); + + User user = new User( "", "", "not an email" ); + + Set> constraintViolations = validator.validate( user ); + + // as User has nonstandard getters no violations are triggered + assertEquals( 0, constraintViolations.size() ); + //end::no-strategy[] + } + + @Test + public void customNoPrefixStrategyUsed() { + //tag::custom-strategy[] + Validator validator = Validation.byProvider( HibernateValidator.class ) + .configure() + // Setting a custom getter property selection strategy + .getterPropertySelectionStrategy( new NoPrefixGetterPropertySelectionStrategy() ) + .buildValidatorFactory() + .getValidator(); + + User user = new User( "first", "last", "not an email" ); + + Set> constraintViolations = validator.validate( user ); + + assertEquals( 1, constraintViolations.size() ); + //end::custom-strategy[] + } +} diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/NoPrefixGetterPropertySelectionStrategy.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/NoPrefixGetterPropertySelectionStrategy.java new file mode 100644 index 0000000000..e65f52c862 --- /dev/null +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/NoPrefixGetterPropertySelectionStrategy.java @@ -0,0 +1,33 @@ +//tag::include[] +package org.hibernate.validator.referenceguide.chapter12.getterselectionstrategy; + +//end::include[] +import java.util.Collections; +import java.util.Set; + +import org.hibernate.validator.spi.properties.ConstrainableExecutable; +import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; + +//tag::include[] +public class NoPrefixGetterPropertySelectionStrategy implements GetterPropertySelectionStrategy { + + @Override + public boolean isGetter(ConstrainableExecutable executable) { + // We check that the method has non void return type and no parameters. + // And we do not care about method name at all. + return executable.getReturnType() != void.class + && executable.getParameterTypes().length == 0; + } + + @Override + public String getPropertyName(ConstrainableExecutable method) { + return method.getName(); + } + + @Override + public Set getGetterMethodNameCandidates(String propertyName) { + // As method name == property name there always is just one possible name for a method + return Collections.singleton( propertyName ); + } +} +//end::include[] diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/User.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/User.java new file mode 100644 index 0000000000..74ae800452 --- /dev/null +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/User.java @@ -0,0 +1,38 @@ +//tag::include[] +package org.hibernate.validator.referenceguide.chapter12.getterselectionstrategy; + +//end::include[] +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; + +//tag::include[] +public class User { + + private final String firstName; + private final String lastName; + private final String email; + + //end::include[] + public User(String firstName, String lastName, String email) { + this.firstName = firstName; + this.lastName = lastName; + this.email = email; + } + + //tag::include[] + @NotEmpty + public String firstName() { + return firstName; + } + + @NotEmpty + public String lastName() { + return lastName; + } + + @Email + public String email() { + return email; + } +} +//end::include[] diff --git a/documentation/src/test/resources/org/hibernate/validator/referenceguide/chapter12/getter-property-selection-strategy-validation.xml b/documentation/src/test/resources/org/hibernate/validator/referenceguide/chapter12/getter-property-selection-strategy-validation.xml new file mode 100644 index 0000000000..fe08b7ca72 --- /dev/null +++ b/documentation/src/test/resources/org/hibernate/validator/referenceguide/chapter12/getter-property-selection-strategy-validation.xml @@ -0,0 +1,12 @@ + + + + org.hibernate.validator.referenceguide.chapter12.getterselectionstrategy.NoPrefixGetterPropertySelectionStrategy + + + From cc606a286435e8d5a8c3ebf9fec9de95d1b35d9e Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 19 Jun 2018 10:30:46 +0200 Subject: [PATCH 099/393] HV-1363 Improve the documentation --- documentation/src/main/asciidoc/ch12.asciidoc | 61 +++++++++++-------- .../GetterPropertySelectionStrategyTest.java | 6 +- ...PrefixGetterPropertySelectionStrategy.java | 6 +- .../getterselectionstrategy/User.java | 8 ++- 4 files changed, 45 insertions(+), 36 deletions(-) diff --git a/documentation/src/main/asciidoc/ch12.asciidoc b/documentation/src/main/asciidoc/ch12.asciidoc index 3a5a7b8940..e6d0202b2a 100644 --- a/documentation/src/main/asciidoc/ch12.asciidoc +++ b/documentation/src/main/asciidoc/ch12.asciidoc @@ -677,25 +677,29 @@ validator factory still is referenced by application code. ==== [[section-getter-property-selection-strategy]] -=== Getter property selection strategy configuration +=== Customizing the getter property selection strategy -When a regular validation operation is performed on an object it's properties get validated. Per -JavaBean specification, a property can either be a field or a getter. Hibernate Validator uses -next set of rules to determine if a method is a getter or not: +When a bean is validated by Hibernate Validator, its properties get validated. A property can either +be a field or a getter. +By default, Hibernate Validator respects the JavaBeans specification and considers a method as a getter as soon +as one of the conditions below is true: -- a method name starts with `get`, it has a nonvoid return type and has no parameters -- a method name starts with `is`, has a return type of `boolean` and has no parameters -- a method name starts with `has`, has a return type of `boolean` and has no parameters (this -is a Hibernate Validator specific rule and is not mandated by the JavaBeans specification) +- the method name starts with `get`, it has a non-void return type and has no parameters; +- the method name starts with `is`, has a return type of `boolean` and has no parameters; +- the method name starts with `has`, has a return type of `boolean` and has no parameters (this rule +is specific to Hibernate Validator and is not mandated by the JavaBeans specification) -If any of the statements above are true - method is considered a getter. +While these rules are usually appropriate when following the classic JavaBeans convention, it might happen, +especially with code generators, that the JavaBeans naming convention is not followed and that the getters' +names are following a different convention. -When working with objects that do not follow JavaBean specification rules on getters. These rules -should either be redefined or extended, in order to be able to fully validate the object. An example -of such objects can be the ones constructed from classes that follow fluent design pattern (i.e. <> ). +In this case, the strategy for detecting getters should be redefined in order to fully validate the object. + +A classic example of this requirement is when the classes follow a fluent naming convention, +as illustrated in <>. [[example-using-fluent-api-pattern]] -.A data class that uses nonstandard getters +.A class that uses non-standard getters ==== [source, JAVA, indent=0] ---- @@ -703,9 +707,10 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/gettersele ---- ==== -If such object gets validated no validation will be performed on the methods: +If such object gets validated, no validation will be performed on the getters as they are not detected +by the standard strategy. -.Validating a class with nonstandard getters and default getter property selection strategy +.Validating a class with non-standard getters using the default getter property selection strategy ==== [source, JAVA, indent=0] ---- @@ -713,10 +718,11 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/gettersele ---- ==== -To make Hibernate Validator treat such methods as getter properties a custom `GetterPropertySelectionStrategy` -should be configured. In particular case the strategy can be implemeted like: +To make Hibernate Validator treat such methods as properties, a custom `GetterPropertySelectionStrategy` +should be configured. +In this particular case, a possible implementation of the strategy would be: -.Custom GetterPropertySelectionStrategy implementation +.Custom `GetterPropertySelectionStrategy` implementation ==== [source, JAVA, indent=0] ---- @@ -724,12 +730,13 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/gettersele ---- ==== -There are multiple ways to configuring Hibernate Validator to use such strategy. It can either be done -programmatically (<>) or via the -`hibernate.validator.getter_property_selection_strategy` property using XML configuration (<>). +There are multiple ways to configure Hibernate Validator to use this strategy. It can either be done +programmatically (see <>) or by using the +`hibernate.validator.getter_property_selection_strategy` property in the XML configuration +(see <>). [[custom-getter-strategy-programmatically]] -.Configuring the custom `GetterPropertySelectionStrategy` programmatically +.Configuring a custom `GetterPropertySelectionStrategy` programmatically ==== [source, JAVA, indent=0] ---- @@ -738,7 +745,7 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/gettersele ==== [[custom-getter-strategy-xml]] -.Configuring the custom `GetterPropertySelectionStrategy` using XML property +.Configuring a custom `GetterPropertySelectionStrategy` using an XML property ==== [source, XML, indent=0] ---- @@ -748,8 +755,8 @@ include::{resourcesdir}/org/hibernate/validator/referenceguide/chapter12/getter- [WARNING] ==== -It is important to mention that in cases when any programmatic constraints are added using -`HibernateValidatorConfiguration#addMapping(ConstraintMapping)` it should be done after the -required getter property selection strategy is configured. Otherwise, the default one will be -used. +It is important to mention that in cases where programmatic constraints are added using +`HibernateValidatorConfiguration#addMapping(ConstraintMapping)`, adding mappings should +always be done after the required getter property selection strategy is configured. +Otherwise, the default strategy will be used for the mappings added before defining the strategy. ==== \ No newline at end of file diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/GetterPropertySelectionStrategyTest.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/GetterPropertySelectionStrategyTest.java index ac3041ce2d..1776be3d32 100644 --- a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/GetterPropertySelectionStrategyTest.java +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/GetterPropertySelectionStrategyTest.java @@ -26,7 +26,7 @@ public void defaultStrategyUsed() { Set> constraintViolations = validator.validate( user ); - // as User has nonstandard getters no violations are triggered + // as User has non-standard getters no violations are triggered assertEquals( 0, constraintViolations.size() ); //end::no-strategy[] } @@ -41,11 +41,11 @@ public void customNoPrefixStrategyUsed() { .buildValidatorFactory() .getValidator(); - User user = new User( "first", "last", "not an email" ); + User user = new User( "", "", "not an email" ); Set> constraintViolations = validator.validate( user ); - assertEquals( 1, constraintViolations.size() ); + assertEquals( 3, constraintViolations.size() ); //end::custom-strategy[] } } diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/NoPrefixGetterPropertySelectionStrategy.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/NoPrefixGetterPropertySelectionStrategy.java index e65f52c862..8199c0e9b3 100644 --- a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/NoPrefixGetterPropertySelectionStrategy.java +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/NoPrefixGetterPropertySelectionStrategy.java @@ -13,8 +13,8 @@ public class NoPrefixGetterPropertySelectionStrategy implements GetterPropertySe @Override public boolean isGetter(ConstrainableExecutable executable) { - // We check that the method has non void return type and no parameters. - // And we do not care about method name at all. + // We check that the method has a non-void return type and no parameters. + // And we do not care about the method name. return executable.getReturnType() != void.class && executable.getParameterTypes().length == 0; } @@ -26,7 +26,7 @@ public String getPropertyName(ConstrainableExecutable method) { @Override public Set getGetterMethodNameCandidates(String propertyName) { - // As method name == property name there always is just one possible name for a method + // As method name == property name, there always is just one possible name for a method return Collections.singleton( propertyName ); } } diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/User.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/User.java index 74ae800452..787120fe90 100644 --- a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/User.java +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/User.java @@ -8,9 +8,11 @@ //tag::include[] public class User { - private final String firstName; - private final String lastName; - private final String email; + private String firstName; + private String lastName; + private String email; + + // [...] //end::include[] public User(String firstName, String lastName, String email) { From 668bea33aaf2833df077ae601de3dbecf8165c9f Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 19 Jun 2018 11:00:43 +0200 Subject: [PATCH 100/393] HV-1363 Some editorialization --- .../HibernateValidatorConfiguration.java | 3 +- .../validator/HibernateValidatorFactory.java | 2 +- .../cfg/context/DefaultConstraintMapping.java | 2 +- .../TypeConstraintMappingContextImpl.java | 2 +- .../internal/engine/ValidatorFactoryImpl.java | 5 ++- .../properties/javabean/JavaBeanHelper.java | 4 +- .../validator/internal/util/logging/Log.java | 3 -- ...=> GetMethodFromGetterNameCandidates.java} | 38 ++++++++----------- .../GetterPropertySelectionStrategy.java | 32 ++++++++-------- .../spi/properties/package-info.java | 2 +- .../GetterPropertySelectionStrategyTest.java | 3 +- 11 files changed, 44 insertions(+), 52 deletions(-) rename engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/{GetMethodFromPropertyNameCandidates.java => GetMethodFromGetterNameCandidates.java} (50%) diff --git a/engine/src/main/java/org/hibernate/validator/HibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/HibernateValidatorConfiguration.java index 4de05535e7..37ef2cba01 100644 --- a/engine/src/main/java/org/hibernate/validator/HibernateValidatorConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/HibernateValidatorConfiguration.java @@ -323,7 +323,8 @@ public interface HibernateValidatorConfiguration extends Configuration TypeConstraintMappingContext type(Class type) { throw LOG.getBeanClassHasAlreadyBeConfiguredViaProgrammaticApiException( type ); } - TypeConstraintMappingContextImpl typeContext = new TypeConstraintMappingContextImpl<>( this, type, javaBeanHelper ); + TypeConstraintMappingContextImpl typeContext = new TypeConstraintMappingContextImpl<>( javaBeanHelper, this, type ); typeContexts.add( typeContext ); configuredTypes.add( type ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java index 4fc7c9c869..fcf2d401dc 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java @@ -70,7 +70,7 @@ public final class TypeConstraintMappingContextImpl extends ConstraintMapping private List> defaultGroupSequence; private Class> defaultGroupSequenceProviderClass; - TypeConstraintMappingContextImpl(DefaultConstraintMapping mapping, Class beanClass, JavaBeanHelper javaBeanHelper) { + TypeConstraintMappingContextImpl(JavaBeanHelper javaBeanHelper, DefaultConstraintMapping mapping, Class beanClass) { super( mapping ); this.javaBeanHelper = javaBeanHelper; this.beanClass = beanClass; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java index 5eac4bc7e4..8da528f0be 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java @@ -155,7 +155,7 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { Map properties = configurationState.getProperties(); - this.javaBeanHelper = new JavaBeanHelper( getterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ) ); + this.javaBeanHelper = new JavaBeanHelper( getGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ) ); // HV-302; don't load XmlMappingParser if not necessary if ( configurationState.getMappingStreams().isEmpty() ) { @@ -564,7 +564,8 @@ private Object getConstraintValidatorPayload(ConfigurationState configurationSta return null; } - private static GetterPropertySelectionStrategy getterPropertySelectionStrategy(ConfigurationImpl hibernateSpecificConfig, Map properties, ClassLoader externalClassLoader) { + private static GetterPropertySelectionStrategy getGetterPropertySelectionStrategy(ConfigurationImpl hibernateSpecificConfig, Map properties, + ClassLoader externalClassLoader) { if ( hibernateSpecificConfig.getGetterPropertySelectionStrategy() != null ) { LOG.usingGetterPropertySelectionStrategy( hibernateSpecificConfig.getGetterPropertySelectionStrategy().getClass() ); return hibernateSpecificConfig.getGetterPropertySelectionStrategy(); diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java index 0a978f478d..572922225e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java @@ -22,7 +22,7 @@ import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredConstructor; import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredField; import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethod; -import org.hibernate.validator.internal.util.privilegedactions.GetMethodFromPropertyNameCandidates; +import org.hibernate.validator.internal.util.privilegedactions.GetMethodFromGetterNameCandidates; import org.hibernate.validator.spi.properties.ConstrainableExecutable; import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; @@ -65,7 +65,7 @@ public Optional findGetter(Class declaringClass, String prope private Optional findGetter(Class declaringClass, String property, boolean lookForMethodsOnSuperClass) { Method getter = run( - GetMethodFromPropertyNameCandidates.action( + GetMethodFromGetterNameCandidates.action( declaringClass, getterPropertySelectionStrategy.getGetterMethodNameCandidates( property ), lookForMethodsOnSuperClass diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 3410782855..3382783496 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -872,7 +872,4 @@ ConstraintDefinitionException getConstraintValidatorDefinitionConstraintMismatch @Message(id = 247, value = "Unable to instantiate getter property selection strategy class %s.") ValidationException getUnableToInstantiateGetterPropertySelectionStrategyClassException(String getterPropertySelectionStrategyClassName, @Cause Exception e); - - @Message(id = 248, value = "Unable to access field %3$s of class %2$s using lookup %1$s.") - ValidationException getUnableToAccessFieldException(Lookup lookup, @FormatWith(ClassObjectFormatter.class) Class clazz, String property, @Cause Throwable e); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetMethodFromPropertyNameCandidates.java b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetMethodFromGetterNameCandidates.java similarity index 50% rename from engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetMethodFromPropertyNameCandidates.java rename to engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetMethodFromGetterNameCandidates.java index add89fa4da..73fd5f8351 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetMethodFromPropertyNameCandidates.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetMethodFromGetterNameCandidates.java @@ -14,32 +14,30 @@ * Returns the method with the specified property name or {@code null} if it does not exist. This action will * iterate through getter name candidates and return the first found method. *

- * {@code GetMethodFromPropertyName#lookForMethodsOnSuperClass} parameter controls if we need to check for methods on + * {@code GetMethodFromPropertyName#lookForMethodsInHierarchy} parameter controls if we need to check for methods on * superclasses/implemented interfaces or not, if equals to {@code false} it will use * {@link Class#getDeclaredMethod(String, Class[])}, and {@link Class#getMethod(String, Class[])} otherwise. * - * @author Emmanuel Bernard - * @author Hardy Ferentschik * @author Marko Bekhta */ -public final class GetMethodFromPropertyNameCandidates implements PrivilegedAction { +public final class GetMethodFromGetterNameCandidates implements PrivilegedAction { private final Class clazz; private final Set getterNameCandidates; - private final boolean lookForMethodsOnSuperClass; + private final boolean lookForMethodsInHierarchy; - private GetMethodFromPropertyNameCandidates(Class clazz, Set getterNameCandidates, boolean lookForMethodsOnSuperClass) { + private GetMethodFromGetterNameCandidates(Class clazz, Set getterNameCandidates, boolean lookForMethodsInHierarchy) { this.clazz = clazz; this.getterNameCandidates = getterNameCandidates; - this.lookForMethodsOnSuperClass = lookForMethodsOnSuperClass; + this.lookForMethodsInHierarchy = lookForMethodsInHierarchy; } - public static GetMethodFromPropertyNameCandidates action(Class clazz, Set getterNameCandidates) { - return new GetMethodFromPropertyNameCandidates( clazz, getterNameCandidates, false ); + public static GetMethodFromGetterNameCandidates action(Class clazz, Set getterNameCandidates) { + return new GetMethodFromGetterNameCandidates( clazz, getterNameCandidates, false ); } - public static GetMethodFromPropertyNameCandidates action(Class clazz, Set possibleMethodNames, boolean lookForMethodsOnSuperClass) { - return new GetMethodFromPropertyNameCandidates( clazz, possibleMethodNames, lookForMethodsOnSuperClass ); + public static GetMethodFromGetterNameCandidates action(Class clazz, Set possibleMethodNames, boolean lookForMethodsInHierarchy) { + return new GetMethodFromGetterNameCandidates( clazz, possibleMethodNames, lookForMethodsInHierarchy ); } @@ -47,22 +45,16 @@ public static GetMethodFromPropertyNameCandidates action(Class clazz, Set - * A JavaBeans method is considered to be a valid getter method (property), if + * A JavaBean's method is considered to be a valid getter method (property), if * one of the next rules can be applied to it: *

*
    @@ -25,7 +25,7 @@ *
  • its name starts with "has", it has no parameters and is returning {@code boolean}.
  • *
*

- * The last rule is Hibernate Validator specific one and is not mandated by the JavaBeans spec. + * The last rule is specific to Hibernate Validator and is not mandated by the JavaBeans specification. * * @author Marko Bekhta * @since 6.1.0 @@ -34,33 +34,33 @@ public interface GetterPropertySelectionStrategy { /** - * Determines if a given {@link ConstrainableExecutable} is a valid JavaBeans getter method (property). + * Determines if a given {@link ConstrainableExecutable} is a getter method (property). * - * @param executable the {@link ConstrainableExecutable} under test + * @param executable a {@link ConstrainableExecutable} * - * @return {@code true} if given executable is a valid JavaBeans property, {@code false} otherwise + * @return {@code true} if the given executable should be considered a getter, {@code false} otherwise */ boolean isGetter(ConstrainableExecutable executable); /** - * Performs a transformation of JavaBeans method name to its corresponding property name. + * Performs a transformation of a getter method name to its corresponding property name. * For example by removing the prefixes like {@code get}/{@code is} etc. * - * @param method the {@link ConstrainableExecutable} which methods name should be transformed + * @param executable a {@link ConstrainableExecutable} * - * @return a property name of a given executable + * @return the property name corresponding to the given executable * - * @throws IllegalArgumentException If a propert name cannot be constructed + * @throws IllegalArgumentException if a property name cannot be constructed */ - String getPropertyName(ConstrainableExecutable method); + String getPropertyName(ConstrainableExecutable executable); /** - * Gives a set of possible method names from based on a getter property name. Usually it means + * Gives a set of possible method names based on a property name. Usually, it means * a property name prefixed with something like "get", "is", "has" etc. * - * @param propertyName getter property name + * @param propertyName a property name * - * @return {@link Set} of possible method names + * @return the {@link Set} of possible getter names */ Set getGetterMethodNameCandidates(String propertyName); diff --git a/engine/src/main/java/org/hibernate/validator/spi/properties/package-info.java b/engine/src/main/java/org/hibernate/validator/spi/properties/package-info.java index 284e7972a9..cc2ba5b5e5 100644 --- a/engine/src/main/java/org/hibernate/validator/spi/properties/package-info.java +++ b/engine/src/main/java/org/hibernate/validator/spi/properties/package-info.java @@ -6,7 +6,7 @@ */ /** - *

This package provides support for customization of the JavaBeans property detection logic.

+ *

This package provides support for customizing the getter detection logic.

*

This package is part of the public Hibernate Validator SPI.

*/ package org.hibernate.validator.spi.properties; diff --git a/engine/src/test/java/org/hibernate/validator/test/properties/GetterPropertySelectionStrategyTest.java b/engine/src/test/java/org/hibernate/validator/test/properties/GetterPropertySelectionStrategyTest.java index 05fdffee89..4bff1739d5 100644 --- a/engine/src/test/java/org/hibernate/validator/test/properties/GetterPropertySelectionStrategyTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/properties/GetterPropertySelectionStrategyTest.java @@ -223,7 +223,8 @@ public static class NoPrefixGetterPropertySelectionStrategy implements GetterPro @Override public boolean isGetter(ConstrainableExecutable executable) { String name = executable.getName(); - return executable.getParameterTypes().length == 0 + return executable.getReturnType() != void.class + && executable.getParameterTypes().length == 0 && !name.startsWith( "is" ) && !name.startsWith( "get" ); } From 64b5e984de13c9914abfe18eb4c6edcb84521303 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 19 Jun 2018 12:37:01 +0200 Subject: [PATCH 101/393] HV-1363 Ignore Object methods in the fluent convention documentation example --- documentation/src/main/asciidoc/ch12.asciidoc | 2 +- ... FluentGetterPropertySelectionStrategy.java} | 17 +++++++++++++++-- .../GetterPropertySelectionStrategyTest.java | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) rename documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/{NoPrefixGetterPropertySelectionStrategy.java => FluentGetterPropertySelectionStrategy.java} (60%) diff --git a/documentation/src/main/asciidoc/ch12.asciidoc b/documentation/src/main/asciidoc/ch12.asciidoc index e6d0202b2a..5a7534542c 100644 --- a/documentation/src/main/asciidoc/ch12.asciidoc +++ b/documentation/src/main/asciidoc/ch12.asciidoc @@ -726,7 +726,7 @@ In this particular case, a possible implementation of the strategy would be: ==== [source, JAVA, indent=0] ---- -include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/NoPrefixGetterPropertySelectionStrategy.java[tags=include] +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/FluentGetterPropertySelectionStrategy.java[tags=include] ---- ==== diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/NoPrefixGetterPropertySelectionStrategy.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/FluentGetterPropertySelectionStrategy.java similarity index 60% rename from documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/NoPrefixGetterPropertySelectionStrategy.java rename to documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/FluentGetterPropertySelectionStrategy.java index 8199c0e9b3..58025c6f22 100644 --- a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/NoPrefixGetterPropertySelectionStrategy.java +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/FluentGetterPropertySelectionStrategy.java @@ -1,21 +1,34 @@ //tag::include[] package org.hibernate.validator.referenceguide.chapter12.getterselectionstrategy; +import java.lang.reflect.Method; +import java.util.Arrays; //end::include[] import java.util.Collections; import java.util.Set; +import java.util.stream.Collectors; import org.hibernate.validator.spi.properties.ConstrainableExecutable; import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; //tag::include[] -public class NoPrefixGetterPropertySelectionStrategy implements GetterPropertySelectionStrategy { +public class FluentGetterPropertySelectionStrategy implements GetterPropertySelectionStrategy { + + private final Set methodNamesToIgnore; + + public FluentGetterPropertySelectionStrategy() { + // we will ignore all the method names coming from Object + this.methodNamesToIgnore = Arrays.stream( Object.class.getDeclaredMethods() ) + .map( Method::getName ) + .collect( Collectors.toSet() ); + } @Override public boolean isGetter(ConstrainableExecutable executable) { // We check that the method has a non-void return type and no parameters. // And we do not care about the method name. - return executable.getReturnType() != void.class + return !methodNamesToIgnore.contains( executable.getName() ) + && executable.getReturnType() != void.class && executable.getParameterTypes().length == 0; } diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/GetterPropertySelectionStrategyTest.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/GetterPropertySelectionStrategyTest.java index 1776be3d32..b9a8a23006 100644 --- a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/GetterPropertySelectionStrategyTest.java +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/GetterPropertySelectionStrategyTest.java @@ -37,7 +37,7 @@ public void customNoPrefixStrategyUsed() { Validator validator = Validation.byProvider( HibernateValidator.class ) .configure() // Setting a custom getter property selection strategy - .getterPropertySelectionStrategy( new NoPrefixGetterPropertySelectionStrategy() ) + .getterPropertySelectionStrategy( new FluentGetterPropertySelectionStrategy() ) .buildValidatorFactory() .getValidator(); From eaa2cb6e45f95007c18297c2e4faea33e1c6b5ab Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 19 Jun 2018 13:25:34 +0200 Subject: [PATCH 102/393] HV-1363 Various adjustments following Gunnar's review --- .../validator/cdi/ValidationExtension.java | 21 +++---- ...GetterPropertySelectionStrategyHelper.java | 12 ++-- ...FluentGetterPropertySelectionStrategy.java | 22 ++++--- ...efaultGetterPropertySelectionStrategy.java | 58 ++++++++++--------- .../properties/javabean/JavaBeanHelper.java | 11 ++-- .../properties/ConstrainableExecutable.java | 8 +-- .../GetterPropertySelectionStrategy.java | 34 +++-------- .../GetterPropertySelectionStrategyTest.java | 46 +++++++-------- 8 files changed, 95 insertions(+), 117 deletions(-) diff --git a/cdi/src/main/java/org/hibernate/validator/cdi/ValidationExtension.java b/cdi/src/main/java/org/hibernate/validator/cdi/ValidationExtension.java index 858222caa9..b7a2b9bf7c 100644 --- a/cdi/src/main/java/org/hibernate/validator/cdi/ValidationExtension.java +++ b/cdi/src/main/java/org/hibernate/validator/cdi/ValidationExtension.java @@ -17,6 +17,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.function.Predicate; @@ -265,15 +266,16 @@ private void determineConstrainedMethods(AnnotatedType type, BeanDescript for ( AnnotatedMethod annotatedMethod : type.getMethods() ) { Method method = annotatedMethod.getJavaMember(); - boolean isGetter = getterPropertySelectionStrategyHelper.isGetter( method ); + Optional correspondingProperty = getterPropertySelectionStrategyHelper.getProperty( method ); // obtain @ValidateOnExecution from the top-most method in the hierarchy Method methodForExecutableTypeRetrieval = replaceWithOverriddenOrInterfaceMethod( method, overriddenAndImplementedMethods ); EnumSet classLevelExecutableTypes = executableTypesDefinedOnType( methodForExecutableTypeRetrieval.getDeclaringClass() ); - EnumSet memberLevelExecutableType = executableTypesDefinedOnMethod( methodForExecutableTypeRetrieval, isGetter ); + EnumSet memberLevelExecutableType = executableTypesDefinedOnMethod( methodForExecutableTypeRetrieval, + correspondingProperty.isPresent() ); - ExecutableType currentExecutableType = isGetter ? ExecutableType.GETTER_METHODS : ExecutableType.NON_GETTER_METHODS; + ExecutableType currentExecutableType = correspondingProperty.isPresent() ? ExecutableType.GETTER_METHODS : ExecutableType.NON_GETTER_METHODS; // validation is enabled per default, so explicit configuration can just veto whether // validation occurs @@ -282,11 +284,11 @@ private void determineConstrainedMethods(AnnotatedType type, BeanDescript } boolean needsValidation; - if ( isGetter ) { - needsValidation = isGetterConstrained( method, beanDescriptor ); + if ( correspondingProperty.isPresent() ) { + needsValidation = isGetterConstrained( beanDescriptor, method, correspondingProperty.get() ); } else { - needsValidation = isNonGetterConstrained( method, beanDescriptor ); + needsValidation = isNonGetterConstrained( beanDescriptor, method ); } if ( needsValidation ) { @@ -313,13 +315,12 @@ private void determineConstrainedConstructors(AnnotatedType type, BeanDes } } - private boolean isNonGetterConstrained(Method method, BeanDescriptor beanDescriptor) { + private boolean isNonGetterConstrained(BeanDescriptor beanDescriptor, Method method) { return beanDescriptor.getConstraintsForMethod( method.getName(), method.getParameterTypes() ) != null; } - private boolean isGetterConstrained(Method method, BeanDescriptor beanDescriptor) { - String propertyName = getterPropertySelectionStrategyHelper.getPropertyName( method ); - PropertyDescriptor propertyDescriptor = beanDescriptor.getConstraintsForProperty( propertyName ); + private boolean isGetterConstrained(BeanDescriptor beanDescriptor, Method method, String property) { + PropertyDescriptor propertyDescriptor = beanDescriptor.getConstraintsForProperty( property ); return propertyDescriptor != null && propertyDescriptor.findConstraints() .declaredOn( ElementType.METHOD ) .hasConstraints(); diff --git a/cdi/src/main/java/org/hibernate/validator/cdi/internal/util/GetterPropertySelectionStrategyHelper.java b/cdi/src/main/java/org/hibernate/validator/cdi/internal/util/GetterPropertySelectionStrategyHelper.java index edbda53e39..609e53860e 100644 --- a/cdi/src/main/java/org/hibernate/validator/cdi/internal/util/GetterPropertySelectionStrategyHelper.java +++ b/cdi/src/main/java/org/hibernate/validator/cdi/internal/util/GetterPropertySelectionStrategyHelper.java @@ -7,7 +7,7 @@ package org.hibernate.validator.cdi.internal.util; import java.lang.reflect.Method; -import java.lang.reflect.Type; +import java.util.Optional; import javax.validation.ValidatorFactory; @@ -29,12 +29,8 @@ private GetterPropertySelectionStrategyHelper(GetterPropertySelectionStrategy ge this.getterPropertySelectionStrategy = getterPropertySelectionStrategy; } - public boolean isGetter(Method method) { - return getterPropertySelectionStrategy.isGetter( new ConstrainableMethod( method ) ); - } - - public String getPropertyName(Method method) { - return getterPropertySelectionStrategy.getPropertyName( new ConstrainableMethod( method ) ); + public Optional getProperty(Method method) { + return getterPropertySelectionStrategy.getProperty( new ConstrainableMethod( method ) ); } public static GetterPropertySelectionStrategyHelper forValidationFactory(ValidatorFactory factory) { @@ -67,7 +63,7 @@ public String getName() { } @Override - public Type[] getParameterTypes() { + public Class[] getParameterTypes() { return method.getParameterTypes(); } } diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/FluentGetterPropertySelectionStrategy.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/FluentGetterPropertySelectionStrategy.java index 58025c6f22..6885155778 100644 --- a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/FluentGetterPropertySelectionStrategy.java +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/getterselectionstrategy/FluentGetterPropertySelectionStrategy.java @@ -1,10 +1,11 @@ //tag::include[] package org.hibernate.validator.referenceguide.chapter12.getterselectionstrategy; +//end::include[] import java.lang.reflect.Method; import java.util.Arrays; -//end::include[] import java.util.Collections; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -24,17 +25,14 @@ public FluentGetterPropertySelectionStrategy() { } @Override - public boolean isGetter(ConstrainableExecutable executable) { - // We check that the method has a non-void return type and no parameters. - // And we do not care about the method name. - return !methodNamesToIgnore.contains( executable.getName() ) - && executable.getReturnType() != void.class - && executable.getParameterTypes().length == 0; - } - - @Override - public String getPropertyName(ConstrainableExecutable method) { - return method.getName(); + public Optional getProperty(ConstrainableExecutable executable) { + if ( methodNamesToIgnore.contains( executable.getName() ) + || executable.getReturnType() == void.class + || executable.getParameterTypes().length > 0 ) { + return Optional.empty(); + } + + return Optional.of( executable.getName() ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/DefaultGetterPropertySelectionStrategy.java b/engine/src/main/java/org/hibernate/validator/internal/properties/DefaultGetterPropertySelectionStrategy.java index 57588c5d1e..885c340537 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/DefaultGetterPropertySelectionStrategy.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/DefaultGetterPropertySelectionStrategy.java @@ -7,6 +7,7 @@ package org.hibernate.validator.internal.properties; import java.lang.invoke.MethodHandles; +import java.util.Optional; import java.util.Set; import org.hibernate.validator.internal.util.CollectionHelper; @@ -33,6 +34,36 @@ public class DefaultGetterPropertySelectionStrategy implements GetterPropertySel GETTER_PREFIX_HAS }; + @Override + public Optional getProperty(ConstrainableExecutable executable) { + Contracts.assertNotNull( executable, "executable cannot be null" ); + + if ( !isGetter( executable ) ) { + return Optional.empty(); + } + + String methodName = executable.getName(); + + for ( String prefix : GETTER_PREFIXES ) { + if ( methodName.startsWith( prefix ) ) { + return Optional.of( StringHelper.decapitalize( methodName.substring( prefix.length() ) ) ); + } + } + + throw new AssertionError( "Method " + executable.getName() + " was considered a getter but we couldn't extract a property name." ); + } + + @Override + public Set getGetterMethodNameCandidates(String propertyName) { + Contracts.assertNotEmpty( propertyName, "Name of a property must not be empty" ); + + Set nameCandidates = CollectionHelper.newHashSet( GETTER_PREFIXES.length ); + for ( String prefix : GETTER_PREFIXES ) { + nameCandidates.add( prefix + Character.toUpperCase( propertyName.charAt( 0 ) ) + propertyName.substring( 1 ) ); + } + return nameCandidates; + } + /** * Checks whether the given executable is a valid JavaBean getter method, which * is the case if @@ -49,8 +80,7 @@ public class DefaultGetterPropertySelectionStrategy implements GetterPropertySel * @return {@code true}, if the given executable is a JavaBean getter method, * {@code false} otherwise. */ - @Override - public boolean isGetter(ConstrainableExecutable executable) { + private static boolean isGetter(ConstrainableExecutable executable) { if ( executable.getParameterTypes().length != 0 ) { return false; } @@ -72,28 +102,4 @@ else if ( methodName.startsWith( GETTER_PREFIX_HAS ) && executable.getReturnType return false; } - - @Override - public String getPropertyName(ConstrainableExecutable executable) { - Contracts.assertNotNull( executable, "executable cannot be null" ); - - String methodName = executable.getName(); - for ( String prefix : GETTER_PREFIXES ) { - if ( methodName.startsWith( prefix ) ) { - return StringHelper.decapitalize( methodName.substring( prefix.length() ) ); - } - } - throw LOG.getIllegalArgumentException( "Property name cannot be constructed for a given method " + executable.getName() ); - } - - @Override - public Set getGetterMethodNameCandidates(String propertyName) { - Contracts.assertNotEmpty( propertyName, "Name of a property must not be empty" ); - - Set nameCandidates = CollectionHelper.newHashSet( GETTER_PREFIXES.length ); - for ( String prefix : GETTER_PREFIXES ) { - nameCandidates.add( prefix + Character.toUpperCase( propertyName.charAt( 0 ) ) + propertyName.substring( 1 ) ); - } - return nameCandidates; - } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java index 572922225e..b9788ea685 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java @@ -12,7 +12,6 @@ import java.lang.reflect.Executable; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.lang.reflect.Type; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Optional; @@ -76,7 +75,7 @@ private Optional findGetter(Class declaringClass, String prop } else { return Optional.of( - new JavaBeanGetter( declaringClass, getter, getterPropertySelectionStrategy.getPropertyName( new JavaBeanConstrainableExecutable( getter ) ) ) + new JavaBeanGetter( declaringClass, getter, property ) ); } } @@ -115,8 +114,10 @@ public JavaBeanExecutable executable(Class declaringClass, Executable exec public JavaBeanMethod executable(Class declaringClass, Method method) { JavaBeanConstrainableExecutable executable = new JavaBeanConstrainableExecutable( method ); - if ( getterPropertySelectionStrategy.isGetter( executable ) ) { - return new JavaBeanGetter( declaringClass, method, getterPropertySelectionStrategy.getPropertyName( executable ) ); + + Optional correspondingProperty = getterPropertySelectionStrategy.getProperty( executable ); + if ( correspondingProperty.isPresent() ) { + return new JavaBeanGetter( declaringClass, method, correspondingProperty.get() ); } return new JavaBeanMethod( method ); @@ -151,7 +152,7 @@ public String getName() { } @Override - public Type[] getParameterTypes() { + public Class[] getParameterTypes() { return method.getParameterTypes(); } } diff --git a/engine/src/main/java/org/hibernate/validator/spi/properties/ConstrainableExecutable.java b/engine/src/main/java/org/hibernate/validator/spi/properties/ConstrainableExecutable.java index 888b1284f0..3c51e30156 100644 --- a/engine/src/main/java/org/hibernate/validator/spi/properties/ConstrainableExecutable.java +++ b/engine/src/main/java/org/hibernate/validator/spi/properties/ConstrainableExecutable.java @@ -6,15 +6,15 @@ */ package org.hibernate.validator.spi.properties; -import java.lang.reflect.Type; +import org.hibernate.validator.Incubating; /** - * A class that describes JavaBeans method. Is used for determining if a given - * JavaBeans method is a property or not. + * Descriptor for a method of a Java class. * * @author Marko Bekhta * @since 6.1.0 */ +@Incubating public interface ConstrainableExecutable { /** @@ -30,5 +30,5 @@ public interface ConstrainableExecutable { /** * @return the parameter types for the executable this object represents */ - Type[] getParameterTypes(); + Class[] getParameterTypes(); } diff --git a/engine/src/main/java/org/hibernate/validator/spi/properties/GetterPropertySelectionStrategy.java b/engine/src/main/java/org/hibernate/validator/spi/properties/GetterPropertySelectionStrategy.java index 5f2aef8d0a..0833f6ff64 100644 --- a/engine/src/main/java/org/hibernate/validator/spi/properties/GetterPropertySelectionStrategy.java +++ b/engine/src/main/java/org/hibernate/validator/spi/properties/GetterPropertySelectionStrategy.java @@ -6,26 +6,15 @@ */ package org.hibernate.validator.spi.properties; +import java.util.Optional; import java.util.Set; import org.hibernate.validator.Incubating; -import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; /** - * Used to define the strategy to detect the getter of a bean. The default - * implementation ({@link DefaultGetterPropertySelectionStrategy}) uses the JavaBeans - * naming convention: + * Used to define the strategy to detect the getters of a bean. *

- * A JavaBean's method is considered to be a valid getter method (property), if - * one of the next rules can be applied to it: - *

- *
    - *
  • its name starts with "get" and it has a return type but no parameters
  • - *
  • its name starts with "is", it has no parameters and is returning {@code boolean}
  • - *
  • its name starts with "has", it has no parameters and is returning {@code boolean}.
  • - *
- *

- * The last rule is specific to Hibernate Validator and is not mandated by the JavaBeans specification. + * A getter is considered as being a property of the bean and thus validated when validating the bean. * * @author Marko Bekhta * @since 6.1.0 @@ -34,25 +23,16 @@ public interface GetterPropertySelectionStrategy { /** - * Determines if a given {@link ConstrainableExecutable} is a getter method (property). - * - * @param executable a {@link ConstrainableExecutable} - * - * @return {@code true} if the given executable should be considered a getter, {@code false} otherwise - */ - boolean isGetter(ConstrainableExecutable executable); - - /** - * Performs a transformation of a getter method name to its corresponding property name. - * For example by removing the prefixes like {@code get}/{@code is} etc. + * Returns the property corresponding to the getter if the method is considered a getter. * * @param executable a {@link ConstrainableExecutable} * - * @return the property name corresponding to the given executable + * @return an optional containing the property corresponding to the given executable if it is considered a getter, + * or an empty optional otherwise * * @throws IllegalArgumentException if a property name cannot be constructed */ - String getPropertyName(ConstrainableExecutable executable); + Optional getProperty(ConstrainableExecutable executable); /** * Gives a set of possible method names based on a property name. Usually, it means diff --git a/engine/src/test/java/org/hibernate/validator/test/properties/GetterPropertySelectionStrategyTest.java b/engine/src/test/java/org/hibernate/validator/test/properties/GetterPropertySelectionStrategyTest.java index 4bff1739d5..816b82ee7b 100644 --- a/engine/src/test/java/org/hibernate/validator/test/properties/GetterPropertySelectionStrategyTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/properties/GetterPropertySelectionStrategyTest.java @@ -10,10 +10,10 @@ import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; import java.lang.reflect.Method; -import java.lang.reflect.Type; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -35,7 +35,6 @@ import org.hibernate.validator.testutil.ConstraintViolationAssert; import org.hibernate.validator.testutil.TestForIssue; import org.hibernate.validator.testutils.ValidatorUtil; - import org.testng.annotations.Test; /** @@ -45,15 +44,15 @@ public class GetterPropertySelectionStrategyTest { @Test public void testGetterPropertySelectionStrategy() throws Exception { - GetterPropertySelectionStrategy filter = new FooGetterPropertySelectionStrategy(); + GetterPropertySelectionStrategy strategy = new FooGetterPropertySelectionStrategy(); ConstrainableExecutableImpl fooMethod = new ConstrainableExecutableImpl( Foo.class.getDeclaredMethod( "fooMethod" ) ); ConstrainableExecutableImpl getMethod = new ConstrainableExecutableImpl( Foo.class.getDeclaredMethod( "getMethod" ) ); - assertThat( filter.isGetter( fooMethod ) ).isTrue(); - assertThat( filter.isGetter( getMethod ) ).isFalse(); + assertThat( strategy.getProperty( fooMethod ) ).isPresent(); + assertThat( strategy.getProperty( getMethod ) ).isNotPresent(); - assertThat( filter.getPropertyName( fooMethod ) ).isEqualTo( "method" ); + assertThat( strategy.getProperty( fooMethod ).get() ).isEqualTo( "method" ); } @Test @@ -221,17 +220,15 @@ public int getTest() { public static class NoPrefixGetterPropertySelectionStrategy implements GetterPropertySelectionStrategy { @Override - public boolean isGetter(ConstrainableExecutable executable) { - String name = executable.getName(); - return executable.getReturnType() != void.class - && executable.getParameterTypes().length == 0 - && !name.startsWith( "is" ) - && !name.startsWith( "get" ); - } + public Optional getProperty(ConstrainableExecutable executable) { + if ( executable.getReturnType() == void.class + || executable.getParameterTypes().length > 0 + || executable.getName().startsWith( "is" ) + || executable.getName().startsWith( "get" ) ) { + return Optional.empty(); + } - @Override - public String getPropertyName(ConstrainableExecutable method) { - return method.getName(); + return Optional.of( executable.getName() ); } @Override @@ -243,16 +240,15 @@ public Set getGetterMethodNameCandidates(String propertyName) { public static class FooGetterPropertySelectionStrategy implements GetterPropertySelectionStrategy { @Override - public boolean isGetter(ConstrainableExecutable executable) { - return executable.getParameterTypes().length == 0 - && executable.getName().startsWith( "foo" ); - } + public Optional getProperty(ConstrainableExecutable executable) { + if ( executable.getParameterTypes().length > 0 + || !executable.getName().startsWith( "foo" ) ) { + return Optional.empty(); + } - @Override - public String getPropertyName(ConstrainableExecutable method) { - char[] chars = method.getName().substring( 3 ).toCharArray(); + char[] chars = executable.getName().substring( 3 ).toCharArray(); chars[0] = Character.toLowerCase( chars[0] ); - return new String( chars ); + return Optional.of( new String( chars ) ); } @Override @@ -280,7 +276,7 @@ public String getName() { } @Override - public Type[] getParameterTypes() { + public Class[] getParameterTypes() { return method.getParameterTypes(); } } From 6a240f3a51a60f13054eb8ff68208db19657f2a0 Mon Sep 17 00:00:00 2001 From: jpoth Date: Tue, 26 Jun 2018 14:28:45 +0200 Subject: [PATCH 103/393] HV-1610 make OSGI tests work on JDK 10 --- .../osgi/integrationtest/JavaVersionUtil.java | 34 +++++++++++++++ .../KarafFeaturesAreInstallableTest.java | 2 + .../integrationtest/OsgiIntegrationTest.java | 2 + .../osgi/integrationtest/PaxExamOptions.java | 43 +++++++++++++++++++ pom.xml | 14 ++---- 5 files changed, 84 insertions(+), 11 deletions(-) create mode 100644 osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/JavaVersionUtil.java create mode 100644 osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/PaxExamOptions.java diff --git a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/JavaVersionUtil.java b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/JavaVersionUtil.java new file mode 100644 index 0000000000..0a8cc90c17 --- /dev/null +++ b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/JavaVersionUtil.java @@ -0,0 +1,34 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.osgi.integrationtest; + +import java.util.Locale; + +final class JavaVersionUtil { + + private JavaVersionUtil() { + } + + static int getMajorVersion() { + String javaSpecVersion = System.getProperty( "java.specification.version" ); + try { + if ( javaSpecVersion.contains( "." ) ) { //before jdk 9 + return Integer.parseInt( javaSpecVersion.split( "\\." )[1] ); + } + else { + return Integer.parseInt( javaSpecVersion ); + } + } + catch (NumberFormatException e) { + throw getUnableToParseVersionException( javaSpecVersion ); + } + } + + private static IllegalArgumentException getUnableToParseVersionException(String version) { + return new IllegalArgumentException( String.format( Locale.ROOT, "We are unable to parse Java version '%1$s'.", version ) ); + } +} diff --git a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/KarafFeaturesAreInstallableTest.java b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/KarafFeaturesAreInstallableTest.java index 12b5c2e266..16bec3fcd9 100644 --- a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/KarafFeaturesAreInstallableTest.java +++ b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/KarafFeaturesAreInstallableTest.java @@ -6,6 +6,7 @@ */ package org.hibernate.validator.osgi.integrationtest; +import static org.hibernate.validator.osgi.integrationtest.PaxExamOptions.JAVA_9; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.ops4j.pax.exam.CoreOptions.maven; @@ -68,6 +69,7 @@ public Option[] config() { return options( when( DEBUG ).useOptions( debugConfiguration( "5005", true ) ), + when( JavaVersionUtil.getMajorVersion() >= 9 ).useOptions( JAVA_9.option() ), karafDistributionConfiguration() .frameworkUrl( maven() diff --git a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java index 135074a717..db3ed64543 100644 --- a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java +++ b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java @@ -6,6 +6,7 @@ */ package org.hibernate.validator.osgi.integrationtest; +import static org.hibernate.validator.osgi.integrationtest.PaxExamOptions.JAVA_9; import static org.junit.Assert.assertEquals; import static org.ops4j.pax.exam.CoreOptions.maven; import static org.ops4j.pax.exam.CoreOptions.options; @@ -91,6 +92,7 @@ public Option[] config() { return options( when( DEBUG ).useOptions( debugConfiguration( "5005", true ) ), + when( JavaVersionUtil.getMajorVersion() >= 9 ).useOptions( JAVA_9.option() ), karafDistributionConfiguration() .frameworkUrl( maven() diff --git a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/PaxExamOptions.java b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/PaxExamOptions.java new file mode 100644 index 0000000000..252ef5f797 --- /dev/null +++ b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/PaxExamOptions.java @@ -0,0 +1,43 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.osgi.integrationtest; + +import org.ops4j.pax.exam.CoreOptions; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.options.DefaultCompositeOption; + +public enum PaxExamOptions { + JAVA_9( + CoreOptions.vmOptions( + "--add-opens", + "java.base/java.security=ALL-UNNAMED", + "--add-opens", + "java.base/java.net=ALL-UNNAMED", + "--add-opens", + "java.base/java.lang=ALL-UNNAMED", + "--add-opens", + "java.base/java.util=ALL-UNNAMED", + "--add-exports=java.base/sun.net.www.protocol.http=ALL-UNNAMED", + "--add-exports=java.base/sun.net.www.protocol.https=ALL-UNNAMED", + "--add-exports=java.xml.bind/com.sun.xml.internal.bind.v2.runtime=ALL-UNNAMED", + "--add-exports=jdk.xml.dom/org.w3c.dom.html=ALL-UNNAMED", + "--add-exports=jdk.naming.rmi/com.sun.jndi.url.rmi=ALL-UNNAMED", + "--add-exports=java.xml.ws/com.sun.xml.internal.messaging.saaj.soap.impl=ALL-UNNAMED", + "--add-modules", + "java.xml.ws.annotation,java.corba,java.transaction,java.xml.bind,java.xml.ws,jdk.xml.bind" ) + ); + + private final Option[] options; + + PaxExamOptions(Option... options) { + this.options = options; + } + + public Option option() { + return new DefaultCompositeOption( options ); + } +} diff --git a/pom.xml b/pom.xml index 7b174e5fc2..3a72f3dcc8 100644 --- a/pom.xml +++ b/pom.xml @@ -171,8 +171,8 @@ 1.0.0.Final - 4.1.2 - 4.11.0 + 4.2.0 + 4.12.0 2.5.2 6.0.0 5.181 @@ -1162,15 +1162,6 @@ - - jdk9- - - (,10) - - - osgi - - jdk9+ @@ -1229,6 +1220,7 @@ integration + osgi From fb6450dfec46d19eb1411362bff9cb2b1ab240b4 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 6 Jul 2018 18:29:14 +0200 Subject: [PATCH 104/393] HV-1610 Minor improvements --- .../validator/osgi/integrationtest/JavaVersionUtil.java | 6 +----- .../integrationtest/KarafFeaturesAreInstallableTest.java | 2 +- .../osgi/integrationtest/OsgiIntegrationTest.java | 2 +- .../validator/osgi/integrationtest/PaxExamOptions.java | 8 ++++---- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/JavaVersionUtil.java b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/JavaVersionUtil.java index 0a8cc90c17..a38a53ac71 100644 --- a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/JavaVersionUtil.java +++ b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/JavaVersionUtil.java @@ -24,11 +24,7 @@ static int getMajorVersion() { } } catch (NumberFormatException e) { - throw getUnableToParseVersionException( javaSpecVersion ); + throw new IllegalArgumentException( String.format( Locale.ROOT, "We are unable to parse Java version '%1$s'.", javaSpecVersion ) ); } } - - private static IllegalArgumentException getUnableToParseVersionException(String version) { - return new IllegalArgumentException( String.format( Locale.ROOT, "We are unable to parse Java version '%1$s'.", version ) ); - } } diff --git a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/KarafFeaturesAreInstallableTest.java b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/KarafFeaturesAreInstallableTest.java index 16bec3fcd9..ff7b12dd2e 100644 --- a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/KarafFeaturesAreInstallableTest.java +++ b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/KarafFeaturesAreInstallableTest.java @@ -69,7 +69,7 @@ public Option[] config() { return options( when( DEBUG ).useOptions( debugConfiguration( "5005", true ) ), - when( JavaVersionUtil.getMajorVersion() >= 9 ).useOptions( JAVA_9.option() ), + when( JavaVersionUtil.getMajorVersion() >= 9 ).useOptions( JAVA_9.options() ), karafDistributionConfiguration() .frameworkUrl( maven() diff --git a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java index db3ed64543..e156542893 100644 --- a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java +++ b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java @@ -92,7 +92,7 @@ public Option[] config() { return options( when( DEBUG ).useOptions( debugConfiguration( "5005", true ) ), - when( JavaVersionUtil.getMajorVersion() >= 9 ).useOptions( JAVA_9.option() ), + when( JavaVersionUtil.getMajorVersion() >= 9 ).useOptions( JAVA_9.options() ), karafDistributionConfiguration() .frameworkUrl( maven() diff --git a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/PaxExamOptions.java b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/PaxExamOptions.java index 252ef5f797..cf8166b46d 100644 --- a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/PaxExamOptions.java +++ b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/PaxExamOptions.java @@ -31,13 +31,13 @@ public enum PaxExamOptions { "java.xml.ws.annotation,java.corba,java.transaction,java.xml.bind,java.xml.ws,jdk.xml.bind" ) ); - private final Option[] options; + private final Option options; PaxExamOptions(Option... options) { - this.options = options; + this.options = new DefaultCompositeOption( options ); } - public Option option() { - return new DefaultCompositeOption( options ); + public Option options() { + return options; } } From d6165adbb7a1d0faa742571edb191a6c63fec17d Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 13 Jul 2018 15:44:29 +0200 Subject: [PATCH 105/393] HV-1628 Remove more calls deprecated by JDK 10 --- .../constraintvalidators/bv/size/SizeValidatorTest.java | 2 +- .../internal/engine/ValidatorFactoryNoELBootstrapTest.java | 4 +++- .../validator/test/internal/engine/path/PathImplTest.java | 4 ++-- .../java/com/example/ExampleConstraintValidatorFactory.java | 6 ++++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/size/SizeValidatorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/size/SizeValidatorTest.java index 09e3da8900..5a841e602b 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/size/SizeValidatorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/size/SizeValidatorTest.java @@ -177,7 +177,7 @@ private ConstraintValidator getValidatorMin1Max2(Class validator descriptorBuilder.setMessage( "{validator.max}" ); Size m = descriptorBuilder.build().getAnnotation(); @SuppressWarnings("unchecked") - ConstraintValidator validator = (ConstraintValidator) validatorClass.newInstance(); + ConstraintValidator validator = (ConstraintValidator) validatorClass.getConstructor().newInstance(); validator.initialize( m ); return validator; } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/ValidatorFactoryNoELBootstrapTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/ValidatorFactoryNoELBootstrapTest.java index 2efac1fdcf..869915b1b9 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/ValidatorFactoryNoELBootstrapTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/ValidatorFactoryNoELBootstrapTest.java @@ -27,6 +27,7 @@ import javax.validation.Validator; import javax.validation.constraints.Min; +import org.hibernate.validator.internal.IgnoreForbiddenApisErrors; import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader; import org.hibernate.validator.internal.util.privilegedactions.SetContextClassLoader; import org.hibernate.validator.messageinterpolation.ParameterMessageInterpolator; @@ -143,6 +144,7 @@ public ELIgnoringClassLoader( String packageMissing ) { } @Override + @IgnoreForbiddenApisErrors(reason = "getPackage() is deprecated but getDefinedPackage() is only available from JDK 9.") public Class loadClass(String className) throws ClassNotFoundException { // This is what we in the end want to achieve. Throw ClassNotFoundException for javax.el classes if ( className.startsWith( packageMissing ) ) { @@ -230,7 +232,7 @@ private void runWithoutElLibs(Class delegateType, String packageMissing) thro ClassLoader classLoader = new ELIgnoringClassLoader( packageMissing ); run( SetContextClassLoader.action( classLoader ) ); - Object test = classLoader.loadClass( delegateType.getName() ).newInstance(); + Object test = classLoader.loadClass( delegateType.getName() ).getConstructor().newInstance(); test.getClass().getMethod( "run" ).invoke( test ); } finally { diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java index 257eef802a..3f982953bc 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java @@ -67,7 +67,7 @@ public void testParsing() { elem = propIter.next(); assertEquals( elem.getName(), "deliveryAddress" ); assertTrue( elem.isInIterable() ); - assertEquals( elem.getIndex(), new Integer( 3 ) ); + assertEquals( elem.getIndex(), Integer.valueOf( 3 ) ); assertTrue( propIter.hasNext() ); elem = propIter.next(); @@ -78,7 +78,7 @@ public void testParsing() { elem = propIter.next(); assertEquals( elem.getName(), null ); assertTrue( elem.isInIterable() ); - assertEquals( elem.getIndex(), new Integer( 1 ) ); + assertEquals( elem.getIndex(), Integer.valueOf( 1 ) ); assertFalse( propIter.hasNext() ); diff --git a/osgi/integrationtest/src/test/java/com/example/ExampleConstraintValidatorFactory.java b/osgi/integrationtest/src/test/java/com/example/ExampleConstraintValidatorFactory.java index 3b6c81ee5a..ed160f1eec 100644 --- a/osgi/integrationtest/src/test/java/com/example/ExampleConstraintValidatorFactory.java +++ b/osgi/integrationtest/src/test/java/com/example/ExampleConstraintValidatorFactory.java @@ -6,6 +6,7 @@ */ package com.example; +import java.lang.reflect.InvocationTargetException; import java.util.concurrent.atomic.AtomicInteger; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorFactory; @@ -22,9 +23,10 @@ public class ExampleConstraintValidatorFactory implements ConstraintValidatorFac @Override public > T getInstance(Class key) { try { - return key.newInstance(); + return key.getConstructor().newInstance(); } - catch (InstantiationException | IllegalAccessException e) { + catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException + | SecurityException e) { throw new RuntimeException( e ); } finally { From 6d3dd242c22cb6a20bf82ebb43647bb967c465ad Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 17 Jul 2018 15:54:27 +0200 Subject: [PATCH 106/393] HV-1640 Add --add-modules=java.se for WildFly tools This is necessary for JDK 11 build 22 due to https://issues.jboss.org/browse/MODULES-372. Hopefully, we will be able to remove this option later. --- pom.xml | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3a72f3dcc8..055c3c1925 100644 --- a/pom.xml +++ b/pom.xml @@ -272,7 +272,8 @@ ${surefire.jvm.args.additional} ${surefire.jvm.args.add-opens} ${surefire.jvm.args.illegal-access} - ${arquillian.wildfly.jvm.args.add-opens} + + ${arquillian.wildfly.jvm.args.add-opens} ${arquillian.wildfly.jvm.args.add-modules} ${maven.compiler.argument.source} @@ -1228,6 +1229,11 @@ [11,) + + + --add-modules=java.se + + @@ -1250,6 +1256,31 @@ + + + + org.wildfly.plugins + wildfly-maven-plugin + + + --add-opens=java.base/java.lang=ALL-UNNAMED + --add-opens=java.base/java.security=ALL-UNNAMED + --add-opens=java.base/java.io=ALL-UNNAMED + --add-modules=java.se + + + + + org.jboss.as + patch-gen-maven-plugin + + + --add-modules=java.se + + + + + From 45e7fdf275989e5c022d4a6bd3a8ad6a8fb88dfe Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 17 Jul 2018 15:57:45 +0200 Subject: [PATCH 107/393] HV-1641 Use OpenJFX snapshots when building with JDK 11 We used to download snapshots from the website but they are now published on a Maven repository. --- engine/pom.xml | 8 +++----- pom.xml | 34 +++++++--------------------------- 2 files changed, 10 insertions(+), 32 deletions(-) diff --git a/engine/pom.xml b/engine/pom.xml index 01a82c5d41..edc12d861d 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -289,11 +289,9 @@ - net.java - javafx-core - 11-ea+13 - system - ${maven.multiModuleProjectDirectory}/target/javafx/javafx-sdk-11/lib/javafx.base.jar + org.openjfx + javafx.base + 11.0.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index 055c3c1925..7c32639b7e 100644 --- a/pom.xml +++ b/pom.xml @@ -207,7 +207,6 @@ 3.0.2 1.4.0 2.8.2 - 1.4.0 3.0.0-M1 2.5 1.6 @@ -961,11 +960,6 @@ sigtest-maven-plugin ${version.sigtest.plugin} - - com.googlecode.maven-download-plugin - download-maven-plugin - ${version.download.plugin} - org.eclipse.m2e @@ -1235,27 +1229,6 @@ - - - com.googlecode.maven-download-plugin - download-maven-plugin - false - - - install-javafx - validate - - wget - - - https://download.java.net/java/early_access/openjfx11/13/binaries/openjfx-11-ea+13_linux-x64_bin-sdk.zip - true - ${maven.multiModuleProjectDirectory}/target/javafx - - - - - @@ -1282,6 +1255,13 @@ + + + sonatype-oss-snapshots + Sonatype OSS Snapshots + https://oss.sonatype.org/content/repositories/snapshots/ + + jqassistant From 5a682384beb77157728a06eb490284e673021bb0 Mon Sep 17 00:00:00 2001 From: de-simakov Date: Thu, 26 Jul 2018 10:45:19 +0700 Subject: [PATCH 108/393] HV-1643 Fix Russian translation for @Null constraint --- .../org/hibernate/validator/ValidationMessages_ru.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ru.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ru.properties index 56a4877b75..6c89c64ab8 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ru.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ru.properties @@ -9,7 +9,7 @@ javax.validation.constraints.Min.message = \u0434\u043E\u043B\u0436\u043 javax.validation.constraints.NotBlank.message = \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0443\u0441\u0442\u043E javax.validation.constraints.NotEmpty.message = \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0443\u0441\u0442\u043E javax.validation.constraints.NotNull.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0437\u0430\u0434\u0430\u043D\u043E -javax.validation.constraints.Null.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435\u0437\u0430\u0434\u0430\u043D\u043E +javax.validation.constraints.Null.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E javax.validation.constraints.Past.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0432 \u043F\u0440\u043E\u0448\u043B\u043E\u043C javax.validation.constraints.Pattern.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043E\u0432\u0430\u0442\u044C \u0448\u0430\u0431\u043B\u043E\u043D\u0443 "{regexp}" javax.validation.constraints.Size.message = \u0440\u0430\u0437\u043C\u0435\u0440 \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043C\u0435\u0436\u0434\u0443 {min} \u0438 {max} From fc9a95a44199d63fa9e1d742d1003b5b7a682ff3 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 9 Aug 2018 17:48:54 +0200 Subject: [PATCH 109/393] HV-1645 Revert "HV-1609 Change how we filter which beans to process in CDI extension" This reverts commit 9f40990aa7054e0e420a41b4d7620b4a609914d2. --- .../validator/cdi/ValidationExtension.java | 26 +- .../cdi/internal/ValidateableBeanFilter.java | 161 ---------- .../internal/ValidateableBeanFilterTest.java | 276 ------------------ 3 files changed, 11 insertions(+), 452 deletions(-) delete mode 100644 cdi/src/main/java/org/hibernate/validator/cdi/internal/ValidateableBeanFilter.java delete mode 100644 cdi/src/test/java/org/hibernate/validator/test/cdi/internal/ValidateableBeanFilterTest.java diff --git a/cdi/src/main/java/org/hibernate/validator/cdi/ValidationExtension.java b/cdi/src/main/java/org/hibernate/validator/cdi/ValidationExtension.java index b7a2b9bf7c..4be3dab84e 100644 --- a/cdi/src/main/java/org/hibernate/validator/cdi/ValidationExtension.java +++ b/cdi/src/main/java/org/hibernate/validator/cdi/ValidationExtension.java @@ -19,7 +19,6 @@ import java.util.List; import java.util.Optional; import java.util.Set; -import java.util.function.Predicate; import javax.enterprise.event.Observes; import javax.enterprise.inject.Default; @@ -34,9 +33,12 @@ import javax.enterprise.inject.spi.Extension; import javax.enterprise.inject.spi.ProcessAnnotatedType; import javax.enterprise.inject.spi.ProcessBean; +import javax.enterprise.inject.spi.WithAnnotations; import javax.enterprise.util.AnnotationLiteral; import javax.validation.BootstrapConfiguration; import javax.validation.Configuration; +import javax.validation.Constraint; +import javax.validation.Valid; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; @@ -46,7 +48,6 @@ import javax.validation.metadata.PropertyDescriptor; import org.hibernate.validator.cdi.internal.InheritedMethodsHelper; -import org.hibernate.validator.cdi.internal.ValidateableBeanFilter; import org.hibernate.validator.cdi.internal.ValidationProviderHelper; import org.hibernate.validator.cdi.internal.ValidatorBean; import org.hibernate.validator.cdi.internal.ValidatorFactoryBean; @@ -83,7 +84,6 @@ public class ValidationExtension implements Extension { EnumSet.of( ExecutableType.CONSTRUCTORS, ExecutableType.NON_GETTER_METHODS, ExecutableType.GETTER_METHODS ); private static final EnumSet DEFAULT_EXECUTABLE_TYPES = EnumSet.of( ExecutableType.CONSTRUCTORS, ExecutableType.NON_GETTER_METHODS ); - private static final Predicate> VALIDATEABLE_BEAN_FILTER = new ValidateableBeanFilter(); @SuppressWarnings("serial") private final Annotation defaultQualifier = new AnnotationLiteral() { @@ -222,23 +222,19 @@ else if ( bean.getTypes().contains( Validator.class ) || bean instanceof Validat * @param processAnnotatedTypeEvent event fired for each annotated type * @param the annotated type */ - public void processAnnotatedType(@Observes ProcessAnnotatedType processAnnotatedTypeEvent) { - // NOTE: we cannot use @WithAnnotations for filtering purposes here. - // This annotation does not consider implemented interfaces and super classes for annotations. - // Hence beans with no Hibernate Validator/Bean Validation annotations (@Valid, @Constraint, - // @ValidateOnExecution) on them, that implement interfaces that have such annotations - // will not be pushed to this method if @WithAnnotations is used. - // To prevent filling memory with useless metadata and redundant work in HV we have a custom - // VALIDATEABLE_BEAN_FILTER that checks for annotation presence in the way that we need. + public void processAnnotatedType(@Observes @WithAnnotations({ + Constraint.class, + Valid.class, + ValidateOnExecution.class + }) ProcessAnnotatedType processAnnotatedTypeEvent) { Contracts.assertNotNull( processAnnotatedTypeEvent, "The ProcessAnnotatedType event cannot be null" ); - AnnotatedType type = processAnnotatedTypeEvent.getAnnotatedType(); - - // validation globally disabled or annotated type has none of needed annotations: - if ( !isExecutableValidationEnabled || !VALIDATEABLE_BEAN_FILTER.test( type.getJavaClass() ) ) { + // validation globally disabled + if ( !isExecutableValidationEnabled ) { return; } + AnnotatedType type = processAnnotatedTypeEvent.getAnnotatedType(); Set> constrainedCallables = determineConstrainedCallables( type ); if ( !constrainedCallables.isEmpty() ) { diff --git a/cdi/src/main/java/org/hibernate/validator/cdi/internal/ValidateableBeanFilter.java b/cdi/src/main/java/org/hibernate/validator/cdi/internal/ValidateableBeanFilter.java deleted file mode 100644 index 4c9f7a5547..0000000000 --- a/cdi/src/main/java/org/hibernate/validator/cdi/internal/ValidateableBeanFilter.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.cdi.internal; - -import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedParameterizedType; -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Constructor; -import java.lang.reflect.Executable; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.function.Predicate; - -import javax.enterprise.inject.spi.WithAnnotations; -import javax.validation.Constraint; -import javax.validation.Valid; -import javax.validation.executable.ValidateOnExecution; - -import org.hibernate.validator.internal.util.CollectionHelper; -import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper; - -/** - * A filter that checks if the passed class has any of these annotations: - *

    - *
  • {@link Valid}
  • - *
  • {@link Constraint}
  • - *
  • {@link ValidateOnExecution}
  • - *
- *

- * on a type level, or on any member, or any parameter of any member. Super classes and all implemented interfaces are - * considered while looking for these annotations. - *

- * The annotation may be applied as a meta-annotation on any annotation considered. - *

- * This filter is required as {@link WithAnnotations} does not look for annotations into the class hierarchy. - * - * @author Marko Bekhta - */ -public class ValidateableBeanFilter implements Predicate> { - - private static final Set> MATCHING_ANNOTATIONS = Collections.unmodifiableSet( - CollectionHelper.asSet( Valid.class, Constraint.class, ValidateOnExecution.class ) - ); - - @Override - public boolean test(Class type) { - for ( Class clazz : ClassHierarchyHelper.getHierarchy( type ) ) { - if ( hasMatchingAnnotation( clazz ) ) { - return true; - } - } - - return false; - } - - private boolean hasMatchingAnnotation(Class clazz) { - Set processedAnnotations = new HashSet<>(); - // 1. Is present on a type level: - if ( containsMatchingAnnotation( clazz.getDeclaredAnnotations(), processedAnnotations ) ) { - return true; - } - - // 2. Or on a field level - for ( Field field : clazz.getDeclaredFields() ) { - if ( hasMatchingAnnotation( field.getAnnotatedType(), processedAnnotations ) ) { - return true; - } - if ( containsMatchingAnnotation( field.getDeclaredAnnotations(), processedAnnotations ) ) { - return true; - } - } - // 3. Or on any executable - // 3.1 Constructors - for ( Constructor constructor : clazz.getDeclaredConstructors() ) { - if ( hasMatchingAnnotation( constructor, processedAnnotations ) ) { - return true; - } - } - - // 3.2 Methods - for ( Method method : clazz.getDeclaredMethods() ) { - if ( hasMatchingAnnotation( method, processedAnnotations ) ) { - return true; - } - } - return false; - } - - private boolean containsMatchingAnnotation(Annotation[] annotations, Set processedAnnotations) { - for ( Annotation annotation : annotations ) { - if ( isMatchingAnnotation( annotation, processedAnnotations ) ) { - return true; - } - } - return false; - } - - private boolean hasMatchingAnnotation(AnnotatedType annotatedType, Set processedAnnotations) { - if ( containsMatchingAnnotation( annotatedType.getDeclaredAnnotations(), processedAnnotations ) ) { - return true; - } - if ( annotatedType instanceof AnnotatedParameterizedType ) { - for ( AnnotatedType type : ( (AnnotatedParameterizedType) annotatedType ).getAnnotatedActualTypeArguments() ) { - if ( hasMatchingAnnotation( type, processedAnnotations ) ) { - return true; - } - } - } - return false; - } - - private boolean hasMatchingAnnotation(Executable executable, Set processedAnnotations) { - // Check the executable itself first - if ( containsMatchingAnnotation( executable.getDeclaredAnnotations(), processedAnnotations ) ) { - return true; - } - // Check its return value - if ( hasMatchingAnnotation( executable.getAnnotatedReturnType(), processedAnnotations ) ) { - return true; - } - // Then check its parameters - for ( AnnotatedType annotatedParameterType : executable.getAnnotatedParameterTypes() ) { - if ( hasMatchingAnnotation( annotatedParameterType, processedAnnotations ) ) { - return true; - } - } - // NOTE: this check looks to be redundant BUT without it, test on BeanWithCustomConstraintOnParameter - // will fail as executable.getAnnotatedParameterTypes() on BeanWithCustomConstraintOnParameter#doDefault() - // will not contain matching annotations - for ( Annotation[] annotations : executable.getParameterAnnotations() ) { - if ( containsMatchingAnnotation( annotations, processedAnnotations ) ) { - return true; - } - } - return false; - } - - private boolean isMatchingAnnotation(Annotation annotationToCheck, Set processedAnnotations) { - // Need to have this to prevent infinite loops, for example on annotations like @Target - if ( !processedAnnotations.add( annotationToCheck ) ) { - return false; - } - Class annotationType = annotationToCheck.annotationType(); - if ( MATCHING_ANNOTATIONS.contains( annotationType ) ) { - return true; - } - for ( Annotation annotation : annotationType.getDeclaredAnnotations() ) { - if ( isMatchingAnnotation( annotation, processedAnnotations ) ) { - return true; - } - } - return false; - } -} diff --git a/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/ValidateableBeanFilterTest.java b/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/ValidateableBeanFilterTest.java deleted file mode 100644 index 8d72aba85c..0000000000 --- a/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/ValidateableBeanFilterTest.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.test.cdi.internal; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; - -import java.io.Serializable; -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Predicate; - -import javax.validation.Constraint; -import javax.validation.Payload; -import javax.validation.Valid; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Pattern; -import javax.validation.constraints.Size; -import javax.validation.executable.ExecutableType; -import javax.validation.executable.ValidateOnExecution; - -import org.hibernate.validator.cdi.internal.ValidateableBeanFilter; - -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -/** - * @author Marko Bekhta - */ -public class ValidateableBeanFilterTest { - - private Predicate> predicate; - - @BeforeMethod - public void setUp() { - this.predicate = new ValidateableBeanFilter(); - } - - @Test - public void test() { - // Cases where no required annotations are present: - // 1. Object doesn't have any required annotations - assertFalse( predicate.test( Object.class ) ); - // 2. Simple class with no annotations - assertFalse( predicate.test( SimpleClassWithNoAnnotations.class ) ); - // 3. Class that implements a lot of interfaces but there's no required annotations on it - assertFalse( predicate.test( ImplementsALotOfInterfacesButNoneAreAnnotated.class ) ); - - // Cases where annotation could be found somewhere: - // 1. A constraint annotation on an interface - assertTrue( predicate.test( InterfaceWithConstraintAnnotation.class ) ); - // 2. Class that doesn't have any own annotations but implements an interface with one - assertTrue( predicate.test( NoAnnotationsOfItsOwnButImplementsAnnotatedInterface.class ) ); - // 3. Class with deeper hierarchy and its own annotation - assertTrue( predicate.test( ExtendsCleanClassButHasOwnAnnotation.class ) ); - - // 4. Interface with @Valid and class that implements it - assertTrue( predicate.test( ImplementsInterfaceWithValidAnnotation.class ) ); - assertTrue( predicate.test( InterfaceWithValidAnnotation.class ) ); - - // 5. Interface with constraint and class that implements it - assertTrue( predicate.test( InterfaceWithConstraintAnnotation.class ) ); - assertTrue( predicate.test( ImplementsInterfaceWithConstraintAnnotation.class ) ); - - // 6. Interface with @ValidateOnExecution and class that implements it - assertTrue( predicate.test( ImplementsInterfaceWithValidateOnExecutionAnnotation.class ) ); - assertTrue( predicate.test( InterfaceWithValidateOnExecutionAnnotation.class ) ); - - // 7. Class with annotated field - assertTrue( predicate.test( AnnotatedField.class ) ); - - // 8. Class with annotated constructor - assertTrue( predicate.test( AnnotatedConstructor.class ) ); - - // 9. Annotated type arguments - assertTrue( predicate.test( TypeArgumentField.class ) ); - assertTrue( predicate.test( TypeArgumentReturnValue.class ) ); - assertTrue( predicate.test( TypeArgumentMethodParameter.class ) ); - assertTrue( predicate.test( TypeArgumentConstructorParameter.class ) ); - assertTrue( predicate.test( NestedTypeArgumentField.class ) ); - assertTrue( predicate.test( DeepNestedAnnotatedMethodParameter.class ) ); - - // 10. Custom user constraint: - assertTrue( predicate.test( BeanWithCustomConstraintOnParameter.class ) ); - assertTrue( predicate.test( BeanWithCustomConstraintOnField.class ) ); - assertTrue( predicate.test( BeanWithCustomConstraintOnReturnValue.class ) ); - } - - @SuppressWarnings("unused") - private static class AnnotatedMethodParameter { - void doSomething(@NotNull String string) { - } - } - - private static class DeepNestedAnnotatedMethodParameter { - @SuppressWarnings("unused") - void doSomething(List>>>> strings) { - } - } - - private static class TypeArgumentField { - @SuppressWarnings("unused") - private List<@NotNull String> strings; - } - - private static class NestedTypeArgumentField { - @SuppressWarnings("unused") - private List> strings; - } - - private static class TypeArgumentReturnValue { - @SuppressWarnings("unused") - List<@NotNull String> strings() { - return null; - } - } - - private static class TypeArgumentMethodParameter { - @SuppressWarnings("unused") - void strings(List<@NotNull String> strings) { - } - } - - private static class TypeArgumentConstructorParameter { - @SuppressWarnings("unused") - TypeArgumentConstructorParameter(List<@NotNull String> strings) { - } - } - - private static class AnnotatedConstructor { - @Valid - public AnnotatedConstructor() { - } - } - - private static class AnnotatedField { - @Min(10) - private int num; - } - - private static class SimpleClassWithNoAnnotations { - - @SuppressWarnings("unused") - public void doNothing() { - } - } - - private static class NoAnnotationsOfItsOwnButImplementsAnnotatedInterface extends SimpleClassWithNoAnnotations implements InterfaceWithConstraintAnnotation { - - @Override - public int bar() { - return 0; - } - - @SuppressWarnings("unused") - public void doSomething(int foo) { - } - } - - interface InterfaceWithConstraintAnnotation { - - @Min(10) - int bar(); - } - - private static class ImplementsInterfaceWithConstraintAnnotation implements InterfaceWithConstraintAnnotation { - - @Override - public int bar() { - return 0; - } - } - - interface InterfaceWithValidAnnotation { - - @Valid - SimpleClassWithNoAnnotations bar(); - } - - private static class ImplementsInterfaceWithValidAnnotation implements InterfaceWithValidAnnotation { - - @Override - public SimpleClassWithNoAnnotations bar() { - return null; - } - } - - @ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS) - interface InterfaceWithValidateOnExecutionAnnotation { - - int bar(); - } - - private static class ImplementsInterfaceWithValidateOnExecutionAnnotation implements InterfaceWithValidateOnExecutionAnnotation { - @Override - public int bar() { - return 0; - } - } - - private static class ImplementsALotOfInterfacesButNoneAreAnnotated implements Serializable, Predicate, Comparable { - - @Override - public int compareTo(ImplementsALotOfInterfacesButNoneAreAnnotated o) { - return 0; - } - - @Override - public boolean test(Integer integer) { - return false; - } - } - - private static class ExtendsCleanClassButHasOwnAnnotation extends ImplementsALotOfInterfacesButNoneAreAnnotated { - - @ValidateOnExecution - public int bar() { - return 0; - } - } - - /** - * This class and {@link ValidNumber} is taken from Felix tests, where the issue was initially - * discovered. - */ - public static class BeanWithCustomConstraintOnParameter { - - public void doDefault(@ValidNumber String number) { - } - } - - public static class BeanWithCustomConstraintOnField { - private @ValidNumber String number; - } - - - public static class BeanWithCustomConstraintOnReturnValue { - @ValidNumber - String number() { - return null; - } - } - - @Documented - @Target({ ANNOTATION_TYPE, METHOD, FIELD, CONSTRUCTOR, PARAMETER }) - @Retention(RUNTIME) - @Constraint(validatedBy = {}) - @Size(min = 3, message = "Must be 3 at least") - @Pattern(regexp = "[0-9]*") - @NotNull(message = "Cannot be null") - public @interface ValidNumber { - - String message() default "invalid number"; - - Class[] groups() default {}; - - Class[] payload() default {}; - - String value() default ""; - } -} From b75c9fcd24195a6204f900343d8262ebbb5b79e4 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 9 Aug 2018 15:13:07 +0200 Subject: [PATCH 110/393] HV-1644 Avoid having JavaFX as a transitive dependency Also remove the snapshot repository we temporarily added as the artifacts have been published to Maven Central. --- distribution/pom.xml | 14 ++++++++++++++ documentation/pom.xml | 14 ++++++++++++++ engine/pom.xml | 5 +++-- pom.xml | 10 +++------- tck-runner/pom.xml | 14 ++++++++++++++ 5 files changed, 48 insertions(+), 9 deletions(-) diff --git a/distribution/pom.xml b/distribution/pom.xml index 68e669143d..a60c2e907e 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -210,5 +210,19 @@ -html5 + + jdk11+ + + [11,) + + + + org.openjfx + javafx-base + ${version.org.openjfx} + provided + + + diff --git a/documentation/pom.xml b/documentation/pom.xml index 5b2b1c74c9..76e5181564 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -339,5 +339,19 @@ + + jdk11+ + + [11,) + + + + org.openjfx + javafx-base + ${version.org.openjfx} + test + + + diff --git a/engine/pom.xml b/engine/pom.xml index edc12d861d..5fd0209f0b 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -290,8 +290,9 @@ org.openjfx - javafx.base - 11.0.0-SNAPSHOT + javafx-base + ${version.org.openjfx} + provided diff --git a/pom.xml b/pom.xml index 7c32639b7e..9119b332f6 100644 --- a/pom.xml +++ b/pom.xml @@ -158,6 +158,9 @@ 1.2 + + 11-ea+19 + 1.1.11.Final 6.8 @@ -1255,13 +1258,6 @@ - - - sonatype-oss-snapshots - Sonatype OSS Snapshots - https://oss.sonatype.org/content/repositories/snapshots/ - - jqassistant diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index d3c3159efd..b9f98b5536 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -368,5 +368,19 @@ --add-opens java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED + + jdk11+ + + [11,) + + + + org.openjfx + javafx-base + ${version.org.openjfx} + test + + + From 82b84873243a415aa95d4bc7878714471bf2ba83 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 9 Aug 2018 19:15:35 +0200 Subject: [PATCH 111/393] HV-1644 Fix surefire options to properly run the JavaFX tests Fix the test.policy file too as it was using a property that has been renamed. --- tck-runner/pom.xml | 6 +++--- tck-runner/src/test/resources/test.policy | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index b9f98b5536..454ce6932d 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -176,9 +176,9 @@ LocalSecurityManagerTesting - -DincludeJavaFXTests=true -Djava.security.manager -Djava.security.policy=${project.build.directory}/test-classes/test.policy + -DincludeJavaFXTests=true -Djava.security.manager -Djava.security.policy=${project.build.directory}/test-classes/test.policy - + @@ -227,7 +227,7 @@ - -DincludeJavaFXTests=true -Xmx1024m -Djava.util.logging.manager=org.jboss.logmanager.LogManager + -DincludeJavaFXTests=true -Xmx1024m -Djava.util.logging.manager=org.jboss.logmanager.LogManager Servlet 3.0 diff --git a/tck-runner/src/test/resources/test.policy b/tck-runner/src/test/resources/test.policy index 1b454f882e..61b629f5db 100644 --- a/tck-runner/src/test/resources/test.policy +++ b/tck-runner/src/test/resources/test.policy @@ -80,7 +80,7 @@ grant codeBase "file:${localRepository}/org/hibernate/beanvalidation/tck/-" { // tests (which do not use privileged actions for these) grant codeBase "file:${project.build.directory}/classes" { permission java.util.PropertyPermission "validation.provider", "read"; - permission java.io.FilePermission "${localRepository}/org/hibernate/beanvalidation/tck/beanvalidation-tck-tests/${tck.version}/beanvalidation-tck-tests-${tck.version}.jar", "read"; + permission java.io.FilePermission "${localRepository}/org/hibernate/beanvalidation/tck/beanvalidation-tck-tests/${version.org.hibernate.beanvalidation.tck}/beanvalidation-tck-tests-${version.org.hibernate.beanvalidation.tck}.jar", "read"; permission java.util.PropertyPermission "user.language", "write"; permission org.hibernate.validator.HibernateValidatorPermission "accessPrivateMembers"; }; From 15aa4882f0d70873d4702f0721924f436257af41 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 9 Aug 2018 23:40:27 +0200 Subject: [PATCH 112/393] HV-1647 Allow running TCK tests in container mode with JDK 11 We need some additional magic for JavaFX as it's not in the JDK anymore. --- tck-runner/pom.xml | 150 +++++++++++++++--- .../modules/jdk11/javafx/api/main/module.xml | 14 ++ .../{ => jdk8}/javafx/api/main/module.xml | 0 3 files changed, 141 insertions(+), 23 deletions(-) create mode 100644 tck-runner/src/test/modules/jdk11/javafx/api/main/module.xml rename tck-runner/src/test/modules/{ => jdk8}/javafx/api/main/module.xml (100%) diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 454ce6932d..4b01b88584 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -305,28 +305,9 @@ ${wildfly.target-dir} - - - maven-resources-plugin - - - copy-resources - generate-test-resources - - copy-resources - - - ${wildfly.target-dir}/modules/system/layers/base/ - - - src/test/modules - true - - - - - - + + + org.codehaus.gmavenplus @@ -360,7 +341,7 @@ - jdk9 + jdk9+ [9,) @@ -368,6 +349,38 @@ --add-opens java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED + + jdk10- + + (,11) + + + + + + maven-resources-plugin + + + copy-resources + generate-test-resources + + copy-resources + + + ${wildfly.target-dir}/modules/system/layers/base/ + + + src/test/modules/jdk8 + true + + + + + + + + + jdk11+ @@ -381,6 +394,97 @@ test + + + + + maven-resources-plugin + + + copy-resources + generate-test-resources + + copy-resources + + + ${wildfly.target-dir}/modules/system/layers/base/ + + + src/test/modules/jdk11 + true + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy + generate-test-resources + + copy + + + + + org.openjfx + javafx-base + ${version.org.openjfx} + jar + + + org.openjfx + javafx-base + ${version.org.openjfx} + ${javafx.platform} + jar + + + ${wildfly.target-dir}/modules/system/layers/base/javafx/api/main/ + + + + + + + + + + linux + + + linux + + + + linux + + + + macosx + + + mac os x + + + + mac + + + + windows + + + windows + + + + win + diff --git a/tck-runner/src/test/modules/jdk11/javafx/api/main/module.xml b/tck-runner/src/test/modules/jdk11/javafx/api/main/module.xml new file mode 100644 index 0000000000..91344118d8 --- /dev/null +++ b/tck-runner/src/test/modules/jdk11/javafx/api/main/module.xml @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/tck-runner/src/test/modules/javafx/api/main/module.xml b/tck-runner/src/test/modules/jdk8/javafx/api/main/module.xml similarity index 100% rename from tck-runner/src/test/modules/javafx/api/main/module.xml rename to tck-runner/src/test/modules/jdk8/javafx/api/main/module.xml From ab66cfe5a3fc89822c5843cb1de3eefb0496ae01 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 10 Aug 2018 10:40:27 +0200 Subject: [PATCH 113/393] HV-1648 Reenable WildFly integration tests for JDK 11 --- integration/pom.xml | 239 +++++++++++++++++++++++++++++--------------- pom.xml | 8 +- 2 files changed, 162 insertions(+), 85 deletions(-) diff --git a/integration/pom.xml b/integration/pom.xml index 15618dd186..7e78f49241 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -165,19 +165,6 @@ target/failsafe-reports/failsafe-summary-wildfly-current.xml - - - wildfly-secondary-integration-test - - integration-test - - - - wildfly-secondary - - target/failsafe-reports/failsafe-summary-wildfly-secondary.xml - - verify @@ -186,7 +173,6 @@ target/failsafe-reports/failsafe-summary-wildfly-current.xml - target/failsafe-reports/failsafe-summary-wildfly-secondary.xml @@ -196,7 +182,7 @@ maven-dependency-plugin - unpack-wildfly + unpack-wildfly-current pre-integration-test unpack @@ -212,20 +198,11 @@ false ${project.build.directory} - - - org.wildfly - wildfly-dist - ${version.wildfly.secondary} - tar.gz - false - ${project.build.directory} - - copy-patch + copy-patch-current pre-integration-test copy @@ -241,20 +218,11 @@ zip ${project.build.directory} - - - ${project.groupId} - hibernate-validator-modules - ${project.version} - wildfly-${version.wildfly.secondary}-patch - zip - ${project.build.directory} - - copy-javamoney + copy-javamoney-current pre-integration-test copy @@ -274,19 +242,6 @@ ${version.org.javamoney.moneta} ${wildfly.modules-dir}/org/javamoney/moneta/main/ - - - javax.money - money-api - ${version.javax.money} - ${wildfly-secondary.modules-dir}/javax/money/api/main/ - - - org.javamoney - moneta - ${version.org.javamoney.moneta} - ${wildfly-secondary.modules-dir}/org/javamoney/moneta/main/ - @@ -312,23 +267,6 @@ - - - copy-wildfly-secondary-resources - pre-integration-test - - copy-resources - - - ${wildfly-secondary.modules-dir} - - - src/test/modules - true - - - - @@ -351,22 +289,6 @@ - - - apply-wildfly-secondary-patch-file - pre-integration-test - - execute-commands - - - true - ${project.build.directory}/wildfly-${version.wildfly.secondary}/ - false - - patch apply ${project.build.directory}/hibernate-validator-modules-${project.version}-wildfly-${version.wildfly.secondary}-patch.zip - - - @@ -382,5 +304,160 @@ --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED + + + jdk10- + + (,11) + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + wildfly-secondary-integration-test + + integration-test + + + + wildfly-secondary + + target/failsafe-reports/failsafe-summary-wildfly-secondary.xml + + + + verify + + verify + + + + target/failsafe-reports/failsafe-summary-wildfly-current.xml + target/failsafe-reports/failsafe-summary-wildfly-secondary.xml + + + + + + + maven-dependency-plugin + + + unpack-wildfly-secondary + pre-integration-test + + unpack + + + + + + org.wildfly + wildfly-dist + ${version.wildfly.secondary} + tar.gz + false + ${project.build.directory} + + + + + + copy-patch-secondary + pre-integration-test + + copy + + + + + + ${project.groupId} + hibernate-validator-modules + ${project.version} + wildfly-${version.wildfly.secondary}-patch + zip + ${project.build.directory} + + + + + + copy-javamoney-secondary + pre-integration-test + + copy + + + + + + javax.money + money-api + ${version.javax.money} + ${wildfly-secondary.modules-dir}/javax/money/api/main/ + + + org.javamoney + moneta + ${version.org.javamoney.moneta} + ${wildfly-secondary.modules-dir}/org/javamoney/moneta/main/ + + + + + + + + maven-resources-plugin + + + + copy-wildfly-secondary-resources + pre-integration-test + + copy-resources + + + ${wildfly-secondary.modules-dir} + + + src/test/modules + true + + + + + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + apply-wildfly-secondary-patch-file + pre-integration-test + + execute-commands + + + true + ${project.build.directory}/wildfly-${version.wildfly.secondary}/ + false + + patch apply ${project.build.directory}/hibernate-validator-modules-${project.version}-wildfly-${version.wildfly.secondary}-patch.zip + + + + + + + + diff --git a/pom.xml b/pom.xml index 9119b332f6..a5660b8af9 100644 --- a/pom.xml +++ b/pom.xml @@ -91,6 +91,7 @@ tck-runner annotation-processor performance + integration @@ -124,9 +125,9 @@ 2.1.0.Final - 13.0.0.Final + 14.0.0.Beta1 - 12.0.0.Final + 13.0.0.Final ${version.wildfly} @@ -148,7 +149,7 @@ --> 2.0 3.0.4.Final - 2.1.0.Final + 2.1.1.Final 1.0.1.Final 1.0.0.Final @@ -1217,7 +1218,6 @@ (,11) - integration osgi From 562359a06272099a62f0ba9b8550f5ba2de15e0f Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 10 Aug 2018 12:19:59 +0200 Subject: [PATCH 114/393] HV-1649 Upgrade to Bean Validation TCK 2.0.4.Final --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a5660b8af9..c409971068 100644 --- a/pom.xml +++ b/pom.xml @@ -117,7 +117,7 @@ 2.0.1.Final - 2.0.3.Final + 2.0.4.Final 2.8 3.0.1-b09 From 1ad23ad6e8c45bcba989e1a068cebea7b4a4c907 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Fri, 10 Aug 2018 16:11:22 +0000 Subject: [PATCH 115/393] [Jenkins release job] README.md updated by release build 6.0.12.Final --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 36455f7a48..b5c9efd472 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hibernate Validator -*Version: 6.0.10.Final - 15-05-2018* +*Version: 6.0.12.Final - 10-08-2018* ## What is it? @@ -35,7 +35,7 @@ Logging will delegate any log requests to that provider. org.hibernate.validator hibernate-validator - 6.0.10.Final + 6.0.12.Final You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. @@ -54,7 +54,7 @@ extension by adding the following dependency: org.hibernate.validator hibernate-validator-cdi - 6.0.10.Final + 6.0.12.Final * _hibernate-validator-annotation-processor-<version>.jar_ is an optional jar which can be integrated with your build From d3858bc7c7c003d4b4f892f5831da40b5f20ccf3 Mon Sep 17 00:00:00 2001 From: Audrey Romanet Date: Mon, 20 Aug 2018 11:36:06 +0200 Subject: [PATCH 116/393] HV-1650 use ASCII encoding in French translations --- .../ValidationMessages_fr.properties | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties index 5f9715ecd4..675fb5251a 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties @@ -9,7 +9,7 @@ javax.validation.constraints.FutureOrPresent.message = doit \u00EAtre dans le pr javax.validation.constraints.Max.message = doit \u00EAtre au maximum \u00E9gal \u00E0 {value} javax.validation.constraints.Min.message = doit \u00EAtre au minimum \u00E9gal \u00E0 {value} javax.validation.constraints.Negative.message = doit \u00EAtre strictement n\u00E9gatif -javax.validation.constraints.NegativeOrZero.message = doit \u00EAtre n\u00E9gatif ou \u00E9gal à 0 +javax.validation.constraints.NegativeOrZero.message = doit \u00EAtre n\u00E9gatif ou \u00E9gal \u00E0 0 javax.validation.constraints.NotBlank.message = ne peut pas \u00EAtre vide javax.validation.constraints.NotEmpty.message = ne peut pas \u00EAtre vide javax.validation.constraints.NotNull.message = ne peut pas \u00EAtre nul @@ -18,7 +18,7 @@ javax.validation.constraints.Past.message = doit \u00EAtre dans le pa javax.validation.constraints.PastOrPresent.message = doit \u00EAtre dans le pass\u00E9 ou dans le pr\u00E9sent javax.validation.constraints.Pattern.message = doit respecter "{regexp}" javax.validation.constraints.Positive.message = doit \u00EAtre strictement positif -javax.validation.constraints.PositiveOrZero.message = doit \u00EAtre positif ou \u00E9gal à 0 +javax.validation.constraints.PositiveOrZero.message = doit \u00EAtre positif ou \u00E9gal \u00E0 0 javax.validation.constraints.Size.message = la taille doit \u00EAtre comprise entre {min} et {max} org.hibernate.validator.constraints.CreditCardNumber.message = num\u00E9ro de carte de cr\u00E9dit invalide @@ -26,8 +26,8 @@ org.hibernate.validator.constraints.Currency.message = devise invalide ( org.hibernate.validator.constraints.EAN.message = code barre {type} invalide org.hibernate.validator.constraints.Email.message = adresse email mal form\u00E9e org.hibernate.validator.constraints.ISBN.message = ISBN invalide -org.hibernate.validator.constraints.Length.message = la longueur doit \u00EAtre comprise entre {min} et {max} caractères -org.hibernate.validator.constraints.CodePointLength.message = la longueur doit \u00EAtre comprise entre {min} et {max} caractères +org.hibernate.validator.constraints.Length.message = la longueur doit \u00EAtre comprise entre {min} et {max} caract\u00E8res +org.hibernate.validator.constraints.CodePointLength.message = la longueur doit \u00EAtre comprise entre {min} et {max} caract\u00E8res org.hibernate.validator.constraints.LuhnCheck.message = le chiffre de contr\u00F4le pour ${validatedValue} est invalide, le contr\u00F4le Luhn Modulo 10 a \u00E9chou\u00E9 org.hibernate.validator.constraints.Mod10Check.message = le chiffre de contr\u00F4le pour ${validatedValue} est invalide, le contr\u00F4le Modulo 10 a \u00E9chou\u00E9 org.hibernate.validator.constraints.Mod11Check.message = le chiffre de contr\u00F4le pour ${validatedValue} est invalide, le contr\u00F4le Modulo 11 a \u00E9chou\u00E9 @@ -41,13 +41,13 @@ org.hibernate.validator.constraints.ScriptAssert.message = le script "{scrip org.hibernate.validator.constraints.UniqueElements.message = ne doit contenir que des \u00E9l\u00E9ments uniques org.hibernate.validator.constraints.URL.message = URL mal form\u00E9e -org.hibernate.validator.constraints.br.CNPJ.message = numéro d'enregistrement brésilien de société contribuable (CNPJ) invalide -org.hibernate.validator.constraints.br.CPF.message = numéro d'enregistrement brésilien de contribuable individuel (CPF) invalide -org.hibernate.validator.constraints.br.TituloEleitoral.message = numéro de carte d'électeur brésilienne invalide +org.hibernate.validator.constraints.br.CNPJ.message = num\u00E9ro d'enregistrement br\u00E9silien de soci\u00E9t\u00E9 contribuable (CNPJ) invalide +org.hibernate.validator.constraints.br.CPF.message = num\u00E9ro d'enregistrement br\u00E9silien de contribuable individuel (CPF) invalide +org.hibernate.validator.constraints.br.TituloEleitoral.message = num\u00E9ro de carte d'\u00E9lecteur br\u00E9silienne invalide -org.hibernate.validator.constraints.pl.REGON.message = numéro d'imposition polonais (REGON) invalide -org.hibernate.validator.constraints.pl.NIP.message = numéro d'identification de TVA polonais (NIP) invalide -org.hibernate.validator.constraints.pl.PESEL.message = numéro d'identification national polonais (PESEL) invalide +org.hibernate.validator.constraints.pl.REGON.message = num\u00E9ro d'imposition polonais (REGON) invalide +org.hibernate.validator.constraints.pl.NIP.message = num\u00E9ro d'identification de TVA polonais (NIP) invalide +org.hibernate.validator.constraints.pl.PESEL.message = num\u00E9ro d'identification national polonais (PESEL) invalide org.hibernate.validator.constraints.time.DurationMax.message = doit \u00EAtre plus court que${inclusive == true ? ' ou \u00E9gal \u00E0' : ''}${days == 0 ? '' : days == 1 ? ' 1 jour' : ' ' += days += ' jours'}${hours == 0 ? '' : hours == 1 ? ' 1 heure' : ' ' += hours += ' heures'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 seconde' : ' ' += seconds += ' secondes'}${millis == 0 ? '' : millis == 1 ? ' 1 milliseconde' : ' ' += millis += ' millisecondes'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanoseconde' : ' ' += nanos += ' nanosecondes'} org.hibernate.validator.constraints.time.DurationMin.message = doit \u00EAtre plus long que${inclusive == true ? ' ou \u00E9gal \u00E0' : ''}${days == 0 ? '' : days == 1 ? ' 1 jour' : ' ' += days += ' jours'}${hours == 0 ? '' : hours == 1 ? ' 1 heure' : ' ' += hours += ' heures'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 seconde' : ' ' += seconds += ' secondes'}${millis == 0 ? '' : millis == 1 ? ' 1 milliseconde' : ' ' += millis += ' millisecondes'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanoseconde' : ' ' += nanos += ' nanosecondes'} From 53fd14f7aa075dc0675596671d5de8083ab0a9fb Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 22 Aug 2018 12:41:24 +0200 Subject: [PATCH 117/393] HV-1652 Fix a few theoretical null pointer dereference issues --- .../ServiceLoaderBasedConstraintMappingContributor.java | 5 +++-- .../internal/metadata/core/ConstraintHelper.java | 4 ++-- .../validator/internal/metadata/core/MetaConstraints.java | 8 ++++---- .../hibernate/validator/internal/util/logging/Log.java | 3 +++ .../internal/xml/config/ValidationXmlParser.java | 8 +++++++- .../validator/internal/xml/mapping/MappingXmlParser.java | 4 ++++ 6 files changed, 23 insertions(+), 9 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ServiceLoaderBasedConstraintMappingContributor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ServiceLoaderBasedConstraintMappingContributor.java index a4ebb12d7d..2d4b4a4444 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ServiceLoaderBasedConstraintMappingContributor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ServiceLoaderBasedConstraintMappingContributor.java @@ -60,7 +60,7 @@ public void createConstraintMappings(ConstraintMappingBuilder builder) { ConstraintValidator.class ) ); for ( ConstraintValidator constraintValidator : discoveredConstraintValidators ) { - Class constraintValidatorClass = constraintValidator.getClass(); + Class constraintValidatorClass = constraintValidator.getClass(); Class annotationType = determineAnnotationType( constraintValidatorClass ); List> validators = customValidators.get( annotationType ); @@ -90,7 +90,8 @@ private void registerConstraintDefinition(ConstraintMappi } } - private Class determineAnnotationType(Class constraintValidatorClass) { + @SuppressWarnings("rawtypes") + private Class determineAnnotationType(Class constraintValidatorClass) { ResolvedType resolvedType = typeResolutionHelper.getTypeResolver() .resolve( constraintValidatorClass ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java index 2b949bef6b..487f912cb3 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java @@ -885,7 +885,7 @@ private void assertPayloadParameterExists(Class annotation throw LOG.getConstraintWithoutMandatoryParameterException( PAYLOAD, annotationType.getName() ); } Class[] defaultPayload = (Class[]) method.getDefaultValue(); - if ( defaultPayload.length != 0 ) { + if ( defaultPayload == null || defaultPayload.length != 0 ) { throw LOG.getWrongDefaultValueForPayloadParameterException( annotationType.getName() ); } } @@ -901,7 +901,7 @@ private void assertGroupsParameterExists(Class annotationT throw LOG.getConstraintWithoutMandatoryParameterException( GROUPS, annotationType.getName() ); } Class[] defaultGroups = (Class[]) method.getDefaultValue(); - if ( defaultGroups.length != 0 ) { + if ( defaultGroups == null || defaultGroups.length != 0 ) { throw LOG.getWrongDefaultValueForGroupsParameterException( annotationType.getName() ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraints.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraints.java index 0a95ddd10d..ced135aa74 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraints.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraints.java @@ -159,14 +159,14 @@ private static void addValueExtractorDescriptorForTypeArgumentLocation( ValueExt */ private static Class getWrappedValueType(TypeResolutionHelper typeResolutionHelper, Type declaredType, ValueExtractorDescriptor valueExtractorDescriptor) { ResolvedType resolvedType = typeResolutionHelper.getTypeResolver().resolve( declaredType ); + List resolvedTypeParameters = resolvedType.typeParametersFor( valueExtractorDescriptor.getContainerType() ); - if ( resolvedTypeParameters.isEmpty() ) { + if ( resolvedTypeParameters == null || resolvedTypeParameters.isEmpty() ) { throw LOG.getNoValueExtractorFoundForUnwrapException( declaredType ); } - else { - return resolvedTypeParameters.get( TypeVariables.getTypeParameterIndex( valueExtractorDescriptor.getExtractedTypeParameter() ) ).getErasedType(); - } + + return resolvedTypeParameters.get( TypeVariables.getTypeParameterIndex( valueExtractorDescriptor.getExtractedTypeParameter() ) ).getErasedType(); } private static TypeVariable getContainerClassTypeParameter(Class declaredType, ValueExtractorDescriptor selectedValueExtractorDescriptor) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 3382783496..c79e7ca4ef 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -872,4 +872,7 @@ ConstraintDefinitionException getConstraintValidatorDefinitionConstraintMismatch @Message(id = 247, value = "Unable to instantiate getter property selection strategy class %s.") ValidationException getUnableToInstantiateGetterPropertySelectionStrategyClassException(String getterPropertySelectionStrategyClassName, @Cause Exception e); + + @Message(id = 248, value = "Unable to get an XML schema named %s.") + ValidationException unableToGetXmlSchema(String schemaResourceName); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationXmlParser.java b/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationXmlParser.java index bdfb20f81d..45d15c333a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationXmlParser.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationXmlParser.java @@ -136,7 +136,13 @@ private Schema getSchema(XmlParserHelper xmlParserHelper, String schemaVersion) throw LOG.getUnsupportedSchemaVersionException( VALIDATION_XML_FILE, schemaVersion ); } - return xmlParserHelper.getSchema( schemaResource ); + Schema schema = xmlParserHelper.getSchema( schemaResource ); + + if ( schema == null ) { + throw LOG.unableToGetXmlSchema( schemaResource ); + } + + return schema; } private void closeStream(InputStream inputStream) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java index 3c70c66e50..51f5e103e4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java @@ -117,6 +117,10 @@ public final void parse(Set mappingStreams) { // do any validation of the input. String schemaResourceName = getSchemaResourceName( schemaVersion ); Schema schema = xmlParserHelper.getSchema( schemaResourceName ); + if ( schema == null ) { + throw LOG.unableToGetXmlSchema( schemaResourceName ); + } + Validator validator = schema.newValidator(); validator.validate( new StreamSource( new CloseIgnoringInputStream( in ) ) ); From 6b00bffc6381dc16d8321583b6e09b8df4189129 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Wed, 22 Aug 2018 22:16:06 +0000 Subject: [PATCH 118/393] [Jenkins release job] README.md updated by release build 6.0.13.Final --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b5c9efd472..edaad42681 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hibernate Validator -*Version: 6.0.12.Final - 10-08-2018* +*Version: 6.0.13.Final - 22-08-2018* ## What is it? @@ -35,7 +35,7 @@ Logging will delegate any log requests to that provider. org.hibernate.validator hibernate-validator - 6.0.12.Final + 6.0.13.Final You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. @@ -54,7 +54,7 @@ extension by adding the following dependency: org.hibernate.validator hibernate-validator-cdi - 6.0.12.Final + 6.0.13.Final * _hibernate-validator-annotation-processor-<version>.jar_ is an optional jar which can be integrated with your build From 13e32aefcb6ff77735e130bd37f71b87f8599307 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Wed, 18 Jul 2018 13:03:16 +0000 Subject: [PATCH 119/393] [Jenkins release job] changelog.txt updated by release build 6.0.11.Final --- changelog.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/changelog.txt b/changelog.txt index ad70f7062e..49f25c3ea4 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,26 @@ Hibernate Validator Changelog ============================= +6.0.11.Final (18-07-2018) +------------------------- + +** Bug + * HV-1637 - translations - PropertNotFoundException for @DecimalMax when using the German translation + +** Improvement + * HV-1628 - annotation-processor, engine, tests - Configure a stricter forbidden-apis policy and remove calls deprecated in Java 10 + * HV-1615 - translations - Improvements on the dutch translations + +** Remove Feature + * HV-1624 - engine - Remove the StaticFieldELResolver + +** Task + * HV-1641 - build - Use the OSS snapshot repository to download the JavaFX dependencies when building with JDK 11 + * HV-1640 - build - Add compatibility with the latest JDK 11 build 22 + * HV-1610 - integration - Reenable OSGi tests for JDK 10 + * HV-1608 - build - Have the build work with JDK 11 + * HV-1577 - engine - Use Stax instead of JAXB to parse the XML descriptors + 6.0.10.Final (15-05-2018) ------------------------- From d1ee13dbf7fc4201a3bafab0292fe7f6abcf8d7b Mon Sep 17 00:00:00 2001 From: Jenkins Date: Fri, 10 Aug 2018 16:11:22 +0000 Subject: [PATCH 120/393] [Jenkins release job] changelog.txt updated by release build 6.0.12.Final --- changelog.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/changelog.txt b/changelog.txt index 49f25c3ea4..410adc4b00 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,23 @@ Hibernate Validator Changelog ============================= +6.0.12.Final (10-08-2018) +------------------------- + +** Bug + * HV-1645 - extensions - Revert HV-1609 due to increased CDI startup caused by ValidateableBeanFilter + * HV-1644 - build - Using Hibernate Validator with Java 11 brings JavaFX on the classpath + +** Improvement + * HV-1643 - translations - Fix Russian translation for @Null constraint + +** Task + * HV-1649 - tck-runner - Upgrade to Bean Validation TCK 2.0.4.Final + * HV-1648 - build, integration - Reenable WildFly integration tests for JDK 11 + * HV-1647 - tck-runner - Allow running TCK tests in container mode with JDK 11 + * HV-1646 - build, integration, tck-runner - Upgrade WildFly to 14.0.0.Beta1 + * HV-1627 - build - Upgrade our JPA test dependency to 2.2 + 6.0.11.Final (18-07-2018) ------------------------- From 60e5c17bfbe709f32018e97a483f6011093587fe Mon Sep 17 00:00:00 2001 From: Jenkins Date: Wed, 22 Aug 2018 22:16:07 +0000 Subject: [PATCH 121/393] [Jenkins release job] changelog.txt updated by release build 6.0.13.Final --- changelog.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/changelog.txt b/changelog.txt index 410adc4b00..4d3458aa8a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,13 @@ Hibernate Validator Changelog ============================= +6.0.13.Final (22-08-2018) +------------------------- + +** Bug + * HV-1652 - engine - Fix a few theoretical null pointer dereference issues + * HV-1650 - validators - French translations are badly encoded + 6.0.12.Final (10-08-2018) ------------------------- From dec84676d255c17574c15dace7891c1afd09260b Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 24 Oct 2018 14:42:48 +0200 Subject: [PATCH 122/393] HV-1658 Replace a couple of stream usages --- .../metadata/core/ConstraintHelper.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java index 487f912cb3..7858874584 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java @@ -687,18 +687,21 @@ private static void putConstraint(Map void putConstraints(Map, List>> validators, Class constraintType, Class> validatorType1, Class> validatorType2) { - List> descriptors = Stream.of( validatorType1, validatorType2 ) - .map( vt -> ConstraintValidatorDescriptor.forClass( vt, constraintType ) ) - .collect( Collectors.toList() ); + List> descriptors = new ArrayList<>( 2 ); + + descriptors.add( ConstraintValidatorDescriptor.forClass( validatorType1, constraintType ) ); + descriptors.add( ConstraintValidatorDescriptor.forClass( validatorType2, constraintType ) ); validators.put( constraintType, CollectionHelper.toImmutableList( descriptors ) ); } private static void putConstraints(Map, List>> validators, - Class constraintType, List>> validatorDescriptors) { - List> descriptors = validatorDescriptors.stream() - .map( vt -> ConstraintValidatorDescriptor.forClass( vt, constraintType ) ) - .collect( Collectors.toList() ); + Class constraintType, List>> validatorTypes) { + List> descriptors = new ArrayList<>( validatorTypes.size() ); + + for ( Class> validatorType : validatorTypes ) { + descriptors.add( ConstraintValidatorDescriptor.forClass( validatorType, constraintType ) ); + } validators.put( constraintType, CollectionHelper.toImmutableList( descriptors ) ); } From c31a27d10b1d85b70cd0682a51a7deae2af23505 Mon Sep 17 00:00:00 2001 From: AOE Takashi Date: Mon, 1 Oct 2018 22:50:29 +0900 Subject: [PATCH 123/393] HV-1656 Add translation of Validation Messages for Japanese language --- .../ValidationMessages_ja.properties | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 engine/src/main/resources/org/hibernate/validator/ValidationMessages_ja.properties diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ja.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ja.properties new file mode 100644 index 0000000000..71994d2ae4 --- /dev/null +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ja.properties @@ -0,0 +1,53 @@ +javax.validation.constraints.AssertFalse.message = false \u306b\u3057\u3066\u304f\u3060\u3055\u3044 +javax.validation.constraints.AssertTrue.message = true \u306b\u3057\u3066\u304f\u3060\u3055\u3044 +javax.validation.constraints.DecimalMax.message = {value} ${inclusive == true ? '\u4ee5\u4e0b\u306e\u5024\u306b\u3057\u3066\u304f\u3060\u3055\u3044' : '\u3088\u308a\u5c0f\u3055\u306a\u5024\u306b\u3057\u3066\u304f\u3060\u3055\u3044'} +javax.validation.constraints.DecimalMin.message = {value} ${inclusive == true ? '\u4ee5\u4e0a\u306e\u5024\u306b\u3057\u3066\u304f\u3060\u3055\u3044' : '\u3088\u308a\u5927\u304d\u306a\u5024\u306b\u3057\u3066\u304f\u3060\u3055\u3044'} +javax.validation.constraints.Digits.message = \u5024\u306f\u6b21\u306e\u7bc4\u56f2\u306b\u3057\u3066\u304f\u3060\u3055\u3044 (<\u6574\u6570 {integer} \u6841>.<\u5c0f\u6570\u70b9\u4ee5\u4e0b {fraction} \u6841>) +javax.validation.constraints.Email.message = \u96fb\u5b50\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3068\u3057\u3066\u6b63\u3057\u3044\u5f62\u5f0f\u306b\u3057\u3066\u304f\u3060\u3055\u3044 +javax.validation.constraints.Future.message = \u672a\u6765\u306e\u65e5\u4ed8\u306b\u3057\u3066\u304f\u3060\u3055\u3044 +javax.validation.constraints.FutureOrPresent.message = \u73fe\u5728\u3082\u3057\u304f\u306f\u672a\u6765\u306e\u65e5\u4ed8\u306b\u3057\u3066\u304f\u3060\u3055\u3044 +javax.validation.constraints.Max.message = {value} \u4ee5\u4e0b\u306e\u5024\u306b\u3057\u3066\u304f\u3060\u3055\u3044 +javax.validation.constraints.Min.message = {value} \u4ee5\u4e0a\u306e\u5024\u306b\u3057\u3066\u304f\u3060\u3055\u3044 +javax.validation.constraints.Negative.message = 0 \u3088\u308a\u5c0f\u3055\u306a\u5024\u306b\u3057\u3066\u304f\u3060\u3055\u3044 +javax.validation.constraints.NegativeOrZero.message = 0 \u4ee5\u4e0b\u306e\u5024\u306b\u3057\u3066\u304f\u3060\u3055\u3044 +javax.validation.constraints.NotBlank.message = \u7a7a\u767d\u306f\u8a31\u53ef\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +javax.validation.constraints.NotEmpty.message = \u7a7a\u8981\u7d20\u306f\u8a31\u53ef\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +javax.validation.constraints.NotNull.message = null \u306f\u8a31\u53ef\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +javax.validation.constraints.Null.message = null \u306b\u3057\u3066\u304f\u3060\u3055\u3044 +javax.validation.constraints.Past.message = \u904e\u53bb\u306e\u65e5\u4ed8\u306b\u3057\u3066\u304f\u3060\u3055\u3044 +javax.validation.constraints.PastOrPresent.message = \u73fe\u5728\u3082\u3057\u304f\u306f\u904e\u53bb\u306e\u65e5\u4ed8\u306b\u3057\u3066\u304f\u3060\u3055\u3044 +javax.validation.constraints.Pattern.message = \u6b63\u898f\u8868\u73fe "{regexp}" \u306b\u30de\u30c3\u30c1\u3055\u305b\u3066\u304f\u3060\u3055\u3044 +javax.validation.constraints.Positive.message = 0 \u3088\u308a\u5927\u304d\u306a\u5024\u306b\u3057\u3066\u304f\u3060\u3055\u3044 +javax.validation.constraints.PositiveOrZero.message = 0 \u4ee5\u4e0a\u306e\u5024\u306b\u3057\u3066\u304f\u3060\u3055\u3044 +javax.validation.constraints.Size.message = {min} \u304b\u3089 {max} \u306e\u9593\u306e\u30b5\u30a4\u30ba\u306b\u3057\u3066\u304f\u3060\u3055\u3044 + +org.hibernate.validator.constraints.CreditCardNumber.message = \u6b63\u3057\u304f\u306a\u3044\u30af\u30ec\u30b8\u30c3\u30c8\u30ab\u30fc\u30c9\u306e\u756a\u53f7\u3067\u3059 +org.hibernate.validator.constraints.Currency.message = \u6b63\u3057\u304f\u306a\u3044\u901a\u8ca8\u5358\u4f4d\u3067\u3059 ({value} \u306e\u4e2d\u304b\u3089\u9078\u3093\u3067\u304f\u3060\u3055\u3044) +org.hibernate.validator.constraints.EAN.message = \u6b63\u3057\u304f\u306a\u3044 {type} \u30d0\u30fc\u30b3\u30fc\u30c9\u3067\u3059 +org.hibernate.validator.constraints.Email.message = \u96fb\u5b50\u30e1\u30fc\u30eb\u3068\u3057\u3066\u6b63\u3057\u3044\u5f62\u5f0f\u306b\u3057\u3066\u304f\u3060\u3055\u3044 +org.hibernate.validator.constraints.ISBN.message = \u6b63\u3057\u304f\u306a\u3044 ISBN \u3067\u3059 +org.hibernate.validator.constraints.Length.message = {min} \u304b\u3089 {max} \u306e\u9593\u306e\u9577\u3055\u306b\u3057\u3066\u304f\u3060\u3055\u3044 +org.hibernate.validator.constraints.CodePointLength.message = {min} \u304b\u3089 {max} \u306e\u9593\u306e\u9577\u3055\u306b\u3057\u3066\u304f\u3060\u3055\u3044 +org.hibernate.validator.constraints.LuhnCheck.message = ${validatedValue} \u306e\u30c1\u30a7\u30c3\u30af\u30c7\u30b8\u30c3\u30c8\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093 (Luhn \u30e2\u30c7\u30e5\u30e9\u30b910\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0) +org.hibernate.validator.constraints.Mod10Check.message = ${validatedValue} \u306e\u30c1\u30a7\u30c3\u30af\u30c7\u30b8\u30c3\u30c8\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093 (\u30e2\u30c7\u30e5\u30e9\u30b910) +org.hibernate.validator.constraints.Mod11Check.message = ${validatedValue} \u306e\u30c1\u30a7\u30c3\u30af\u30c7\u30b8\u30c3\u30c8\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093 (\u30e2\u30c7\u30e5\u30e9\u30b911) +org.hibernate.validator.constraints.ModCheck.message = ${validatedValue} \u306e\u30c1\u30a7\u30c3\u30af\u30c7\u30b8\u30c3\u30c8\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093 (${modType} \u306e\u30c1\u30a7\u30c3\u30af\u30b5\u30e0\u304c\u5931\u6557\u3057\u307e\u3057\u305f) +org.hibernate.validator.constraints.NotBlank.message = \u7a7a\u767d\u306f\u8a31\u53ef\u3055\u308c\u3066\u307e\u305b\u3093 +org.hibernate.validator.constraints.NotEmpty.message = \u7a7a\u8981\u7d20\u306f\u8a31\u53ef\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +org.hibernate.validator.constraints.ParametersScriptAssert.message = \u6b21\u306e\u30b9\u30af\u30ea\u30d7\u30c8\u5f0f "{script}" \u306b\u3088\u308b\u8a55\u4fa1\u7d50\u679c\u304c true \u306b\u306a\u308a\u307e\u305b\u3093\u3067\u3057\u305f +org.hibernate.validator.constraints.Range.message = {min} \u304b\u3089 {max} \u306e\u9593\u306b\u3057\u3066\u304f\u3060\u3055\u3044 +org.hibernate.validator.constraints.SafeHtml.message = \u5b89\u5168\u3067\u306f\u306a\u3044 HTML \u30b3\u30f3\u30c6\u30f3\u30c4\u3067\u3059 +org.hibernate.validator.constraints.ScriptAssert.message = \u6b21\u306e\u30b9\u30af\u30ea\u30d7\u30c8\u5f0f "{script}" \u306b\u3088\u308b\u8a55\u4fa1\u7d50\u679c\u304c true \u306b\u306a\u308a\u307e\u305b\u3093\u3067\u3057\u305f +org.hibernate.validator.constraints.UniqueElements.message = \u8981\u7d20\u306f\u5168\u3066\u30e6\u30cb\u30fc\u30af\u306b\u3057\u3066\u304f\u3060\u3055\u3044 +org.hibernate.validator.constraints.URL.message = URL \u3068\u3057\u3066\u6b63\u3057\u3044\u5f62\u5f0f\u306b\u3057\u3066\u304f\u3060\u3055\u3044 + +org.hibernate.validator.constraints.br.CNPJ.message = \u6b63\u3057\u304f\u306a\u3044\u30d6\u30e9\u30b8\u30eb\u6cd5\u4eba\u7528\u7a0e\u52d9\u767b\u8a18\u756a\u53f7 (CNPJ) \u3067\u3059 +org.hibernate.validator.constraints.br.CPF.message = \u6b63\u3057\u304f\u306a\u3044\u30d6\u30e9\u30b8\u30eb\u500b\u4eba\u7528\u7d0d\u7a0e\u8005\u756a\u53f7 (CPF) \u3067\u3059 +org.hibernate.validator.constraints.br.TituloEleitoral.message = \u6b63\u3057\u304f\u306a\u3044\u30d6\u30e9\u30b8\u30eb\u6295\u7968\u8005ID\u30ab\u30fc\u30c9\u756a\u53f7\u3067\u3059 + +org.hibernate.validator.constraints.pl.REGON.message = \u6b63\u3057\u304f\u306a\u3044\u30dd\u30fc\u30e9\u30f3\u30c9\u56fd\u5185\u7d4c\u6e08\u767b\u9332\u756a\u53f7 (REGON) \u3067\u3059 +org.hibernate.validator.constraints.pl.NIP.message = \u6b63\u3057\u304f\u306a\u3044\u30dd\u30fc\u30e9\u30f3\u30c9\u7d0d\u7a0e\u8005\u756a\u53f7 (NIP) \u3067\u3059 +org.hibernate.validator.constraints.pl.PESEL.message = \u6b63\u3057\u304f\u306a\u3044\u30dd\u30fc\u30e9\u30f3\u30c9\u500b\u4ebaID\u756a\u53f7 (PESEL) \u3067\u3059 + +org.hibernate.validator.constraints.time.DurationMax.message = ${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} ${inclusive == true ? '\u3068\u540c\u3058\u304b\u3088\u308a\u77ed\u3044\u6642\u9593\u306b\u3057\u3066\u304f\u3060\u3055\u3044' : '\u3088\u308a\u77ed\u3044\u6642\u9593\u306b\u3057\u3066\u304f\u3060\u3055\u3044'} +org.hibernate.validator.constraints.time.DurationMin.message = ${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} ${inclusive == true ? '\u3068\u540c\u3058\u304b\u3088\u308a\u9577\u3044\u6642\u9593\u306b\u3057\u3066\u304f\u3060\u3055\u3044' : '\u3088\u308a\u9577\u3044\u6642\u9593\u306b\u3057\u3066\u304f\u3060\u3055\u3044'} From 71070fbe3798d7a91eacad18e4d65fc22148b01d Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 24 Oct 2018 18:06:18 +0200 Subject: [PATCH 124/393] HV-1656 Add Takashi Aoe to copyright.txt --- copyright.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/copyright.txt b/copyright.txt index a386c100bc..afa62094ab 100644 --- a/copyright.txt +++ b/copyright.txt @@ -60,6 +60,7 @@ Shelly McGowan Steve Ebersole Strong Liu Tadhg Pearson +Takashi Aoe Tomaz Cerar Tommy Johansen Victor Rezende dos Santos From 7cbdb5338795f85a649726d922ebfcce38602798 Mon Sep 17 00:00:00 2001 From: Yao Date: Thu, 30 Aug 2018 00:01:43 +0800 Subject: [PATCH 125/393] HV-1653 Improve the javadoc of ParameterScriptAssert --- .../validator/constraints/ParameterScriptAssert.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/constraints/ParameterScriptAssert.java b/engine/src/main/java/org/hibernate/validator/constraints/ParameterScriptAssert.java index 889eecd16a..d15c7d833c 100644 --- a/engine/src/main/java/org/hibernate/validator/constraints/ParameterScriptAssert.java +++ b/engine/src/main/java/org/hibernate/validator/constraints/ParameterScriptAssert.java @@ -33,15 +33,16 @@ * ("Scripting for the JavaTM Platform") compatible engine can be * found on the classpath. To refer to a parameter within the scripting * expression, use its name as obtained by the active - * {@link javax.validation.ParameterNameProvider}. By default, {@code arg0}, {@code arg1} etc. - * will be used as parameter names. + * {@link javax.validation.ParameterNameProvider}. The default provider will + * return the actual parameter names, if the -parameters compiler option + * has been enabled, and {@code arg0}, {@code arg1} etc. otherwise. *

*

* The following listing shows an example using the JavaScript engine which * comes with the JDK: *

*
- * {@code @ParameterScriptAssert(script = "arg0.before(arg1)", lang = "javascript")
+ * {@code @ParameterScriptAssert(script = "start.before(end)", lang = "javascript")
  * public void createEvent(Date start, Date end) { ... }
  * }
  * 
From fb1c872712c709edd55d08d4aae6fdf11df51d97 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 24 Oct 2018 17:47:12 +0200 Subject: [PATCH 126/393] HV-1659 Upgrade WildFly to 14.0.1 --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index c409971068..077d502e5d 100644 --- a/pom.xml +++ b/pom.xml @@ -125,7 +125,7 @@ 2.1.0.Final - 14.0.0.Beta1 + 14.0.1.Final 13.0.0.Final @@ -147,8 +147,8 @@ They should be aligned with the ones from the Wildfly version we support See http://search.maven.org/#search|gav|1|g%3A"org.wildfly"%20AND%20a%3A"wildfly-parent" --> - 2.0 - 3.0.4.Final + 2.0.SP1 + 3.0.5.Final 2.1.1.Final 1.0.1.Final 1.0.0.Final From 5d1887e6cac88bf9c16c7b95259195507472912b Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Fri, 29 Jun 2018 12:07:57 +0200 Subject: [PATCH 127/393] HV-1661 Remove impossible case from ValidatorImpl#buildNewLocalExecutionContext() --- .../internal/engine/ValidatorImpl.java | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index 9bbe13193e..3bcef46a56 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -739,23 +739,14 @@ private void validateCascadedContainerElementsInContext(Object value, BaseBeanVa private ValueContext buildNewLocalExecutionContext(ValueContext valueContext, Object value) { ValueContext newValueContext; - if ( value != null ) { - newValueContext = ValueContext.getLocalExecutionContext( - validatorScopedContext.getParameterNameProvider(), - value, - beanMetaDataManager.getBeanMetaData( value.getClass() ), - valueContext.getPropertyPath() - ); - newValueContext.setCurrentValidatedValue( value ); - } - else { - newValueContext = ValueContext.getLocalExecutionContext( - validatorScopedContext.getParameterNameProvider(), - valueContext.getCurrentBeanType(), - valueContext.getCurrentBeanMetaData(), - valueContext.getPropertyPath() - ); - } + Contracts.assertNotNull( value, "value cannot be null" ); + newValueContext = ValueContext.getLocalExecutionContext( + validatorScopedContext.getParameterNameProvider(), + value, + beanMetaDataManager.getBeanMetaData( value.getClass() ), + valueContext.getPropertyPath() + ); + newValueContext.setCurrentValidatedValue( value ); return newValueContext; } From acfd96b5ccbe4c364a83ebbaaee37fd4077e76ec Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Thu, 12 Jul 2018 20:53:14 +0200 Subject: [PATCH 128/393] HV-1662 Extract BeanMetaDataBuilder to its own class file --- .../metadata/BeanMetaDataManager.java | 2 +- .../aggregated/BeanMetaDataBuilder.java | 330 ++++++++++++++++++ .../metadata/aggregated/BeanMetaDataImpl.java | 322 +---------------- 3 files changed, 339 insertions(+), 315 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataBuilder.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java index d1908005e3..cab11e9a73 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java @@ -22,7 +22,7 @@ import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl; -import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl.BeanMetaDataBuilder; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataBuilder; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataBuilder.java new file mode 100644 index 0000000000..765fdfe681 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataBuilder.java @@ -0,0 +1,330 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.metadata.aggregated; + +import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; + +import java.util.List; +import java.util.Set; + +import org.hibernate.validator.internal.engine.MethodValidationConfiguration; +import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; +import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; +import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; +import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; +import org.hibernate.validator.internal.metadata.raw.ConstrainedField; +import org.hibernate.validator.internal.metadata.raw.ConstrainedType; +import org.hibernate.validator.internal.properties.Callable; +import org.hibernate.validator.internal.util.ExecutableHelper; +import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; +import org.hibernate.validator.internal.util.StringHelper; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.spi.group.DefaultGroupSequenceProvider; + +/** + * @author Hardy Ferentschik + * @author Gunnar Morling + * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI + * @author Chris Beckey <cbeckey@paypal.com> + * @author Guillaume Smet + * @author Marko Bekhta + */ +public class BeanMetaDataBuilder { + + private final ConstraintHelper constraintHelper; + private final ValidationOrderGenerator validationOrderGenerator; + private final Class beanClass; + private final Set builders = newHashSet(); + private final ExecutableHelper executableHelper; + private final TypeResolutionHelper typeResolutionHelper; + private final ValueExtractorManager valueExtractorManager; + private final ExecutableParameterNameProvider parameterNameProvider; + private final MethodValidationConfiguration methodValidationConfiguration; + + private ConfigurationSource sequenceSource; + private ConfigurationSource providerSource; + private List> defaultGroupSequence; + private DefaultGroupSequenceProvider defaultGroupSequenceProvider; + + + private BeanMetaDataBuilder( + ConstraintHelper constraintHelper, + ExecutableHelper executableHelper, + TypeResolutionHelper typeResolutionHelper, + ValueExtractorManager valueExtractorManager, + ExecutableParameterNameProvider parameterNameProvider, + ValidationOrderGenerator validationOrderGenerator, + Class beanClass, + MethodValidationConfiguration methodValidationConfiguration) { + this.beanClass = beanClass; + this.constraintHelper = constraintHelper; + this.validationOrderGenerator = validationOrderGenerator; + this.executableHelper = executableHelper; + this.typeResolutionHelper = typeResolutionHelper; + this.valueExtractorManager = valueExtractorManager; + this.parameterNameProvider = parameterNameProvider; + this.methodValidationConfiguration = methodValidationConfiguration; + } + + public static BeanMetaDataBuilder getInstance( + ConstraintHelper constraintHelper, + ExecutableHelper executableHelper, + TypeResolutionHelper typeResolutionHelper, + ValueExtractorManager valueExtractorManager, + ExecutableParameterNameProvider parameterNameProvider, + ValidationOrderGenerator validationOrderGenerator, + Class beanClass, + MethodValidationConfiguration methodValidationConfiguration) { + return new BeanMetaDataBuilder<>( + constraintHelper, + executableHelper, + typeResolutionHelper, + valueExtractorManager, + parameterNameProvider, + validationOrderGenerator, + beanClass, + methodValidationConfiguration ); + } + + public void add(BeanConfiguration configuration) { + if ( configuration.getBeanClass().equals( beanClass ) ) { + if ( configuration.getDefaultGroupSequence() != null + && ( sequenceSource == null || configuration.getSource() + .getPriority() >= sequenceSource.getPriority() ) ) { + + sequenceSource = configuration.getSource(); + defaultGroupSequence = configuration.getDefaultGroupSequence(); + } + + if ( configuration.getDefaultGroupSequenceProvider() != null + && ( providerSource == null || configuration.getSource() + .getPriority() >= providerSource.getPriority() ) ) { + + providerSource = configuration.getSource(); + defaultGroupSequenceProvider = configuration.getDefaultGroupSequenceProvider(); + } + } + + for ( ConstrainedElement constrainedElement : configuration.getConstrainedElements() ) { + addMetaDataToBuilder( constrainedElement, builders ); + } + } + + private void addMetaDataToBuilder(ConstrainedElement constrainableElement, Set builders) { + for ( BuilderDelegate builder : builders ) { + boolean foundBuilder = builder.add( constrainableElement ); + + if ( foundBuilder ) { + return; + } + } + + builders.add( + new BuilderDelegate( + beanClass, + constrainableElement, + constraintHelper, + executableHelper, + typeResolutionHelper, + valueExtractorManager, + parameterNameProvider, + methodValidationConfiguration + ) + ); + } + + public BeanMetaDataImpl build() { + Set aggregatedElements = newHashSet(); + + for ( BuilderDelegate builder : builders ) { + aggregatedElements.addAll( builder.build() ); + } + + return new BeanMetaDataImpl<>( + beanClass, + defaultGroupSequence, + defaultGroupSequenceProvider, + aggregatedElements, + validationOrderGenerator + ); + } + + private static class BuilderDelegate { + private final Class beanClass; + private final ConstrainedElement constrainedElement; + private final ConstraintHelper constraintHelper; + private final ExecutableHelper executableHelper; + private final TypeResolutionHelper typeResolutionHelper; + private final ValueExtractorManager valueExtractorManager; + private final ExecutableParameterNameProvider parameterNameProvider; + private MetaDataBuilder metaDataBuilder; + private ExecutableMetaData.Builder methodBuilder; + private final MethodValidationConfiguration methodValidationConfiguration; + private final int hashCode; + + public BuilderDelegate( + Class beanClass, + ConstrainedElement constrainedElement, + ConstraintHelper constraintHelper, + ExecutableHelper executableHelper, + TypeResolutionHelper typeResolutionHelper, + ValueExtractorManager valueExtractorManager, + ExecutableParameterNameProvider parameterNameProvider, + MethodValidationConfiguration methodValidationConfiguration + ) { + this.beanClass = beanClass; + this.constrainedElement = constrainedElement; + this.constraintHelper = constraintHelper; + this.executableHelper = executableHelper; + this.typeResolutionHelper = typeResolutionHelper; + this.valueExtractorManager = valueExtractorManager; + this.parameterNameProvider = parameterNameProvider; + this.methodValidationConfiguration = methodValidationConfiguration; + + switch ( constrainedElement.getKind() ) { + case FIELD: + ConstrainedField constrainedField = (ConstrainedField) constrainedElement; + metaDataBuilder = new PropertyMetaData.Builder( + beanClass, + constrainedField, + constraintHelper, + typeResolutionHelper, + valueExtractorManager + ); + break; + case CONSTRUCTOR: + case METHOD: + case GETTER: + ConstrainedExecutable constrainedExecutable = (ConstrainedExecutable) constrainedElement; + Callable callable = constrainedExecutable.getCallable(); + + // HV-890 Not adding meta-data for private super-type methods to the method meta-data of this bean; + // It is not needed and it may conflict with sub-type methods of the same signature + if ( !callable.isPrivate() || beanClass == callable.getDeclaringClass() ) { + methodBuilder = new ExecutableMetaData.Builder( + beanClass, + constrainedExecutable, + constraintHelper, + executableHelper, + typeResolutionHelper, + valueExtractorManager, + parameterNameProvider, + methodValidationConfiguration + ); + } + + if ( constrainedElement.getKind() == ConstrainedElement.ConstrainedElementKind.GETTER ) { + metaDataBuilder = new PropertyMetaData.Builder( + beanClass, + constrainedExecutable, + constraintHelper, + typeResolutionHelper, + valueExtractorManager + ); + } + break; + case TYPE: + ConstrainedType constrainedType = (ConstrainedType) constrainedElement; + metaDataBuilder = new ClassMetaData.Builder( + beanClass, + constrainedType, + constraintHelper, + typeResolutionHelper, + valueExtractorManager + ); + break; + default: + throw new IllegalStateException( + StringHelper.format( "Constrained element kind '%1$s' not supported here.", constrainedElement.getKind() ) ); + } + + this.hashCode = buildHashCode(); + } + + public boolean add(ConstrainedElement constrainedElement) { + boolean added = false; + + if ( methodBuilder != null && methodBuilder.accepts( constrainedElement ) ) { + methodBuilder.add( constrainedElement ); + added = true; + } + + if ( metaDataBuilder != null && metaDataBuilder.accepts( constrainedElement ) ) { + metaDataBuilder.add( constrainedElement ); + + if ( !added && constrainedElement.getKind().isMethod() && methodBuilder == null ) { + ConstrainedExecutable constrainedMethod = (ConstrainedExecutable) constrainedElement; + methodBuilder = new ExecutableMetaData.Builder( + beanClass, + constrainedMethod, + constraintHelper, + executableHelper, + typeResolutionHelper, + valueExtractorManager, + parameterNameProvider, + methodValidationConfiguration + ); + } + + added = true; + } + + return added; + } + + public Set build() { + Set metaDataSet = newHashSet(); + + if ( metaDataBuilder != null ) { + metaDataSet.add( metaDataBuilder.build() ); + } + + if ( methodBuilder != null ) { + metaDataSet.add( methodBuilder.build() ); + } + + return metaDataSet; + } + + @Override + public int hashCode() { + return hashCode; + } + + private int buildHashCode() { + final int prime = 31; + int result = 1; + result = prime * result + beanClass.hashCode(); + result = prime * result + constrainedElement.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if ( this == obj ) { + return true; + } + if ( !super.equals( obj ) ) { + return false; + } + if ( getClass() != obj.getClass() ) { + return false; + } + BuilderDelegate other = (BuilderDelegate) obj; + if ( !beanClass.equals( other.beanClass ) ) { + return false; + } + if ( !constrainedElement.equals( other.constrainedElement ) ) { + return false; + } + return true; + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java index 3926d11e81..4fba8e79b7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataImpl.java @@ -27,31 +27,17 @@ import javax.validation.metadata.ConstructorDescriptor; import javax.validation.metadata.PropertyDescriptor; -import org.hibernate.validator.internal.engine.MethodValidationConfiguration; import org.hibernate.validator.internal.engine.groups.Sequence; import org.hibernate.validator.internal.engine.groups.ValidationOrder; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.descriptor.BeanDescriptorImpl; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.descriptor.ExecutableDescriptorImpl; import org.hibernate.validator.internal.metadata.facets.Cascadable; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; -import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; -import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; -import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; -import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; -import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; -import org.hibernate.validator.internal.metadata.raw.ConstrainedField; -import org.hibernate.validator.internal.metadata.raw.ConstrainedType; -import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.ExecutableHelper; -import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; -import org.hibernate.validator.internal.util.StringHelper; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper; import org.hibernate.validator.internal.util.classhierarchy.Filters; import org.hibernate.validator.internal.util.logging.Log; @@ -68,6 +54,7 @@ * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI * @author Chris Beckey <cbeckey@paypal.com> * @author Guillaume Smet + * @author Marko Bekhta */ public final class BeanMetaDataImpl implements BeanMetaData { @@ -267,7 +254,7 @@ public BeanDescriptor getBeanDescriptor() { BeanDescriptor beanDescriptor = this.beanDescriptor; if ( beanDescriptor == null ) { - synchronized ( this ) { + synchronized (this) { beanDescriptor = this.beanDescriptor; if ( beanDescriptor == null ) { @@ -349,9 +336,9 @@ public Iterator getDefaultValidationSequence(T beanState) { if ( hasDefaultGroupSequenceProvider() ) { List> providerDefaultGroupSequence = defaultGroupSequenceProvider.getValidationGroups( beanState ); return validationOrderGenerator.getDefaultValidationOrder( - beanClass, - getValidDefaultGroupSequence( beanClass, providerDefaultGroupSequence ) - ) + beanClass, + getValidDefaultGroupSequence( beanClass, providerDefaultGroupSequence ) + ) .getSequenceIterator(); } else { @@ -435,9 +422,9 @@ private static Map getConstrainedMethodsAsDesc if ( executableMetaData.getKind() == ElementKind.METHOD && executableMetaData.isConstrained() ) { ExecutableDescriptorImpl descriptor = executableMetaData.asDescriptor( - defaultGroupSequenceIsRedefined, - resolvedDefaultGroupSequence - ); + defaultGroupSequenceIsRedefined, + resolvedDefaultGroupSequence + ); for ( String signature : executableMetaData.getSignatures() ) { constrainedMethodDescriptors.put( signature, descriptor ); @@ -571,299 +558,6 @@ public String toString() { + ", defaultGroupSequence=" + getDefaultGroupSequence( null ) + '}'; } - public static class BeanMetaDataBuilder { - - private final ConstraintHelper constraintHelper; - private final ValidationOrderGenerator validationOrderGenerator; - private final Class beanClass; - private final Set builders = newHashSet(); - private final ExecutableHelper executableHelper; - private final TypeResolutionHelper typeResolutionHelper; - private final ValueExtractorManager valueExtractorManager; - private final ExecutableParameterNameProvider parameterNameProvider; - private final MethodValidationConfiguration methodValidationConfiguration; - - private ConfigurationSource sequenceSource; - private ConfigurationSource providerSource; - private List> defaultGroupSequence; - private DefaultGroupSequenceProvider defaultGroupSequenceProvider; - - - private BeanMetaDataBuilder( - ConstraintHelper constraintHelper, - ExecutableHelper executableHelper, - TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager, - ExecutableParameterNameProvider parameterNameProvider, - ValidationOrderGenerator validationOrderGenerator, - Class beanClass, - MethodValidationConfiguration methodValidationConfiguration) { - this.beanClass = beanClass; - this.constraintHelper = constraintHelper; - this.validationOrderGenerator = validationOrderGenerator; - this.executableHelper = executableHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; - this.parameterNameProvider = parameterNameProvider; - this.methodValidationConfiguration = methodValidationConfiguration; - } - - public static BeanMetaDataBuilder getInstance( - ConstraintHelper constraintHelper, - ExecutableHelper executableHelper, - TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager, - ExecutableParameterNameProvider parameterNameProvider, - ValidationOrderGenerator validationOrderGenerator, - Class beanClass, - MethodValidationConfiguration methodValidationConfiguration) { - return new BeanMetaDataBuilder<>( - constraintHelper, - executableHelper, - typeResolutionHelper, - valueExtractorManager, - parameterNameProvider, - validationOrderGenerator, - beanClass, - methodValidationConfiguration ); - } - - public void add(BeanConfiguration configuration) { - if ( configuration.getBeanClass().equals( beanClass ) ) { - if ( configuration.getDefaultGroupSequence() != null - && ( sequenceSource == null || configuration.getSource() - .getPriority() >= sequenceSource.getPriority() ) ) { - - sequenceSource = configuration.getSource(); - defaultGroupSequence = configuration.getDefaultGroupSequence(); - } - - if ( configuration.getDefaultGroupSequenceProvider() != null - && ( providerSource == null || configuration.getSource() - .getPriority() >= providerSource.getPriority() ) ) { - - providerSource = configuration.getSource(); - defaultGroupSequenceProvider = configuration.getDefaultGroupSequenceProvider(); - } - } - - for ( ConstrainedElement constrainedElement : configuration.getConstrainedElements() ) { - addMetaDataToBuilder( constrainedElement, builders ); - } - } - - private void addMetaDataToBuilder(ConstrainedElement constrainableElement, Set builders) { - for ( BuilderDelegate builder : builders ) { - boolean foundBuilder = builder.add( constrainableElement ); - - if ( foundBuilder ) { - return; - } - } - - builders.add( - new BuilderDelegate( - beanClass, - constrainableElement, - constraintHelper, - executableHelper, - typeResolutionHelper, - valueExtractorManager, - parameterNameProvider, - methodValidationConfiguration - ) - ); - } - - public BeanMetaDataImpl build() { - Set aggregatedElements = newHashSet(); - - for ( BuilderDelegate builder : builders ) { - aggregatedElements.addAll( builder.build() ); - } - - return new BeanMetaDataImpl<>( - beanClass, - defaultGroupSequence, - defaultGroupSequenceProvider, - aggregatedElements, - validationOrderGenerator - ); - } - } - - private static class BuilderDelegate { - private final Class beanClass; - private final ConstrainedElement constrainedElement; - private final ConstraintHelper constraintHelper; - private final ExecutableHelper executableHelper; - private final TypeResolutionHelper typeResolutionHelper; - private final ValueExtractorManager valueExtractorManager; - private final ExecutableParameterNameProvider parameterNameProvider; - private MetaDataBuilder metaDataBuilder; - private ExecutableMetaData.Builder methodBuilder; - private final MethodValidationConfiguration methodValidationConfiguration; - private final int hashCode; - - public BuilderDelegate( - Class beanClass, - ConstrainedElement constrainedElement, - ConstraintHelper constraintHelper, - ExecutableHelper executableHelper, - TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager, - ExecutableParameterNameProvider parameterNameProvider, - MethodValidationConfiguration methodValidationConfiguration - ) { - this.beanClass = beanClass; - this.constrainedElement = constrainedElement; - this.constraintHelper = constraintHelper; - this.executableHelper = executableHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; - this.parameterNameProvider = parameterNameProvider; - this.methodValidationConfiguration = methodValidationConfiguration; - - switch ( constrainedElement.getKind() ) { - case FIELD: - ConstrainedField constrainedField = (ConstrainedField) constrainedElement; - metaDataBuilder = new PropertyMetaData.Builder( - beanClass, - constrainedField, - constraintHelper, - typeResolutionHelper, - valueExtractorManager - ); - break; - case CONSTRUCTOR: - case METHOD: - case GETTER: - ConstrainedExecutable constrainedExecutable = (ConstrainedExecutable) constrainedElement; - Callable callable = constrainedExecutable.getCallable(); - - // HV-890 Not adding meta-data for private super-type methods to the method meta-data of this bean; - // It is not needed and it may conflict with sub-type methods of the same signature - if ( !callable.isPrivate() || beanClass == callable.getDeclaringClass() ) { - methodBuilder = new ExecutableMetaData.Builder( - beanClass, - constrainedExecutable, - constraintHelper, - executableHelper, - typeResolutionHelper, - valueExtractorManager, - parameterNameProvider, - methodValidationConfiguration - ); - } - - if ( constrainedElement.getKind() == ConstrainedElementKind.GETTER ) { - metaDataBuilder = new PropertyMetaData.Builder( - beanClass, - constrainedExecutable, - constraintHelper, - typeResolutionHelper, - valueExtractorManager - ); - } - break; - case TYPE: - ConstrainedType constrainedType = (ConstrainedType) constrainedElement; - metaDataBuilder = new ClassMetaData.Builder( - beanClass, - constrainedType, - constraintHelper, - typeResolutionHelper, - valueExtractorManager - ); - break; - default: - throw new IllegalStateException( - StringHelper.format( "Constrained element kind '%1$s' not supported here.", constrainedElement.getKind() ) ); - } - - this.hashCode = buildHashCode(); - } - - public boolean add(ConstrainedElement constrainedElement) { - boolean added = false; - - if ( methodBuilder != null && methodBuilder.accepts( constrainedElement ) ) { - methodBuilder.add( constrainedElement ); - added = true; - } - - if ( metaDataBuilder != null && metaDataBuilder.accepts( constrainedElement ) ) { - metaDataBuilder.add( constrainedElement ); - - if ( !added && constrainedElement.getKind().isMethod() && methodBuilder == null ) { - ConstrainedExecutable constrainedMethod = (ConstrainedExecutable) constrainedElement; - methodBuilder = new ExecutableMetaData.Builder( - beanClass, - constrainedMethod, - constraintHelper, - executableHelper, - typeResolutionHelper, - valueExtractorManager, - parameterNameProvider, - methodValidationConfiguration - ); - } - - added = true; - } - - return added; - } - - public Set build() { - Set metaDataSet = newHashSet(); - - if ( metaDataBuilder != null ) { - metaDataSet.add( metaDataBuilder.build() ); - } - - if ( methodBuilder != null ) { - metaDataSet.add( methodBuilder.build() ); - } - - return metaDataSet; - } - - @Override - public int hashCode() { - return hashCode; - } - - private int buildHashCode() { - final int prime = 31; - int result = 1; - result = prime * result + beanClass.hashCode(); - result = prime * result + constrainedElement.hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if ( this == obj ) { - return true; - } - if ( !super.equals( obj ) ) { - return false; - } - if ( getClass() != obj.getClass() ) { - return false; - } - BuilderDelegate other = (BuilderDelegate) obj; - if ( !beanClass.equals( other.beanClass ) ) { - return false; - } - if ( !constrainedElement.equals( other.constrainedElement ) ) { - return false; - } - return true; - } - } - /** * Tuple for returning default group sequence, provider and validation order at once. */ From 6556e4eaa5bd6692a5e3deaa00c7f27c3dfd16bb Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 8 Nov 2018 00:05:02 +0100 Subject: [PATCH 129/393] Improve README.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index edaad42681..5edbad0403 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This is the reference implementation of [JSR-380 - Bean Validation 2.0](http://beanvalidation.org/). Bean Validation defines a metadata model and API for JavaBean as well as method validation. The default metadata source are annotations, with the ability to override and extend -the meta-data through the use of XML validation descriptors. +the metadata through the use of XML validation descriptors. ## Documentation @@ -20,7 +20,7 @@ The full list of changes for this release can be found in changelog.txt. ## System Requirements -JDK 1.8 or above. +JDK 8 or above. ## Using Hibernate Validator @@ -30,7 +30,7 @@ the JBoss Logging API, an abstraction layer which supports several logging solut provided by the JDK) as implementation. Just add a supported logging library to the classpath (e.g. _log4j-<version>.jar_) and JBoss Logging will delegate any log requests to that provider. -* Add the following to your Maven or Ivy dependency list +* Add the following artifact to your Maven/Ivy/Gradle dependency list: org.hibernate.validator @@ -68,10 +68,10 @@ the Apache Software License 2.0. Refer to license.txt for more information. ## Build from Source -You can build Hibernate Validator from source by cloning the git repository git://github.com/hibernate/hibernate-validator.git. -You will also need a JDK 8 and Maven 3 (>= 3.3.1). With these prerequisites in place you can compile the source via: +You can build Hibernate Validator from source by cloning the git repository `git://github.com/hibernate/hibernate-validator.git`. +You will also need a JDK 8+ and Maven 3 (>= 3.3.1). With these prerequisites in place you can compile the source via: - mvn -s settings-example.xml clean install + mvn clean install There are more build options available as well. For more information refer to [Contributing to Hibernate Validator](http://hibernate.org/validator/contribute/). From ef1c133dfc3a31bdb206f1f960cb40136e0a5c81 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 29 Nov 2018 14:26:24 +0100 Subject: [PATCH 130/393] HV-1668 Properly register all built-in constraints Before this commit, purely composed constraints were not declared in the list of built-in constraints as it was not useful. --- .../metadata/core/ConstraintHelper.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java index 7858874584..6a227e8d83 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java @@ -55,6 +55,7 @@ import org.hibernate.validator.constraints.CodePointLength; import org.hibernate.validator.constraints.ConstraintComposition; +import org.hibernate.validator.constraints.CreditCardNumber; import org.hibernate.validator.constraints.Currency; import org.hibernate.validator.constraints.EAN; import org.hibernate.validator.constraints.ISBN; @@ -64,12 +65,14 @@ import org.hibernate.validator.constraints.Mod11Check; import org.hibernate.validator.constraints.ModCheck; import org.hibernate.validator.constraints.ParameterScriptAssert; +import org.hibernate.validator.constraints.Range; import org.hibernate.validator.constraints.SafeHtml; import org.hibernate.validator.constraints.ScriptAssert; import org.hibernate.validator.constraints.URL; import org.hibernate.validator.constraints.UniqueElements; import org.hibernate.validator.constraints.br.CNPJ; import org.hibernate.validator.constraints.br.CPF; +import org.hibernate.validator.constraints.br.TituloEleitoral; import org.hibernate.validator.constraints.pl.NIP; import org.hibernate.validator.constraints.pl.PESEL; import org.hibernate.validator.constraints.pl.REGON; @@ -418,8 +421,6 @@ public ConstraintHelper() { putConstraints( tmpConstraints, FutureOrPresent.class, futureOrPresentValidators ); - putConstraint( tmpConstraints, ISBN.class, ISBNValidator.class ); - if ( isJavaMoneyInClasspath() ) { putConstraints( tmpConstraints, Max.class, Arrays.asList( MaxValidatorForBigDecimal.class, @@ -657,29 +658,39 @@ public ConstraintHelper() { if ( isJavaMoneyInClasspath() ) { putConstraint( tmpConstraints, Currency.class, CurrencyValidatorForMonetaryAmount.class ); } + putConstraint( tmpConstraints, CreditCardNumber.class ); putConstraint( tmpConstraints, DurationMax.class, DurationMaxValidator.class ); putConstraint( tmpConstraints, DurationMin.class, DurationMinValidator.class ); putConstraint( tmpConstraints, EAN.class, EANValidator.class ); putConstraint( tmpConstraints, org.hibernate.validator.constraints.Email.class, org.hibernate.validator.internal.constraintvalidators.hv.EmailValidator.class ); + putConstraint( tmpConstraints, ISBN.class, ISBNValidator.class ); putConstraint( tmpConstraints, Length.class, LengthValidator.class ); putConstraint( tmpConstraints, CodePointLength.class, CodePointLengthValidator.class ); - putConstraint( tmpConstraints, ModCheck.class, ModCheckValidator.class ); putConstraint( tmpConstraints, LuhnCheck.class, LuhnCheckValidator.class ); + putConstraint( tmpConstraints, ModCheck.class, ModCheckValidator.class ); putConstraint( tmpConstraints, Mod10Check.class, Mod10CheckValidator.class ); putConstraint( tmpConstraints, Mod11Check.class, Mod11CheckValidator.class ); - putConstraint( tmpConstraints, REGON.class, REGONValidator.class ); putConstraint( tmpConstraints, NIP.class, NIPValidator.class ); - putConstraint( tmpConstraints, PESEL.class, PESELValidator.class ); putConstraint( tmpConstraints, org.hibernate.validator.constraints.NotBlank.class, org.hibernate.validator.internal.constraintvalidators.hv.NotBlankValidator.class ); + putConstraint( tmpConstraints, org.hibernate.validator.constraints.NotEmpty.class ); putConstraint( tmpConstraints, ParameterScriptAssert.class, ParameterScriptAssertValidator.class ); + putConstraint( tmpConstraints, PESEL.class, PESELValidator.class ); + putConstraint( tmpConstraints, Range.class ); + putConstraint( tmpConstraints, REGON.class, REGONValidator.class ); putConstraint( tmpConstraints, SafeHtml.class, SafeHtmlValidator.class ); putConstraint( tmpConstraints, ScriptAssert.class, ScriptAssertValidator.class ); + putConstraint( tmpConstraints, TituloEleitoral.class ); putConstraint( tmpConstraints, UniqueElements.class, UniqueElementsValidator.class ); putConstraint( tmpConstraints, URL.class, URLValidator.class ); this.builtinConstraints = Collections.unmodifiableMap( tmpConstraints ); } + private static
void putConstraint(Map, List>> validators, + Class constraintType) { + validators.put( constraintType, Collections.emptyList() ); + } + private static void putConstraint(Map, List>> validators, Class constraintType, Class> validatorType) { validators.put( constraintType, Collections.singletonList( ConstraintValidatorDescriptor.forClass( validatorType, constraintType ) ) ); From 3dfc59b77677dbae708a15e9157dc26426e8f5be Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 30 Nov 2018 14:26:17 +0100 Subject: [PATCH 131/393] HV-1671 Allow to retrieve the built-in constraints from ConstraintHelper --- .../validator/internal/metadata/core/ConstraintHelper.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java index 6a227e8d83..219ecce4a1 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java @@ -19,6 +19,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.function.Function; @@ -721,6 +722,10 @@ private boolean isBuiltinConstraint(Class annotationType) return builtinConstraints.containsKey( annotationType ); } + public Set> getBuiltinConstraints() { + return CollectionHelper.toImmutableSet( builtinConstraints.keySet() ); + } + /** * Returns the constraint validator classes for the given constraint * annotation type, as retrieved from From 76cec77b9b275e7c7ad4f49aa8e5d648b22c55d1 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 30 Nov 2018 16:04:01 +0100 Subject: [PATCH 132/393] HV-1669 Only enable the SafeHtml constraint if jsoup is in the classpath --- .../internal/metadata/core/ConstraintHelper.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java index 219ecce4a1..d7502ee3de 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java @@ -307,6 +307,7 @@ public class ConstraintHelper { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); private static final String JODA_TIME_CLASS_NAME = "org.joda.time.ReadableInstant"; private static final String JAVA_MONEY_CLASS_NAME = "javax.money.MonetaryAmount"; + private static final String JSOUP_CLASS_NAME = "org.jsoup.Jsoup"; @Immutable private final Map, List>> builtinConstraints; @@ -678,7 +679,9 @@ public ConstraintHelper() { putConstraint( tmpConstraints, PESEL.class, PESELValidator.class ); putConstraint( tmpConstraints, Range.class ); putConstraint( tmpConstraints, REGON.class, REGONValidator.class ); - putConstraint( tmpConstraints, SafeHtml.class, SafeHtmlValidator.class ); + if ( isJsoupInClasspath() ) { + putConstraint( tmpConstraints, SafeHtml.class, SafeHtmlValidator.class ); + } putConstraint( tmpConstraints, ScriptAssert.class, ScriptAssertValidator.class ); putConstraint( tmpConstraints, TituloEleitoral.class ); putConstraint( tmpConstraints, UniqueElements.class, UniqueElementsValidator.class ); @@ -994,6 +997,10 @@ private static boolean isJavaMoneyInClasspath() { return isClassPresent( JAVA_MONEY_CLASS_NAME ); } + private static boolean isJsoupInClasspath() { + return isClassPresent( JSOUP_CLASS_NAME ); + } + /** * Returns the default validators for the given constraint type. * From 17bc804a3ff2476e8828a1da0a5366bd3080d25b Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 5 Dec 2018 15:05:09 +0100 Subject: [PATCH 133/393] HV-1674 Make the name of the default bundle public in AbstractMessageInterpolator --- .../messageinterpolation/AbstractMessageInterpolator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java index 2143a4adfc..7830f2935e 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java @@ -65,7 +65,7 @@ public abstract class AbstractMessageInterpolator implements MessageInterpolator /** * The name of the default message bundle. */ - private static final String DEFAULT_VALIDATION_MESSAGES = "org.hibernate.validator.ValidationMessages"; + public static final String DEFAULT_VALIDATION_MESSAGES = "org.hibernate.validator.ValidationMessages"; /** * The name of the user-provided message bundle as defined in the specification. From 946634e07c93e567ccb6ca40a058f187aa603e08 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Sun, 2 Dec 2018 17:57:47 +0100 Subject: [PATCH 134/393] HV-1665 Make AP isolating and incremental. Update the doc on AP and Gradle As per Gradle doc on incremental AP(https://docs.gradle.org/nightly/userguide/java_plugin.html#making_an_annotation_processor_incremental) it should be enough to register AP in META-INF/gradle/incremental.annotation.processors with corresponding category separated by a comma. Also added a small section to documentation on AP and Gradle. --- .../gradle/incremental.annotation.processors | 1 + documentation/src/main/asciidoc/ch13.asciidoc | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 annotation-processor/src/main/resources/META-INF/services/gradle/incremental.annotation.processors diff --git a/annotation-processor/src/main/resources/META-INF/services/gradle/incremental.annotation.processors b/annotation-processor/src/main/resources/META-INF/services/gradle/incremental.annotation.processors new file mode 100644 index 0000000000..7148eed480 --- /dev/null +++ b/annotation-processor/src/main/resources/META-INF/services/gradle/incremental.annotation.processors @@ -0,0 +1 @@ +org.hibernate.validator.ap.ConstraintValidationProcessor,isolating diff --git a/documentation/src/main/asciidoc/ch13.asciidoc b/documentation/src/main/asciidoc/ch13.asciidoc index 94b266138b..c352b8c4bf 100644 --- a/documentation/src/main/asciidoc/ch13.asciidoc +++ b/documentation/src/main/asciidoc/ch13.asciidoc @@ -116,6 +116,24 @@ For using the Hibernate Validator annotation processor with Maven, set it up via ---- ==== +[[validator-annotationprocessor-gradle]] +===== Gradle + +When using https://gradle.org[Gradle] it is enough to reference the annotation processor as an `annotationProcessor` dependency. + +.Using the annotation processor with Gradle +==== +[source, groovy] +[subs="verbatim,attributes"] +---- +dependencies { + annotationProcessor group: 'org.hibernate.validator', name: 'hibernate-validator-annotation-processor', version: '{hvVersion}' + + // any other dependencies ... +} +---- +==== + [[validator-annotationprocessor-ant]] ===== Apache Ant From a5f116bb6b023e24ca6196f864a98f661afcf2b2 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 27 Nov 2018 11:32:43 +0100 Subject: [PATCH 135/393] HV-1667 Simplify ValidatorFactoryImpl --- .../internal/engine/ValidatorContextImpl.java | 1 - .../ValidatorFactoryConfigurationHelper.java | 348 +++++++++++ .../internal/engine/ValidatorFactoryImpl.java | 583 +----------------- .../engine/ValidatorFactoryScopedContext.java | 273 ++++++++ .../internal/engine/ValidatorImpl.java | 1 - .../ValidatorScopedContext.java | 4 +- 6 files changed, 636 insertions(+), 574 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryScopedContext.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorContextImpl.java index 38b4b8b405..5ee8cba70f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorContextImpl.java @@ -20,7 +20,6 @@ import javax.validation.valueextraction.ValueExtractor; import org.hibernate.validator.HibernateValidatorContext; -import org.hibernate.validator.internal.engine.ValidatorFactoryImpl.ValidatorFactoryScopedContext; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorDescriptor; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.util.logging.Log; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java new file mode 100644 index 0000000000..49289c5234 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java @@ -0,0 +1,348 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine; + +import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; +import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; + +import java.lang.annotation.Annotation; +import java.lang.invoke.MethodHandles; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.time.Duration; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.validation.spi.ConfigurationState; + +import org.hibernate.validator.HibernateValidatorConfiguration; +import org.hibernate.validator.cfg.ConstraintMapping; +import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping; +import org.hibernate.validator.internal.engine.constraintdefinition.ConstraintDefinitionContribution; +import org.hibernate.validator.internal.engine.scripting.DefaultScriptEvaluatorFactory; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; +import org.hibernate.validator.internal.util.StringHelper; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader; +import org.hibernate.validator.internal.util.privilegedactions.LoadClass; +import org.hibernate.validator.internal.util.privilegedactions.NewInstance; +import org.hibernate.validator.spi.cfg.ConstraintMappingContributor; +import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; +import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; + +final class ValidatorFactoryConfigurationHelper { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + private ValidatorFactoryConfigurationHelper() { + } + + static ClassLoader getExternalClassLoader(ConfigurationState configurationState) { + return ( configurationState instanceof ConfigurationImpl ) ? ( (ConfigurationImpl) configurationState ).getExternalClassLoader() : null; + } + + static Set getConstraintMappings(TypeResolutionHelper typeResolutionHelper, + ConfigurationState configurationState, JavaBeanHelper javaBeanHelper, ClassLoader externalClassLoader) { + Set constraintMappings = newHashSet(); + + if ( configurationState instanceof ConfigurationImpl ) { + ConfigurationImpl hibernateConfiguration = (ConfigurationImpl) configurationState; + + // programmatic config + /* We add these first so that constraint mapping created through DefaultConstraintMappingBuilder will take + * these programmatically defined mappings into account when checking for constraint definition uniqueness + */ + constraintMappings.addAll( hibernateConfiguration.getProgrammaticMappings() ); + + // service loader based config + ConstraintMappingContributor serviceLoaderBasedContributor = new ServiceLoaderBasedConstraintMappingContributor( + typeResolutionHelper, + externalClassLoader != null ? externalClassLoader : run( GetClassLoader.fromContext() ) ); + DefaultConstraintMappingBuilder builder = new DefaultConstraintMappingBuilder( javaBeanHelper, constraintMappings ); + serviceLoaderBasedContributor.createConstraintMappings( builder ); + } + + // XML-defined constraint mapping contributors + List contributors = getPropertyConfiguredConstraintMappingContributors( configurationState.getProperties(), + externalClassLoader ); + + for ( ConstraintMappingContributor contributor : contributors ) { + DefaultConstraintMappingBuilder builder = new DefaultConstraintMappingBuilder( javaBeanHelper, constraintMappings ); + contributor.createConstraintMappings( builder ); + } + + return constraintMappings; + } + + static boolean checkPropertiesForBoolean(Map properties, String propertyKey, boolean programmaticValue) { + boolean value = programmaticValue; + String propertyStringValue = properties.get( propertyKey ); + if ( propertyStringValue != null ) { + value = Boolean.valueOf( propertyStringValue ); + } + return value; + } + + /** + * Returns a list with {@link ConstraintMappingContributor}s configured via the + * {@link HibernateValidatorConfiguration#CONSTRAINT_MAPPING_CONTRIBUTORS} property. + * + * Also takes into account the deprecated {@link HibernateValidatorConfiguration#CONSTRAINT_MAPPING_CONTRIBUTOR} + * property. + * + * @param properties the properties used to bootstrap the factory + * + * @return a list with property-configured {@link ConstraintMappingContributor}s; May be empty but never {@code null} + */ + static List getPropertyConfiguredConstraintMappingContributors( + Map properties, ClassLoader externalClassLoader) { + @SuppressWarnings("deprecation") + String deprecatedPropertyValue = properties.get( HibernateValidatorConfiguration.CONSTRAINT_MAPPING_CONTRIBUTOR ); + String propertyValue = properties.get( HibernateValidatorConfiguration.CONSTRAINT_MAPPING_CONTRIBUTORS ); + + if ( StringHelper.isNullOrEmptyString( deprecatedPropertyValue ) && StringHelper.isNullOrEmptyString( propertyValue ) ) { + return Collections.emptyList(); + } + + StringBuilder assembledPropertyValue = new StringBuilder(); + if ( !StringHelper.isNullOrEmptyString( deprecatedPropertyValue ) ) { + assembledPropertyValue.append( deprecatedPropertyValue ); + } + if ( !StringHelper.isNullOrEmptyString( propertyValue ) ) { + if ( assembledPropertyValue.length() > 0 ) { + assembledPropertyValue.append( "," ); + } + assembledPropertyValue.append( propertyValue ); + } + + String[] contributorNames = assembledPropertyValue.toString().split( "," ); + List contributors = newArrayList( contributorNames.length ); + + for ( String contributorName : contributorNames ) { + @SuppressWarnings("unchecked") + Class contributorType = (Class) run( + LoadClass.action( contributorName, externalClassLoader ) ); + contributors.add( run( NewInstance.action( contributorType, "constraint mapping contributor class" ) ) ); + } + + return contributors; + } + + static boolean getAllowParallelMethodsDefineParameterConstraints(ConfigurationImpl hibernateSpecificConfig, Map properties) { + return checkPropertiesForBoolean( + properties, + HibernateValidatorConfiguration.ALLOW_PARALLEL_METHODS_DEFINE_PARAMETER_CONSTRAINTS, + hibernateSpecificConfig != null ? hibernateSpecificConfig.getMethodValidationConfiguration().isAllowParallelMethodsDefineParameterConstraints() : false + ); + } + + static boolean getAllowMultipleCascadedValidationOnReturnValues(ConfigurationImpl hibernateSpecificConfig, Map properties) { + return checkPropertiesForBoolean( + properties, + HibernateValidatorConfiguration.ALLOW_MULTIPLE_CASCADED_VALIDATION_ON_RESULT, + hibernateSpecificConfig != null ? hibernateSpecificConfig.getMethodValidationConfiguration().isAllowMultipleCascadedValidationOnReturnValues() : false + ); + } + + static boolean getAllowOverridingMethodAlterParameterConstraint(ConfigurationImpl hibernateSpecificConfig, Map properties) { + return checkPropertiesForBoolean( + properties, + HibernateValidatorConfiguration.ALLOW_PARAMETER_CONSTRAINT_OVERRIDE, + hibernateSpecificConfig != null ? hibernateSpecificConfig.getMethodValidationConfiguration().isAllowOverridingMethodAlterParameterConstraint() : false + ); + } + + static boolean getTraversableResolverResultCacheEnabled(ConfigurationImpl configuration, Map properties) { + return checkPropertiesForBoolean( + properties, + HibernateValidatorConfiguration.ENABLE_TRAVERSABLE_RESOLVER_RESULT_CACHE, + configuration != null ? configuration.isTraversableResolverResultCacheEnabled() : true + ); + } + + static boolean getFailFast(ConfigurationImpl configuration, Map properties) { + // check whether fail fast is programmatically enabled + boolean tmpFailFast = configuration != null ? configuration.getFailFast() : false; + + String propertyStringValue = properties.get( HibernateValidatorConfiguration.FAIL_FAST ); + if ( propertyStringValue != null ) { + boolean configurationValue = Boolean.valueOf( propertyStringValue ); + // throw an exception if the programmatic value is true and it overrides a false configured value + if ( tmpFailFast && !configurationValue ) { + throw LOG.getInconsistentFailFastConfigurationException(); + } + tmpFailFast = configurationValue; + } + + return tmpFailFast; + } + + static ScriptEvaluatorFactory getScriptEvaluatorFactory(ConfigurationState configurationState, Map properties, + ClassLoader externalClassLoader) { + if ( configurationState instanceof ConfigurationImpl ) { + ConfigurationImpl hibernateSpecificConfig = (ConfigurationImpl) configurationState; + if ( hibernateSpecificConfig.getScriptEvaluatorFactory() != null ) { + LOG.usingScriptEvaluatorFactory( hibernateSpecificConfig.getScriptEvaluatorFactory().getClass() ); + return hibernateSpecificConfig.getScriptEvaluatorFactory(); + } + } + + String scriptEvaluatorFactoryFqcn = properties.get( HibernateValidatorConfiguration.SCRIPT_EVALUATOR_FACTORY_CLASSNAME ); + if ( scriptEvaluatorFactoryFqcn != null ) { + try { + @SuppressWarnings("unchecked") + Class clazz = (Class) run( + LoadClass.action( scriptEvaluatorFactoryFqcn, externalClassLoader ) + ); + ScriptEvaluatorFactory scriptEvaluatorFactory = run( NewInstance.action( clazz, "script evaluator factory class" ) ); + LOG.usingScriptEvaluatorFactory( clazz ); + + return scriptEvaluatorFactory; + } + catch (Exception e) { + throw LOG.getUnableToInstantiateScriptEvaluatorFactoryClassException( scriptEvaluatorFactoryFqcn, e ); + } + } + + return new DefaultScriptEvaluatorFactory( externalClassLoader ); + } + + static Duration getTemporalValidationTolerance(ConfigurationState configurationState, Map properties) { + if ( configurationState instanceof ConfigurationImpl ) { + ConfigurationImpl hibernateSpecificConfig = (ConfigurationImpl) configurationState; + if ( hibernateSpecificConfig.getTemporalValidationTolerance() != null ) { + LOG.logTemporalValidationTolerance( hibernateSpecificConfig.getTemporalValidationTolerance() ); + return hibernateSpecificConfig.getTemporalValidationTolerance(); + } + } + String temporalValidationToleranceProperty = properties.get( HibernateValidatorConfiguration.TEMPORAL_VALIDATION_TOLERANCE ); + if ( temporalValidationToleranceProperty != null ) { + try { + Duration tolerance = Duration.ofMillis( Long.parseLong( temporalValidationToleranceProperty ) ).abs(); + LOG.logTemporalValidationTolerance( tolerance ); + return tolerance; + } + catch (Exception e) { + throw LOG.getUnableToParseTemporalValidationToleranceException( temporalValidationToleranceProperty, e ); + } + } + + return Duration.ZERO; + } + + static Object getConstraintValidatorPayload(ConfigurationState configurationState) { + if ( configurationState instanceof ConfigurationImpl ) { + ConfigurationImpl hibernateSpecificConfig = (ConfigurationImpl) configurationState; + if ( hibernateSpecificConfig.getConstraintValidatorPayload() != null ) { + LOG.logConstraintValidatorPayload( hibernateSpecificConfig.getConstraintValidatorPayload() ); + return hibernateSpecificConfig.getConstraintValidatorPayload(); + } + } + + return null; + } + + static GetterPropertySelectionStrategy getGetterPropertySelectionStrategy(ConfigurationImpl hibernateSpecificConfig, Map properties, + ClassLoader externalClassLoader) { + if ( hibernateSpecificConfig.getGetterPropertySelectionStrategy() != null ) { + LOG.usingGetterPropertySelectionStrategy( hibernateSpecificConfig.getGetterPropertySelectionStrategy().getClass() ); + return hibernateSpecificConfig.getGetterPropertySelectionStrategy(); + } + + String getterPropertySelectionStrategyFqcn = properties.get( HibernateValidatorConfiguration.GETTER_PROPERTY_SELECTION_STRATEGY_CLASSNAME ); + if ( getterPropertySelectionStrategyFqcn != null ) { + try { + @SuppressWarnings("unchecked") + Class clazz = (Class) run( + LoadClass.action( getterPropertySelectionStrategyFqcn, externalClassLoader ) + ); + GetterPropertySelectionStrategy getterPropertySelectionStrategy = run( NewInstance.action( clazz, "getter property selection strategy class" ) ); + LOG.usingGetterPropertySelectionStrategy( clazz ); + + return getterPropertySelectionStrategy; + } + catch (Exception e) { + throw LOG.getUnableToInstantiateGetterPropertySelectionStrategyClassException( getterPropertySelectionStrategyFqcn, e ); + } + } + + return new DefaultGetterPropertySelectionStrategy(); + } + + static void registerCustomConstraintValidators(Set constraintMappings, + ConstraintHelper constraintHelper) { + Set> definedConstraints = newHashSet(); + for ( DefaultConstraintMapping constraintMapping : constraintMappings ) { + for ( ConstraintDefinitionContribution contribution : constraintMapping.getConstraintDefinitionContributions() ) { + processConstraintDefinitionContribution( contribution, constraintHelper, definedConstraints ); + } + } + } + + static void processConstraintDefinitionContribution( + ConstraintDefinitionContribution constraintDefinitionContribution, ConstraintHelper constraintHelper, + Set> definedConstraints) { + Class constraintType = constraintDefinitionContribution.getConstraintType(); + if ( definedConstraints.contains( constraintType ) ) { + throw LOG.getConstraintHasAlreadyBeenConfiguredViaProgrammaticApiException( constraintType ); + } + definedConstraints.add( constraintType ); + constraintHelper.putValidatorDescriptors( + constraintType, + constraintDefinitionContribution.getValidatorDescriptors(), + constraintDefinitionContribution.includeExisting() + ); + } + + static void logValidatorFactoryScopedConfiguration(ValidatorFactoryScopedContext context) { + LOG.logValidatorFactoryScopedConfiguration( context.getMessageInterpolator().getClass(), "message interpolator" ); + LOG.logValidatorFactoryScopedConfiguration( context.getTraversableResolver().getClass(), "traversable resolver" ); + LOG.logValidatorFactoryScopedConfiguration( context.getParameterNameProvider().getClass(), "parameter name provider" ); + LOG.logValidatorFactoryScopedConfiguration( context.getClockProvider().getClass(), "clock provider" ); + LOG.logValidatorFactoryScopedConfiguration( context.getScriptEvaluatorFactory().getClass(), "script evaluator factory" ); + } + + /** + * Runs the given privileged action, using a privileged block if required. + *

+ * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary + * privileged actions within HV's protection domain. + */ + private static T run(PrivilegedAction action) { + return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); + } + + /** + * The one and only {@link ConstraintMappingContributor.ConstraintMappingBuilder} implementation. + */ + private static class DefaultConstraintMappingBuilder + implements ConstraintMappingContributor.ConstraintMappingBuilder { + + private final JavaBeanHelper javaBeanHelper; + private final Set mappings; + + public DefaultConstraintMappingBuilder(JavaBeanHelper javaBeanHelper, Set mappings) { + this.javaBeanHelper = javaBeanHelper; + this.mappings = mappings; + } + + @Override + public ConstraintMapping addConstraintMapping() { + DefaultConstraintMapping mapping = new DefaultConstraintMapping( javaBeanHelper ); + mappings.add( mapping ); + return mapping; + } + } + + +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java index 8da528f0be..396b559f6d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java @@ -6,13 +6,19 @@ */ package org.hibernate.validator.internal.engine; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getAllowMultipleCascadedValidationOnReturnValues; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getAllowOverridingMethodAlterParameterConstraint; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getAllowParallelMethodsDefineParameterConstraints; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getConstraintMappings; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getConstraintValidatorPayload; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getExternalClassLoader; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getFailFast; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getTraversableResolverResultCacheEnabled; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.logValidatorFactoryScopedConfiguration; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.registerCustomConstraintValidators; import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; -import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; -import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandles; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.time.Duration; import java.util.Collections; import java.util.List; @@ -30,38 +36,25 @@ import javax.validation.ValidatorFactory; import javax.validation.spi.ConfigurationState; -import org.hibernate.validator.HibernateValidatorConfiguration; import org.hibernate.validator.HibernateValidatorContext; import org.hibernate.validator.HibernateValidatorFactory; -import org.hibernate.validator.cfg.ConstraintMapping; -import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping; -import org.hibernate.validator.internal.engine.constraintdefinition.ConstraintDefinitionContribution; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; -import org.hibernate.validator.internal.engine.constraintvalidation.HibernateConstraintValidatorInitializationContextImpl; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; -import org.hibernate.validator.internal.engine.scripting.DefaultScriptEvaluatorFactory; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; import org.hibernate.validator.internal.metadata.provider.ProgrammaticMetaDataProvider; import org.hibernate.validator.internal.metadata.provider.XmlMetaDataProvider; -import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; -import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; -import org.hibernate.validator.internal.util.StringHelper; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; -import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader; -import org.hibernate.validator.internal.util.privilegedactions.LoadClass; -import org.hibernate.validator.internal.util.privilegedactions.NewInstance; import org.hibernate.validator.internal.util.stereotypes.Immutable; import org.hibernate.validator.internal.util.stereotypes.ThreadSafe; -import org.hibernate.validator.spi.cfg.ConstraintMappingContributor; import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; @@ -155,7 +148,7 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { Map properties = configurationState.getProperties(); - this.javaBeanHelper = new JavaBeanHelper( getGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ) ); + this.javaBeanHelper = new JavaBeanHelper( ValidatorFactoryConfigurationHelper.getGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ) ); // HV-302; don't load XmlMappingParser if not necessary if ( configurationState.getMappingStreams().isEmpty() ) { @@ -192,8 +185,8 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { configurationState.getTraversableResolver(), new ExecutableParameterNameProvider( configurationState.getParameterNameProvider() ), configurationState.getClockProvider(), - getTemporalValidationTolerance( configurationState, properties ), - getScriptEvaluatorFactory( configurationState, properties, externalClassLoader ), + ValidatorFactoryConfigurationHelper.getTemporalValidationTolerance( configurationState, properties ), + ValidatorFactoryConfigurationHelper.getScriptEvaluatorFactory( configurationState, properties, externalClassLoader ), getFailFast( hibernateSpecificConfig, properties ), getTraversableResolverResultCacheEnabled( hibernateSpecificConfig, properties ), getConstraintValidatorPayload( hibernateSpecificConfig ) @@ -211,43 +204,6 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { } } - private static ClassLoader getExternalClassLoader(ConfigurationState configurationState) { - return ( configurationState instanceof ConfigurationImpl ) ? ( (ConfigurationImpl) configurationState ).getExternalClassLoader() : null; - } - - private static Set getConstraintMappings(TypeResolutionHelper typeResolutionHelper, - ConfigurationState configurationState, JavaBeanHelper javaBeanHelper, ClassLoader externalClassLoader) { - Set constraintMappings = newHashSet(); - - if ( configurationState instanceof ConfigurationImpl ) { - ConfigurationImpl hibernateConfiguration = (ConfigurationImpl) configurationState; - - // programmatic config - /* We add these first so that constraint mapping created through DefaultConstraintMappingBuilder will take - * these programmatically defined mappings into account when checking for constraint definition uniqueness - */ - constraintMappings.addAll( hibernateConfiguration.getProgrammaticMappings() ); - - // service loader based config - ConstraintMappingContributor serviceLoaderBasedContributor = new ServiceLoaderBasedConstraintMappingContributor( - typeResolutionHelper, - externalClassLoader != null ? externalClassLoader : run( GetClassLoader.fromContext() ) ); - DefaultConstraintMappingBuilder builder = new DefaultConstraintMappingBuilder( javaBeanHelper, constraintMappings ); - serviceLoaderBasedContributor.createConstraintMappings( builder ); - } - - // XML-defined constraint mapping contributors - List contributors = getPropertyConfiguredConstraintMappingContributors( configurationState.getProperties(), - externalClassLoader ); - - for ( ConstraintMappingContributor contributor : contributors ) { - DefaultConstraintMappingBuilder builder = new DefaultConstraintMappingBuilder( javaBeanHelper, constraintMappings ); - contributor.createConstraintMappings( builder ); - } - - return constraintMappings; - } - @Override public Validator getValidator() { return createValidator( @@ -396,266 +352,6 @@ private List buildDataProviders() { return metaDataProviders; } - private static boolean checkPropertiesForBoolean(Map properties, String propertyKey, boolean programmaticValue) { - boolean value = programmaticValue; - String propertyStringValue = properties.get( propertyKey ); - if ( propertyStringValue != null ) { - value = Boolean.valueOf( propertyStringValue ); - } - return value; - } - - /** - * Returns a list with {@link ConstraintMappingContributor}s configured via the - * {@link HibernateValidatorConfiguration#CONSTRAINT_MAPPING_CONTRIBUTORS} property. - * - * Also takes into account the deprecated {@link HibernateValidatorConfiguration#CONSTRAINT_MAPPING_CONTRIBUTOR} - * property. - * - * @param properties the properties used to bootstrap the factory - * - * @return a list with property-configured {@link ConstraintMappingContributor}s; May be empty but never {@code null} - */ - private static List getPropertyConfiguredConstraintMappingContributors( - Map properties, ClassLoader externalClassLoader) { - @SuppressWarnings("deprecation") - String deprecatedPropertyValue = properties.get( HibernateValidatorConfiguration.CONSTRAINT_MAPPING_CONTRIBUTOR ); - String propertyValue = properties.get( HibernateValidatorConfiguration.CONSTRAINT_MAPPING_CONTRIBUTORS ); - - if ( StringHelper.isNullOrEmptyString( deprecatedPropertyValue ) && StringHelper.isNullOrEmptyString( propertyValue ) ) { - return Collections.emptyList(); - } - - StringBuilder assembledPropertyValue = new StringBuilder(); - if ( !StringHelper.isNullOrEmptyString( deprecatedPropertyValue ) ) { - assembledPropertyValue.append( deprecatedPropertyValue ); - } - if ( !StringHelper.isNullOrEmptyString( propertyValue ) ) { - if ( assembledPropertyValue.length() > 0 ) { - assembledPropertyValue.append( "," ); - } - assembledPropertyValue.append( propertyValue ); - } - - String[] contributorNames = assembledPropertyValue.toString().split( "," ); - List contributors = newArrayList( contributorNames.length ); - - for ( String contributorName : contributorNames ) { - @SuppressWarnings("unchecked") - Class contributorType = (Class) run( - LoadClass.action( contributorName, externalClassLoader ) ); - contributors.add( run( NewInstance.action( contributorType, "constraint mapping contributor class" ) ) ); - } - - return contributors; - } - - private static boolean getAllowParallelMethodsDefineParameterConstraints(ConfigurationImpl hibernateSpecificConfig, Map properties) { - return checkPropertiesForBoolean( - properties, - HibernateValidatorConfiguration.ALLOW_PARALLEL_METHODS_DEFINE_PARAMETER_CONSTRAINTS, - hibernateSpecificConfig != null ? hibernateSpecificConfig.getMethodValidationConfiguration().isAllowParallelMethodsDefineParameterConstraints() : false - ); - } - - private static boolean getAllowMultipleCascadedValidationOnReturnValues(ConfigurationImpl hibernateSpecificConfig, Map properties) { - return checkPropertiesForBoolean( - properties, - HibernateValidatorConfiguration.ALLOW_MULTIPLE_CASCADED_VALIDATION_ON_RESULT, - hibernateSpecificConfig != null ? hibernateSpecificConfig.getMethodValidationConfiguration().isAllowMultipleCascadedValidationOnReturnValues() : false - ); - } - - private static boolean getAllowOverridingMethodAlterParameterConstraint(ConfigurationImpl hibernateSpecificConfig, Map properties) { - return checkPropertiesForBoolean( - properties, - HibernateValidatorConfiguration.ALLOW_PARAMETER_CONSTRAINT_OVERRIDE, - hibernateSpecificConfig != null ? hibernateSpecificConfig.getMethodValidationConfiguration().isAllowOverridingMethodAlterParameterConstraint() : false - ); - } - - private static boolean getTraversableResolverResultCacheEnabled(ConfigurationImpl configuration, Map properties) { - return checkPropertiesForBoolean( - properties, - HibernateValidatorConfiguration.ENABLE_TRAVERSABLE_RESOLVER_RESULT_CACHE, - configuration != null ? configuration.isTraversableResolverResultCacheEnabled() : true - ); - } - - private static boolean getFailFast(ConfigurationImpl configuration, Map properties) { - // check whether fail fast is programmatically enabled - boolean tmpFailFast = configuration != null ? configuration.getFailFast() : false; - - String propertyStringValue = properties.get( HibernateValidatorConfiguration.FAIL_FAST ); - if ( propertyStringValue != null ) { - boolean configurationValue = Boolean.valueOf( propertyStringValue ); - // throw an exception if the programmatic value is true and it overrides a false configured value - if ( tmpFailFast && !configurationValue ) { - throw LOG.getInconsistentFailFastConfigurationException(); - } - tmpFailFast = configurationValue; - } - - return tmpFailFast; - } - - private static ScriptEvaluatorFactory getScriptEvaluatorFactory(ConfigurationState configurationState, Map properties, - ClassLoader externalClassLoader) { - if ( configurationState instanceof ConfigurationImpl ) { - ConfigurationImpl hibernateSpecificConfig = (ConfigurationImpl) configurationState; - if ( hibernateSpecificConfig.getScriptEvaluatorFactory() != null ) { - LOG.usingScriptEvaluatorFactory( hibernateSpecificConfig.getScriptEvaluatorFactory().getClass() ); - return hibernateSpecificConfig.getScriptEvaluatorFactory(); - } - } - - String scriptEvaluatorFactoryFqcn = properties.get( HibernateValidatorConfiguration.SCRIPT_EVALUATOR_FACTORY_CLASSNAME ); - if ( scriptEvaluatorFactoryFqcn != null ) { - try { - @SuppressWarnings("unchecked") - Class clazz = (Class) run( - LoadClass.action( scriptEvaluatorFactoryFqcn, externalClassLoader ) - ); - ScriptEvaluatorFactory scriptEvaluatorFactory = run( NewInstance.action( clazz, "script evaluator factory class" ) ); - LOG.usingScriptEvaluatorFactory( clazz ); - - return scriptEvaluatorFactory; - } - catch (Exception e) { - throw LOG.getUnableToInstantiateScriptEvaluatorFactoryClassException( scriptEvaluatorFactoryFqcn, e ); - } - } - - return new DefaultScriptEvaluatorFactory( externalClassLoader ); - } - - private Duration getTemporalValidationTolerance(ConfigurationState configurationState, Map properties) { - if ( configurationState instanceof ConfigurationImpl ) { - ConfigurationImpl hibernateSpecificConfig = (ConfigurationImpl) configurationState; - if ( hibernateSpecificConfig.getTemporalValidationTolerance() != null ) { - LOG.logTemporalValidationTolerance( hibernateSpecificConfig.getTemporalValidationTolerance() ); - return hibernateSpecificConfig.getTemporalValidationTolerance(); - } - } - String temporalValidationToleranceProperty = properties.get( HibernateValidatorConfiguration.TEMPORAL_VALIDATION_TOLERANCE ); - if ( temporalValidationToleranceProperty != null ) { - try { - Duration tolerance = Duration.ofMillis( Long.parseLong( temporalValidationToleranceProperty ) ).abs(); - LOG.logTemporalValidationTolerance( tolerance ); - return tolerance; - } - catch (Exception e) { - throw LOG.getUnableToParseTemporalValidationToleranceException( temporalValidationToleranceProperty, e ); - } - } - - return Duration.ZERO; - } - - private Object getConstraintValidatorPayload(ConfigurationState configurationState) { - if ( configurationState instanceof ConfigurationImpl ) { - ConfigurationImpl hibernateSpecificConfig = (ConfigurationImpl) configurationState; - if ( hibernateSpecificConfig.getConstraintValidatorPayload() != null ) { - LOG.logConstraintValidatorPayload( hibernateSpecificConfig.getConstraintValidatorPayload() ); - return hibernateSpecificConfig.getConstraintValidatorPayload(); - } - } - - return null; - } - - private static GetterPropertySelectionStrategy getGetterPropertySelectionStrategy(ConfigurationImpl hibernateSpecificConfig, Map properties, - ClassLoader externalClassLoader) { - if ( hibernateSpecificConfig.getGetterPropertySelectionStrategy() != null ) { - LOG.usingGetterPropertySelectionStrategy( hibernateSpecificConfig.getGetterPropertySelectionStrategy().getClass() ); - return hibernateSpecificConfig.getGetterPropertySelectionStrategy(); - } - - String getterPropertySelectionStrategyFqcn = properties.get( HibernateValidatorConfiguration.GETTER_PROPERTY_SELECTION_STRATEGY_CLASSNAME ); - if ( getterPropertySelectionStrategyFqcn != null ) { - try { - @SuppressWarnings("unchecked") - Class clazz = (Class) run( - LoadClass.action( getterPropertySelectionStrategyFqcn, externalClassLoader ) - ); - GetterPropertySelectionStrategy getterPropertySelectionStrategy = run( NewInstance.action( clazz, "getter property selection strategy class" ) ); - LOG.usingGetterPropertySelectionStrategy( clazz ); - - return getterPropertySelectionStrategy; - } - catch (Exception e) { - throw LOG.getUnableToInstantiateGetterPropertySelectionStrategyClassException( getterPropertySelectionStrategyFqcn, e ); - } - } - - return new DefaultGetterPropertySelectionStrategy(); - } - - private static void registerCustomConstraintValidators(Set constraintMappings, - ConstraintHelper constraintHelper) { - Set> definedConstraints = newHashSet(); - for ( DefaultConstraintMapping constraintMapping : constraintMappings ) { - for ( ConstraintDefinitionContribution contribution : constraintMapping.getConstraintDefinitionContributions() ) { - processConstraintDefinitionContribution( contribution, constraintHelper, definedConstraints ); - } - } - } - - private static void processConstraintDefinitionContribution( - ConstraintDefinitionContribution constraintDefinitionContribution, ConstraintHelper constraintHelper, - Set> definedConstraints) { - Class constraintType = constraintDefinitionContribution.getConstraintType(); - if ( definedConstraints.contains( constraintType ) ) { - throw LOG.getConstraintHasAlreadyBeenConfiguredViaProgrammaticApiException( constraintType ); - } - definedConstraints.add( constraintType ); - constraintHelper.putValidatorDescriptors( - constraintType, - constraintDefinitionContribution.getValidatorDescriptors(), - constraintDefinitionContribution.includeExisting() - ); - } - - private static void logValidatorFactoryScopedConfiguration(ValidatorFactoryScopedContext context) { - LOG.logValidatorFactoryScopedConfiguration( context.getMessageInterpolator().getClass(), "message interpolator" ); - LOG.logValidatorFactoryScopedConfiguration( context.getTraversableResolver().getClass(), "traversable resolver" ); - LOG.logValidatorFactoryScopedConfiguration( context.getParameterNameProvider().getClass(), "parameter name provider" ); - LOG.logValidatorFactoryScopedConfiguration( context.getClockProvider().getClass(), "clock provider" ); - LOG.logValidatorFactoryScopedConfiguration( context.getScriptEvaluatorFactory().getClass(), "script evaluator factory" ); - } - - /** - * Runs the given privileged action, using a privileged block if required. - *

- * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary - * privileged actions within HV's protection domain. - */ - private static T run(PrivilegedAction action) { - return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); - } - - /** - * The one and only {@link ConstraintMappingContributor.ConstraintMappingBuilder} implementation. - */ - private static class DefaultConstraintMappingBuilder - implements ConstraintMappingContributor.ConstraintMappingBuilder { - - private final JavaBeanHelper javaBeanHelper; - private final Set mappings; - - public DefaultConstraintMappingBuilder(JavaBeanHelper javaBeanHelper, Set mappings) { - this.javaBeanHelper = javaBeanHelper; - this.mappings = mappings; - } - - @Override - public ConstraintMapping addConstraintMapping() { - DefaultConstraintMapping mapping = new DefaultConstraintMapping( javaBeanHelper ); - mappings.add( mapping ); - return mapping; - } - } - private static class BeanMetaDataManagerKey { private final ExecutableParameterNameProvider parameterNameProvider; private final ValueExtractorManager valueExtractorManager; @@ -707,257 +403,4 @@ public String toString() { + ", methodValidationConfiguration=" + methodValidationConfiguration + "]"; } } - - public static class ValidatorFactoryScopedContext { - /** - * The default message interpolator for this factory. - */ - private final MessageInterpolator messageInterpolator; - - /** - * The default traversable resolver for this factory. - */ - private final TraversableResolver traversableResolver; - - /** - * The default parameter name provider for this factory. - */ - private final ExecutableParameterNameProvider parameterNameProvider; - - /** - * Provider for the current time when validating {@code @Future} or {@code @Past} - */ - private final ClockProvider clockProvider; - - /** - * Defines the temporal validation tolerance i.e. the allowed margin of error when comparing date/time in temporal - * constraints. - */ - private final Duration temporalValidationTolerance; - - /** - * Used to get the {@code ScriptEvaluatorFactory} when validating {@code @ScriptAssert} and - * {@code @ParameterScriptAssert} constraints. - */ - private final ScriptEvaluatorFactory scriptEvaluatorFactory; - - /** - * Hibernate Validator specific flag to abort validation on first constraint violation. - */ - private final boolean failFast; - - /** - * Hibernate Validator specific flag to disable the {@code TraversableResolver} result cache. - */ - private final boolean traversableResolverResultCacheEnabled; - - /** - * The constraint validator payload. - */ - private final Object constraintValidatorPayload; - - /** - * The constraint validator initialization context. - */ - private final HibernateConstraintValidatorInitializationContextImpl constraintValidatorInitializationContext; - - private ValidatorFactoryScopedContext(MessageInterpolator messageInterpolator, - TraversableResolver traversableResolver, - ExecutableParameterNameProvider parameterNameProvider, - ClockProvider clockProvider, - Duration temporalValidationTolerance, - ScriptEvaluatorFactory scriptEvaluatorFactory, - boolean failFast, - boolean traversableResolverResultCacheEnabled, - Object constraintValidatorPayload) { - this( messageInterpolator, traversableResolver, parameterNameProvider, clockProvider, temporalValidationTolerance, scriptEvaluatorFactory, failFast, - traversableResolverResultCacheEnabled, constraintValidatorPayload, - new HibernateConstraintValidatorInitializationContextImpl( scriptEvaluatorFactory, clockProvider, - temporalValidationTolerance ) ); - } - - private ValidatorFactoryScopedContext(MessageInterpolator messageInterpolator, - TraversableResolver traversableResolver, - ExecutableParameterNameProvider parameterNameProvider, - ClockProvider clockProvider, - Duration temporalValidationTolerance, - ScriptEvaluatorFactory scriptEvaluatorFactory, - boolean failFast, - boolean traversableResolverResultCacheEnabled, - Object constraintValidatorPayload, - HibernateConstraintValidatorInitializationContextImpl constraintValidatorInitializationContext) { - this.messageInterpolator = messageInterpolator; - this.traversableResolver = traversableResolver; - this.parameterNameProvider = parameterNameProvider; - this.clockProvider = clockProvider; - this.temporalValidationTolerance = temporalValidationTolerance; - this.scriptEvaluatorFactory = scriptEvaluatorFactory; - this.failFast = failFast; - this.traversableResolverResultCacheEnabled = traversableResolverResultCacheEnabled; - this.constraintValidatorPayload = constraintValidatorPayload; - this.constraintValidatorInitializationContext = constraintValidatorInitializationContext; - } - - public MessageInterpolator getMessageInterpolator() { - return this.messageInterpolator; - } - - public TraversableResolver getTraversableResolver() { - return this.traversableResolver; - } - - public ExecutableParameterNameProvider getParameterNameProvider() { - return this.parameterNameProvider; - } - - public ClockProvider getClockProvider() { - return this.clockProvider; - } - - public Duration getTemporalValidationTolerance() { - return this.temporalValidationTolerance; - } - - public ScriptEvaluatorFactory getScriptEvaluatorFactory() { - return this.scriptEvaluatorFactory; - } - - public boolean isFailFast() { - return this.failFast; - } - - public boolean isTraversableResolverResultCacheEnabled() { - return this.traversableResolverResultCacheEnabled; - } - - public Object getConstraintValidatorPayload() { - return this.constraintValidatorPayload; - } - - public HibernateConstraintValidatorInitializationContext getConstraintValidatorInitializationContext() { - return this.constraintValidatorInitializationContext; - } - - static class Builder { - private final ValidatorFactoryScopedContext defaultContext; - - private MessageInterpolator messageInterpolator; - private TraversableResolver traversableResolver; - private ExecutableParameterNameProvider parameterNameProvider; - private ClockProvider clockProvider; - private ScriptEvaluatorFactory scriptEvaluatorFactory; - private Duration temporalValidationTolerance; - private boolean failFast; - private boolean traversableResolverResultCacheEnabled; - private Object constraintValidatorPayload; - private HibernateConstraintValidatorInitializationContextImpl constraintValidatorInitializationContext; - - Builder(ValidatorFactoryScopedContext defaultContext) { - Contracts.assertNotNull( defaultContext, "Default context cannot be null." ); - - this.defaultContext = defaultContext; - this.messageInterpolator = defaultContext.messageInterpolator; - this.traversableResolver = defaultContext.traversableResolver; - this.parameterNameProvider = defaultContext.parameterNameProvider; - this.clockProvider = defaultContext.clockProvider; - this.scriptEvaluatorFactory = defaultContext.scriptEvaluatorFactory; - this.temporalValidationTolerance = defaultContext.temporalValidationTolerance; - this.failFast = defaultContext.failFast; - this.traversableResolverResultCacheEnabled = defaultContext.traversableResolverResultCacheEnabled; - this.constraintValidatorPayload = defaultContext.constraintValidatorPayload; - this.constraintValidatorInitializationContext = defaultContext.constraintValidatorInitializationContext; - } - - public Builder setMessageInterpolator(MessageInterpolator messageInterpolator) { - if ( messageInterpolator == null ) { - this.messageInterpolator = defaultContext.messageInterpolator; - } - else { - this.messageInterpolator = messageInterpolator; - } - - return this; - } - - public Builder setTraversableResolver(TraversableResolver traversableResolver) { - if ( traversableResolver == null ) { - this.traversableResolver = defaultContext.traversableResolver; - } - else { - this.traversableResolver = traversableResolver; - } - return this; - } - - public Builder setParameterNameProvider(ParameterNameProvider parameterNameProvider) { - if ( parameterNameProvider == null ) { - this.parameterNameProvider = defaultContext.parameterNameProvider; - } - else { - this.parameterNameProvider = new ExecutableParameterNameProvider( parameterNameProvider ); - } - return this; - } - - public Builder setClockProvider(ClockProvider clockProvider) { - if ( clockProvider == null ) { - this.clockProvider = defaultContext.clockProvider; - } - else { - this.clockProvider = clockProvider; - } - return this; - } - - public Builder setTemporalValidationTolerance(Duration temporalValidationTolerance) { - this.temporalValidationTolerance = temporalValidationTolerance == null ? Duration.ZERO : temporalValidationTolerance.abs(); - return this; - } - - public Builder setScriptEvaluatorFactory(ScriptEvaluatorFactory scriptEvaluatorFactory) { - if ( scriptEvaluatorFactory == null ) { - this.scriptEvaluatorFactory = defaultContext.scriptEvaluatorFactory; - } - else { - this.scriptEvaluatorFactory = scriptEvaluatorFactory; - } - return this; - } - - public Builder setFailFast(boolean failFast) { - this.failFast = failFast; - return this; - } - - public Builder setTraversableResolverResultCacheEnabled(boolean traversableResolverResultCacheEnabled) { - this.traversableResolverResultCacheEnabled = traversableResolverResultCacheEnabled; - return this; - } - - public Builder setConstraintValidatorPayload(Object constraintValidatorPayload) { - this.constraintValidatorPayload = constraintValidatorPayload; - return this; - } - - public ValidatorFactoryScopedContext build() { - return new ValidatorFactoryScopedContext( - messageInterpolator, - traversableResolver, - parameterNameProvider, - clockProvider, - temporalValidationTolerance, - scriptEvaluatorFactory, - failFast, - traversableResolverResultCacheEnabled, - constraintValidatorPayload, - HibernateConstraintValidatorInitializationContextImpl.of( - constraintValidatorInitializationContext, - scriptEvaluatorFactory, - clockProvider, - temporalValidationTolerance - ) - ); - } - } - } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryScopedContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryScopedContext.java new file mode 100644 index 0000000000..fa87eb016d --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryScopedContext.java @@ -0,0 +1,273 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine; + +import java.time.Duration; + +import javax.validation.ClockProvider; +import javax.validation.MessageInterpolator; +import javax.validation.ParameterNameProvider; +import javax.validation.TraversableResolver; + +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; +import org.hibernate.validator.internal.engine.constraintvalidation.HibernateConstraintValidatorInitializationContextImpl; +import org.hibernate.validator.internal.util.Contracts; +import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; +import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; + +public class ValidatorFactoryScopedContext { + /** + * The default message interpolator for this factory. + */ + private final MessageInterpolator messageInterpolator; + + /** + * The default traversable resolver for this factory. + */ + private final TraversableResolver traversableResolver; + + /** + * The default parameter name provider for this factory. + */ + private final ExecutableParameterNameProvider parameterNameProvider; + + /** + * Provider for the current time when validating {@code @Future} or {@code @Past} + */ + private final ClockProvider clockProvider; + + /** + * Defines the temporal validation tolerance i.e. the allowed margin of error when comparing date/time in temporal + * constraints. + */ + private final Duration temporalValidationTolerance; + + /** + * Used to get the {@code ScriptEvaluatorFactory} when validating {@code @ScriptAssert} and + * {@code @ParameterScriptAssert} constraints. + */ + private final ScriptEvaluatorFactory scriptEvaluatorFactory; + + /** + * Hibernate Validator specific flag to abort validation on first constraint violation. + */ + private final boolean failFast; + + /** + * Hibernate Validator specific flag to disable the {@code TraversableResolver} result cache. + */ + private final boolean traversableResolverResultCacheEnabled; + + /** + * The constraint validator payload. + */ + private final Object constraintValidatorPayload; + + /** + * The constraint validator initialization context. + */ + private final HibernateConstraintValidatorInitializationContextImpl constraintValidatorInitializationContext; + + ValidatorFactoryScopedContext(MessageInterpolator messageInterpolator, + TraversableResolver traversableResolver, + ExecutableParameterNameProvider parameterNameProvider, + ClockProvider clockProvider, + Duration temporalValidationTolerance, + ScriptEvaluatorFactory scriptEvaluatorFactory, + boolean failFast, + boolean traversableResolverResultCacheEnabled, + Object constraintValidatorPayload) { + this( messageInterpolator, traversableResolver, parameterNameProvider, clockProvider, temporalValidationTolerance, scriptEvaluatorFactory, failFast, + traversableResolverResultCacheEnabled, constraintValidatorPayload, + new HibernateConstraintValidatorInitializationContextImpl( scriptEvaluatorFactory, clockProvider, + temporalValidationTolerance ) ); + } + + private ValidatorFactoryScopedContext(MessageInterpolator messageInterpolator, + TraversableResolver traversableResolver, + ExecutableParameterNameProvider parameterNameProvider, + ClockProvider clockProvider, + Duration temporalValidationTolerance, + ScriptEvaluatorFactory scriptEvaluatorFactory, + boolean failFast, + boolean traversableResolverResultCacheEnabled, + Object constraintValidatorPayload, + HibernateConstraintValidatorInitializationContextImpl constraintValidatorInitializationContext) { + this.messageInterpolator = messageInterpolator; + this.traversableResolver = traversableResolver; + this.parameterNameProvider = parameterNameProvider; + this.clockProvider = clockProvider; + this.temporalValidationTolerance = temporalValidationTolerance; + this.scriptEvaluatorFactory = scriptEvaluatorFactory; + this.failFast = failFast; + this.traversableResolverResultCacheEnabled = traversableResolverResultCacheEnabled; + this.constraintValidatorPayload = constraintValidatorPayload; + this.constraintValidatorInitializationContext = constraintValidatorInitializationContext; + } + + public MessageInterpolator getMessageInterpolator() { + return this.messageInterpolator; + } + + public TraversableResolver getTraversableResolver() { + return this.traversableResolver; + } + + public ExecutableParameterNameProvider getParameterNameProvider() { + return this.parameterNameProvider; + } + + public ClockProvider getClockProvider() { + return this.clockProvider; + } + + public Duration getTemporalValidationTolerance() { + return this.temporalValidationTolerance; + } + + public ScriptEvaluatorFactory getScriptEvaluatorFactory() { + return this.scriptEvaluatorFactory; + } + + public boolean isFailFast() { + return this.failFast; + } + + public boolean isTraversableResolverResultCacheEnabled() { + return this.traversableResolverResultCacheEnabled; + } + + public Object getConstraintValidatorPayload() { + return this.constraintValidatorPayload; + } + + public HibernateConstraintValidatorInitializationContext getConstraintValidatorInitializationContext() { + return this.constraintValidatorInitializationContext; + } + + static class Builder { + private final ValidatorFactoryScopedContext defaultContext; + + private MessageInterpolator messageInterpolator; + private TraversableResolver traversableResolver; + private ExecutableParameterNameProvider parameterNameProvider; + private ClockProvider clockProvider; + private ScriptEvaluatorFactory scriptEvaluatorFactory; + private Duration temporalValidationTolerance; + private boolean failFast; + private boolean traversableResolverResultCacheEnabled; + private Object constraintValidatorPayload; + private HibernateConstraintValidatorInitializationContextImpl constraintValidatorInitializationContext; + + Builder(ValidatorFactoryScopedContext defaultContext) { + Contracts.assertNotNull( defaultContext, "Default context cannot be null." ); + + this.defaultContext = defaultContext; + this.messageInterpolator = defaultContext.messageInterpolator; + this.traversableResolver = defaultContext.traversableResolver; + this.parameterNameProvider = defaultContext.parameterNameProvider; + this.clockProvider = defaultContext.clockProvider; + this.scriptEvaluatorFactory = defaultContext.scriptEvaluatorFactory; + this.temporalValidationTolerance = defaultContext.temporalValidationTolerance; + this.failFast = defaultContext.failFast; + this.traversableResolverResultCacheEnabled = defaultContext.traversableResolverResultCacheEnabled; + this.constraintValidatorPayload = defaultContext.constraintValidatorPayload; + this.constraintValidatorInitializationContext = defaultContext.constraintValidatorInitializationContext; + } + + public ValidatorFactoryScopedContext.Builder setMessageInterpolator(MessageInterpolator messageInterpolator) { + if ( messageInterpolator == null ) { + this.messageInterpolator = defaultContext.messageInterpolator; + } + else { + this.messageInterpolator = messageInterpolator; + } + + return this; + } + + public ValidatorFactoryScopedContext.Builder setTraversableResolver(TraversableResolver traversableResolver) { + if ( traversableResolver == null ) { + this.traversableResolver = defaultContext.traversableResolver; + } + else { + this.traversableResolver = traversableResolver; + } + return this; + } + + public ValidatorFactoryScopedContext.Builder setParameterNameProvider(ParameterNameProvider parameterNameProvider) { + if ( parameterNameProvider == null ) { + this.parameterNameProvider = defaultContext.parameterNameProvider; + } + else { + this.parameterNameProvider = new ExecutableParameterNameProvider( parameterNameProvider ); + } + return this; + } + + public ValidatorFactoryScopedContext.Builder setClockProvider(ClockProvider clockProvider) { + if ( clockProvider == null ) { + this.clockProvider = defaultContext.clockProvider; + } + else { + this.clockProvider = clockProvider; + } + return this; + } + + public ValidatorFactoryScopedContext.Builder setTemporalValidationTolerance(Duration temporalValidationTolerance) { + this.temporalValidationTolerance = temporalValidationTolerance == null ? Duration.ZERO : temporalValidationTolerance.abs(); + return this; + } + + public ValidatorFactoryScopedContext.Builder setScriptEvaluatorFactory(ScriptEvaluatorFactory scriptEvaluatorFactory) { + if ( scriptEvaluatorFactory == null ) { + this.scriptEvaluatorFactory = defaultContext.scriptEvaluatorFactory; + } + else { + this.scriptEvaluatorFactory = scriptEvaluatorFactory; + } + return this; + } + + public ValidatorFactoryScopedContext.Builder setFailFast(boolean failFast) { + this.failFast = failFast; + return this; + } + + public ValidatorFactoryScopedContext.Builder setTraversableResolverResultCacheEnabled(boolean traversableResolverResultCacheEnabled) { + this.traversableResolverResultCacheEnabled = traversableResolverResultCacheEnabled; + return this; + } + + public ValidatorFactoryScopedContext.Builder setConstraintValidatorPayload(Object constraintValidatorPayload) { + this.constraintValidatorPayload = constraintValidatorPayload; + return this; + } + + public ValidatorFactoryScopedContext build() { + return new ValidatorFactoryScopedContext( + messageInterpolator, + traversableResolver, + parameterNameProvider, + clockProvider, + temporalValidationTolerance, + scriptEvaluatorFactory, + failFast, + traversableResolverResultCacheEnabled, + constraintValidatorPayload, + HibernateConstraintValidatorInitializationContextImpl.of( + constraintValidatorInitializationContext, + scriptEvaluatorFactory, + clockProvider, + temporalValidationTolerance + ) + ); + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index 3bcef46a56..e5e32b449c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -34,7 +34,6 @@ import javax.validation.valueextraction.ValueExtractor; import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; -import org.hibernate.validator.internal.engine.ValidatorFactoryImpl.ValidatorFactoryScopedContext; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; import org.hibernate.validator.internal.engine.groups.Group; import org.hibernate.validator.internal.engine.groups.GroupWithInheritance; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidatorScopedContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidatorScopedContext.java index b4c6c8c9c5..04953bc7b7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidatorScopedContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidatorScopedContext.java @@ -12,7 +12,7 @@ import javax.validation.MessageInterpolator; import javax.validation.Validator; -import org.hibernate.validator.internal.engine.ValidatorFactoryImpl; +import org.hibernate.validator.internal.engine.ValidatorFactoryScopedContext; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; @@ -65,7 +65,7 @@ public class ValidatorScopedContext { */ private final Object constraintValidatorPayload; - public ValidatorScopedContext(ValidatorFactoryImpl.ValidatorFactoryScopedContext validatorFactoryScopedContext) { + public ValidatorScopedContext(ValidatorFactoryScopedContext validatorFactoryScopedContext) { this.messageInterpolator = validatorFactoryScopedContext.getMessageInterpolator(); this.parameterNameProvider = validatorFactoryScopedContext.getParameterNameProvider(); this.clockProvider = validatorFactoryScopedContext.getClockProvider(); From c51586421543516aa0d5636b88b6243e29c0252a Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 27 Nov 2018 17:43:56 +0100 Subject: [PATCH 136/393] HV-1667 Create an interface for ConstraintValidatorManager --- .../internal/engine/ValidatorFactoryImpl.java | 3 +- .../ConstraintValidatorManager.java | 328 +--------------- .../ConstraintValidatorManagerImpl.java | 363 ++++++++++++++++++ .../ConstraintValidatorManagerTest.java | 6 +- 4 files changed, 375 insertions(+), 325 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManagerImpl.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java index 396b559f6d..bb3d100513 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java @@ -40,6 +40,7 @@ import org.hibernate.validator.HibernateValidatorFactory; import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManagerImpl; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; @@ -192,7 +193,7 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { getConstraintValidatorPayload( hibernateSpecificConfig ) ); - this.constraintValidatorManager = new ConstraintValidatorManager( + this.constraintValidatorManager = new ConstraintValidatorManagerImpl( configurationState.getConstraintValidatorFactory(), this.validatorFactoryScopedContext.getConstraintValidatorInitializationContext() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManager.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManager.java index 105982d119..b35062c622 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManager.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManager.java @@ -6,48 +6,29 @@ */ package org.hibernate.validator.internal.engine.constraintvalidation; -import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; - import java.lang.annotation.Annotation; -import java.lang.invoke.MethodHandles; import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; -import javax.validation.ConstraintDeclarationException; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.ConstraintValidatorFactory; import javax.validation.constraints.Null; -import javax.validation.metadata.ConstraintDescriptor; -import org.hibernate.validator.constraintvalidation.HibernateConstraintValidator; import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; -import org.hibernate.validator.internal.util.Contracts; -import org.hibernate.validator.internal.util.TypeHelper; -import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; -import org.hibernate.validator.internal.util.logging.Log; -import org.hibernate.validator.internal.util.logging.LoggerFactory; /** * Manager in charge of providing and caching initialized {@code ConstraintValidator} instances. * * @author Hardy Ferentschik */ -public class ConstraintValidatorManager { - - private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); +public interface ConstraintValidatorManager { /** * Dummy {@code ConstraintValidator} used as placeholder for the case that for a given context there exists * no matching constraint validator instance */ - static ConstraintValidator DUMMY_CONSTRAINT_VALIDATOR = new ConstraintValidator() { + ConstraintValidator DUMMY_CONSTRAINT_VALIDATOR = new ConstraintValidator() { @Override public boolean isValid(Object value, ConstraintValidatorContext context) { @@ -55,58 +36,6 @@ public boolean isValid(Object value, ConstraintValidatorContext context) { } }; - /** - * The explicit or implicit default constraint validator factory. We always cache {@code ConstraintValidator} - * instances if they are created via the default instance and with the default initialization context. Constraint - * validator instances created via other factory instances (specified eg via {@code ValidatorFactory#usingContext()} - * or initialization context are only cached for the most recently used factory and context. - */ - private final ConstraintValidatorFactory defaultConstraintValidatorFactory; - - /** - * The explicit or implicit default constraint validator initialization context. We always cache - * {@code ConstraintValidator} instances if they are created via the default instance and with the default context. - * Constraint validator instances created via other factory instances (specified eg via - * {@code ValidatorFactory#usingContext()} or initialization context are only cached for the most recently used - * factory and context. - */ - private final HibernateConstraintValidatorInitializationContext defaultConstraintValidatorInitializationContext; - - /** - * The most recently used non default constraint validator factory. - */ - private volatile ConstraintValidatorFactory mostRecentlyUsedNonDefaultConstraintValidatorFactory; - - /** - * The most recently used non default constraint validator initialization context. - */ - private volatile HibernateConstraintValidatorInitializationContext mostRecentlyUsedNonDefaultConstraintValidatorInitializationContext; - - /** - * Used for synchronizing access to {@link #mostRecentlyUsedNonDefaultConstraintValidatorFactory} (which can be - * null itself). - */ - private final Object mostRecentlyUsedNonDefaultConstraintValidatorFactoryAndInitializationContextMutex = new Object(); - - /** - * Cache of initialized {@code ConstraintValidator} instances keyed against validated type, annotation, - * constraint validator factory and constraint validator initialization context ({@code CacheKey}). - */ - private final ConcurrentHashMap> constraintValidatorCache; - - /** - * Creates a new {@code ConstraintValidatorManager}. - * - * @param defaultConstraintValidatorFactory the default validator factory - * @param defaultConstraintValidatorInitializationContext the default initialization context - */ - public ConstraintValidatorManager(ConstraintValidatorFactory defaultConstraintValidatorFactory, - HibernateConstraintValidatorInitializationContext defaultConstraintValidatorInitializationContext) { - this.defaultConstraintValidatorFactory = defaultConstraintValidatorFactory; - this.defaultConstraintValidatorInitializationContext = defaultConstraintValidatorInitializationContext; - this.constraintValidatorCache = new ConcurrentHashMap<>(); - } - /** * @param validatedValueType the type of the value to be validated. Cannot be {@code null}. * @param descriptor the constraint descriptor for which to get an initialized constraint validator. Cannot be {@code null} @@ -117,258 +46,15 @@ public ConstraintValidatorManager(ConstraintValidatorFactory defaultConstraintVa * @return an initialized constraint validator for the given type and annotation of the value to be validated. * {@code null} is returned if no matching constraint validator could be found. */ - public ConstraintValidator getInitializedValidator( - Type validatedValueType, - ConstraintDescriptorImpl descriptor, - ConstraintValidatorFactory constraintValidatorFactory, - HibernateConstraintValidatorInitializationContext initializationContext) { - Contracts.assertNotNull( validatedValueType ); - Contracts.assertNotNull( descriptor ); - Contracts.assertNotNull( constraintValidatorFactory ); - Contracts.assertNotNull( initializationContext ); - - CacheKey key = new CacheKey( descriptor.getAnnotationDescriptor(), validatedValueType, constraintValidatorFactory, initializationContext ); - - @SuppressWarnings("unchecked") - ConstraintValidator constraintValidator = (ConstraintValidator) constraintValidatorCache.get( key ); - - if ( constraintValidator == null ) { - constraintValidator = createAndInitializeValidator( validatedValueType, descriptor, constraintValidatorFactory, initializationContext ); - constraintValidator = cacheValidator( key, constraintValidator ); - } - else { - LOG.tracef( "Constraint validator %s found in cache.", constraintValidator ); - } - - return DUMMY_CONSTRAINT_VALIDATOR == constraintValidator ? null : constraintValidator; - } - - private ConstraintValidator cacheValidator(CacheKey key, - ConstraintValidator constraintValidator) { - // we only cache constraint validator instances for the default and most recently used factory - if ( ( key.getConstraintValidatorFactory() != defaultConstraintValidatorFactory - && key.getConstraintValidatorFactory() != mostRecentlyUsedNonDefaultConstraintValidatorFactory ) || - ( key.getConstraintValidatorInitializationContext() != defaultConstraintValidatorInitializationContext - && key.getConstraintValidatorInitializationContext() != mostRecentlyUsedNonDefaultConstraintValidatorInitializationContext ) ) { - - synchronized ( mostRecentlyUsedNonDefaultConstraintValidatorFactoryAndInitializationContextMutex ) { - if ( key.constraintValidatorFactory != mostRecentlyUsedNonDefaultConstraintValidatorFactory || - key.constraintValidatorInitializationContext != mostRecentlyUsedNonDefaultConstraintValidatorInitializationContext ) { - clearEntries( mostRecentlyUsedNonDefaultConstraintValidatorFactory, mostRecentlyUsedNonDefaultConstraintValidatorInitializationContext ); - mostRecentlyUsedNonDefaultConstraintValidatorFactory = key.getConstraintValidatorFactory(); - mostRecentlyUsedNonDefaultConstraintValidatorInitializationContext = key.getConstraintValidatorInitializationContext(); - } - } - } - - @SuppressWarnings("unchecked") - ConstraintValidator cached = (ConstraintValidator) constraintValidatorCache.putIfAbsent( key, constraintValidator ); - - return cached != null ? cached : constraintValidator; - } - - @SuppressWarnings("unchecked") - private ConstraintValidator createAndInitializeValidator( + ConstraintValidator getInitializedValidator( Type validatedValueType, ConstraintDescriptorImpl descriptor, ConstraintValidatorFactory constraintValidatorFactory, - HibernateConstraintValidatorInitializationContext initializationContext) { + HibernateConstraintValidatorInitializationContext initializationContext); - ConstraintValidatorDescriptor validatorDescriptor = findMatchingValidatorDescriptor( descriptor, validatedValueType ); - ConstraintValidator constraintValidator; + void clear(); - if ( validatorDescriptor == null ) { - constraintValidator = (ConstraintValidator) DUMMY_CONSTRAINT_VALIDATOR; - } - else { - constraintValidator = validatorDescriptor.newInstance( constraintValidatorFactory ); - initializeValidator( descriptor, constraintValidator, initializationContext ); - } - - return constraintValidator; - } - - private void clearEntries(ConstraintValidatorFactory constraintValidatorFactory, HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext) { - Iterator>> cacheEntries = constraintValidatorCache.entrySet().iterator(); - - while ( cacheEntries.hasNext() ) { - Entry> cacheEntry = cacheEntries.next(); - if ( cacheEntry.getKey().getConstraintValidatorFactory() == constraintValidatorFactory && - cacheEntry.getKey().getConstraintValidatorInitializationContext() == constraintValidatorInitializationContext ) { - constraintValidatorFactory.releaseInstance( cacheEntry.getValue() ); - cacheEntries.remove(); - } - } - } + ConstraintValidatorFactory getDefaultConstraintValidatorFactory(); - public void clear() { - for ( Map.Entry> entry : constraintValidatorCache.entrySet() ) { - entry.getKey().getConstraintValidatorFactory().releaseInstance( entry.getValue() ); - } - constraintValidatorCache.clear(); - } - - public ConstraintValidatorFactory getDefaultConstraintValidatorFactory() { - return defaultConstraintValidatorFactory; - } - - public HibernateConstraintValidatorInitializationContext getDefaultConstraintValidatorInitializationContext() { - return defaultConstraintValidatorInitializationContext; - } - - public int numberOfCachedConstraintValidatorInstances() { - return constraintValidatorCache.size(); - } - - /** - * Runs the validator resolution algorithm. - * - * @param validatedValueType The type of the value to be validated (the type of the member/class the constraint was placed on). - * - * @return The class of a matching validator. - */ - private ConstraintValidatorDescriptor findMatchingValidatorDescriptor(ConstraintDescriptorImpl descriptor, Type validatedValueType) { - Map> availableValidatorDescriptors = TypeHelper.getValidatorTypes( - descriptor.getAnnotationType(), - descriptor.getMatchingConstraintValidatorDescriptors() - ); - - List discoveredSuitableTypes = findSuitableValidatorTypes( validatedValueType, availableValidatorDescriptors.keySet() ); - resolveAssignableTypes( discoveredSuitableTypes ); - - if ( discoveredSuitableTypes.size() == 0 ) { - return null; - } - - if ( discoveredSuitableTypes.size() > 1 ) { - throw LOG.getMoreThanOneValidatorFoundForTypeException( validatedValueType, discoveredSuitableTypes ); - } - - Type suitableType = discoveredSuitableTypes.get( 0 ); - return availableValidatorDescriptors.get( suitableType ); - } - - private List findSuitableValidatorTypes(Type type, Iterable availableValidatorTypes) { - List determinedSuitableTypes = newArrayList(); - for ( Type validatorType : availableValidatorTypes ) { - if ( TypeHelper.isAssignable( validatorType, type ) - && !determinedSuitableTypes.contains( validatorType ) ) { - determinedSuitableTypes.add( validatorType ); - } - } - return determinedSuitableTypes; - } - - @SuppressWarnings("unchecked") - private void initializeValidator( - ConstraintDescriptor descriptor, - ConstraintValidator constraintValidator, - HibernateConstraintValidatorInitializationContext initializationContext) { - try { - if ( constraintValidator instanceof HibernateConstraintValidator ) { - ( (HibernateConstraintValidator) constraintValidator ).initialize( descriptor, initializationContext ); - } - constraintValidator.initialize( descriptor.getAnnotation() ); - } - catch (RuntimeException e) { - if ( e instanceof ConstraintDeclarationException ) { - throw e; - } - throw LOG.getUnableToInitializeConstraintValidatorException( constraintValidator.getClass(), e ); - } - } - - /** - * Tries to reduce all assignable classes down to a single class. - * - * @param assignableTypes The set of all classes which are assignable to the class of the value to be validated and - * which are handled by at least one of the validators for the specified constraint. - */ - private void resolveAssignableTypes(List assignableTypes) { - if ( assignableTypes.size() == 0 || assignableTypes.size() == 1 ) { - return; - } - - List typesToRemove = new ArrayList<>(); - do { - typesToRemove.clear(); - Type type = assignableTypes.get( 0 ); - for ( int i = 1; i < assignableTypes.size(); i++ ) { - if ( TypeHelper.isAssignable( type, assignableTypes.get( i ) ) ) { - typesToRemove.add( type ); - } - else if ( TypeHelper.isAssignable( assignableTypes.get( i ), type ) ) { - typesToRemove.add( assignableTypes.get( i ) ); - } - } - assignableTypes.removeAll( typesToRemove ); - } while ( typesToRemove.size() > 0 ); - } - - private static final class CacheKey { - // These members are not final for optimization purposes - private ConstraintAnnotationDescriptor annotationDescriptor; - private Type validatedType; - private ConstraintValidatorFactory constraintValidatorFactory; - private HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext; - private int hashCode; - - private CacheKey(ConstraintAnnotationDescriptor annotationDescriptor, Type validatorType, ConstraintValidatorFactory constraintValidatorFactory, - HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext) { - this.annotationDescriptor = annotationDescriptor; - this.validatedType = validatorType; - this.constraintValidatorFactory = constraintValidatorFactory; - this.constraintValidatorInitializationContext = constraintValidatorInitializationContext; - this.hashCode = createHashCode(); - } - - public ConstraintValidatorFactory getConstraintValidatorFactory() { - return constraintValidatorFactory; - } - - public HibernateConstraintValidatorInitializationContext getConstraintValidatorInitializationContext() { - return constraintValidatorInitializationContext; - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - // no need to check for the type here considering it's only used in a typed map - if ( o == null ) { - return false; - } - - CacheKey other = (CacheKey) o; - - if ( !annotationDescriptor.equals( other.annotationDescriptor ) ) { - return false; - } - if ( !validatedType.equals( other.validatedType ) ) { - return false; - } - if ( !constraintValidatorFactory.equals( other.constraintValidatorFactory ) ) { - return false; - } - if ( !constraintValidatorInitializationContext.equals( other.constraintValidatorInitializationContext ) ) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - return hashCode; - } - - private int createHashCode() { - int result = annotationDescriptor.hashCode(); - result = 31 * result + validatedType.hashCode(); - result = 31 * result + constraintValidatorFactory.hashCode(); - result = 31 * result + constraintValidatorInitializationContext.hashCode(); - return result; - } - } + HibernateConstraintValidatorInitializationContext getDefaultConstraintValidatorInitializationContext(); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManagerImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManagerImpl.java new file mode 100644 index 0000000000..e39d09d051 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManagerImpl.java @@ -0,0 +1,363 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.constraintvalidation; + +import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; + +import java.lang.annotation.Annotation; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; + +import javax.validation.ConstraintDeclarationException; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorFactory; +import javax.validation.metadata.ConstraintDescriptor; + +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidator; +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; +import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; +import org.hibernate.validator.internal.util.Contracts; +import org.hibernate.validator.internal.util.TypeHelper; +import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; + +/** + * Default implementation of the {@link ConstraintValidatorManager}. + * + * @author Hardy Ferentschik + */ +public class ConstraintValidatorManagerImpl implements ConstraintValidatorManager { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + /** + * The explicit or implicit default constraint validator factory. We always cache {@code ConstraintValidator} + * instances if they are created via the default instance and with the default initialization context. Constraint + * validator instances created via other factory instances (specified eg via {@code ValidatorFactory#usingContext()} + * or initialization context are only cached for the most recently used factory and context. + */ + private final ConstraintValidatorFactory defaultConstraintValidatorFactory; + + /** + * The explicit or implicit default constraint validator initialization context. We always cache + * {@code ConstraintValidator} instances if they are created via the default instance and with the default context. + * Constraint validator instances created via other factory instances (specified eg via + * {@code ValidatorFactory#usingContext()} or initialization context are only cached for the most recently used + * factory and context. + */ + private final HibernateConstraintValidatorInitializationContext defaultConstraintValidatorInitializationContext; + + /** + * The most recently used non default constraint validator factory. + */ + private volatile ConstraintValidatorFactory mostRecentlyUsedNonDefaultConstraintValidatorFactory; + + /** + * The most recently used non default constraint validator initialization context. + */ + private volatile HibernateConstraintValidatorInitializationContext mostRecentlyUsedNonDefaultConstraintValidatorInitializationContext; + + /** + * Used for synchronizing access to {@link #mostRecentlyUsedNonDefaultConstraintValidatorFactory} (which can be + * null itself). + */ + private final Object mostRecentlyUsedNonDefaultConstraintValidatorFactoryAndInitializationContextMutex = new Object(); + + /** + * Cache of initialized {@code ConstraintValidator} instances keyed against validated type, annotation, + * constraint validator factory and constraint validator initialization context ({@code CacheKey}). + */ + private final ConcurrentHashMap> constraintValidatorCache; + + /** + * Creates a new {@code ConstraintValidatorManager}. + * + * @param defaultConstraintValidatorFactory the default validator factory + * @param defaultConstraintValidatorInitializationContext the default initialization context + */ + public ConstraintValidatorManagerImpl(ConstraintValidatorFactory defaultConstraintValidatorFactory, + HibernateConstraintValidatorInitializationContext defaultConstraintValidatorInitializationContext) { + this.defaultConstraintValidatorFactory = defaultConstraintValidatorFactory; + this.defaultConstraintValidatorInitializationContext = defaultConstraintValidatorInitializationContext; + this.constraintValidatorCache = new ConcurrentHashMap<>(); + } + + /** + * @param validatedValueType the type of the value to be validated. Cannot be {@code null}. + * @param descriptor the constraint descriptor for which to get an initialized constraint validator. Cannot be {@code null} + * @param constraintValidatorFactory constraint factory used to instantiate the constraint validator. Cannot be {@code null}. + * @param initializationContext context used on constraint validator initialization + * @param the annotation type + * + * @return an initialized constraint validator for the given type and annotation of the value to be validated. + * {@code null} is returned if no matching constraint validator could be found. + */ + @Override + public ConstraintValidator getInitializedValidator( + Type validatedValueType, + ConstraintDescriptorImpl descriptor, + ConstraintValidatorFactory constraintValidatorFactory, + HibernateConstraintValidatorInitializationContext initializationContext) { + Contracts.assertNotNull( validatedValueType ); + Contracts.assertNotNull( descriptor ); + Contracts.assertNotNull( constraintValidatorFactory ); + Contracts.assertNotNull( initializationContext ); + + CacheKey key = new CacheKey( descriptor.getAnnotationDescriptor(), validatedValueType, constraintValidatorFactory, initializationContext ); + + @SuppressWarnings("unchecked") + ConstraintValidator constraintValidator = (ConstraintValidator) constraintValidatorCache.get( key ); + + if ( constraintValidator == null ) { + constraintValidator = createAndInitializeValidator( validatedValueType, descriptor, constraintValidatorFactory, initializationContext ); + constraintValidator = cacheValidator( key, constraintValidator ); + } + else { + LOG.tracef( "Constraint validator %s found in cache.", constraintValidator ); + } + + return DUMMY_CONSTRAINT_VALIDATOR == constraintValidator ? null : constraintValidator; + } + + private ConstraintValidator cacheValidator(CacheKey key, + ConstraintValidator constraintValidator) { + // we only cache constraint validator instances for the default and most recently used factory + if ( ( key.getConstraintValidatorFactory() != defaultConstraintValidatorFactory + && key.getConstraintValidatorFactory() != mostRecentlyUsedNonDefaultConstraintValidatorFactory ) || + ( key.getConstraintValidatorInitializationContext() != defaultConstraintValidatorInitializationContext + && key.getConstraintValidatorInitializationContext() != mostRecentlyUsedNonDefaultConstraintValidatorInitializationContext ) ) { + + synchronized ( mostRecentlyUsedNonDefaultConstraintValidatorFactoryAndInitializationContextMutex ) { + if ( key.constraintValidatorFactory != mostRecentlyUsedNonDefaultConstraintValidatorFactory || + key.constraintValidatorInitializationContext != mostRecentlyUsedNonDefaultConstraintValidatorInitializationContext ) { + clearEntries( mostRecentlyUsedNonDefaultConstraintValidatorFactory, mostRecentlyUsedNonDefaultConstraintValidatorInitializationContext ); + mostRecentlyUsedNonDefaultConstraintValidatorFactory = key.getConstraintValidatorFactory(); + mostRecentlyUsedNonDefaultConstraintValidatorInitializationContext = key.getConstraintValidatorInitializationContext(); + } + } + } + + @SuppressWarnings("unchecked") + ConstraintValidator cached = (ConstraintValidator) constraintValidatorCache.putIfAbsent( key, constraintValidator ); + + return cached != null ? cached : constraintValidator; + } + + @SuppressWarnings("unchecked") + private ConstraintValidator createAndInitializeValidator( + Type validatedValueType, + ConstraintDescriptorImpl descriptor, + ConstraintValidatorFactory constraintValidatorFactory, + HibernateConstraintValidatorInitializationContext initializationContext) { + + ConstraintValidatorDescriptor validatorDescriptor = findMatchingValidatorDescriptor( descriptor, validatedValueType ); + ConstraintValidator constraintValidator; + + if ( validatorDescriptor == null ) { + constraintValidator = (ConstraintValidator) DUMMY_CONSTRAINT_VALIDATOR; + } + else { + constraintValidator = validatorDescriptor.newInstance( constraintValidatorFactory ); + initializeValidator( descriptor, constraintValidator, initializationContext ); + } + + return constraintValidator; + } + + private void clearEntries(ConstraintValidatorFactory constraintValidatorFactory, HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext) { + Iterator>> cacheEntries = constraintValidatorCache.entrySet().iterator(); + + while ( cacheEntries.hasNext() ) { + Entry> cacheEntry = cacheEntries.next(); + if ( cacheEntry.getKey().getConstraintValidatorFactory() == constraintValidatorFactory && + cacheEntry.getKey().getConstraintValidatorInitializationContext() == constraintValidatorInitializationContext ) { + constraintValidatorFactory.releaseInstance( cacheEntry.getValue() ); + cacheEntries.remove(); + } + } + } + + @Override + public void clear() { + for ( Map.Entry> entry : constraintValidatorCache.entrySet() ) { + entry.getKey().getConstraintValidatorFactory().releaseInstance( entry.getValue() ); + } + constraintValidatorCache.clear(); + } + + @Override + public ConstraintValidatorFactory getDefaultConstraintValidatorFactory() { + return defaultConstraintValidatorFactory; + } + + @Override + public HibernateConstraintValidatorInitializationContext getDefaultConstraintValidatorInitializationContext() { + return defaultConstraintValidatorInitializationContext; + } + + public int numberOfCachedConstraintValidatorInstances() { + return constraintValidatorCache.size(); + } + + /** + * Runs the validator resolution algorithm. + * + * @param validatedValueType The type of the value to be validated (the type of the member/class the constraint was placed on). + * + * @return The class of a matching validator. + */ + private ConstraintValidatorDescriptor findMatchingValidatorDescriptor(ConstraintDescriptorImpl descriptor, Type validatedValueType) { + Map> availableValidatorDescriptors = TypeHelper.getValidatorTypes( + descriptor.getAnnotationType(), + descriptor.getMatchingConstraintValidatorDescriptors() + ); + + List discoveredSuitableTypes = findSuitableValidatorTypes( validatedValueType, availableValidatorDescriptors.keySet() ); + resolveAssignableTypes( discoveredSuitableTypes ); + + if ( discoveredSuitableTypes.size() == 0 ) { + return null; + } + + if ( discoveredSuitableTypes.size() > 1 ) { + throw LOG.getMoreThanOneValidatorFoundForTypeException( validatedValueType, discoveredSuitableTypes ); + } + + Type suitableType = discoveredSuitableTypes.get( 0 ); + return availableValidatorDescriptors.get( suitableType ); + } + + private List findSuitableValidatorTypes(Type type, Iterable availableValidatorTypes) { + List determinedSuitableTypes = newArrayList(); + for ( Type validatorType : availableValidatorTypes ) { + if ( TypeHelper.isAssignable( validatorType, type ) + && !determinedSuitableTypes.contains( validatorType ) ) { + determinedSuitableTypes.add( validatorType ); + } + } + return determinedSuitableTypes; + } + + private void initializeValidator( + ConstraintDescriptor descriptor, + ConstraintValidator constraintValidator, + HibernateConstraintValidatorInitializationContext initializationContext) { + try { + if ( constraintValidator instanceof HibernateConstraintValidator ) { + ( (HibernateConstraintValidator) constraintValidator ).initialize( descriptor, initializationContext ); + } + constraintValidator.initialize( descriptor.getAnnotation() ); + } + catch (RuntimeException e) { + if ( e instanceof ConstraintDeclarationException ) { + throw e; + } + throw LOG.getUnableToInitializeConstraintValidatorException( constraintValidator.getClass(), e ); + } + } + + /** + * Tries to reduce all assignable classes down to a single class. + * + * @param assignableTypes The set of all classes which are assignable to the class of the value to be validated and + * which are handled by at least one of the validators for the specified constraint. + */ + private void resolveAssignableTypes(List assignableTypes) { + if ( assignableTypes.size() == 0 || assignableTypes.size() == 1 ) { + return; + } + + List typesToRemove = new ArrayList<>(); + do { + typesToRemove.clear(); + Type type = assignableTypes.get( 0 ); + for ( int i = 1; i < assignableTypes.size(); i++ ) { + if ( TypeHelper.isAssignable( type, assignableTypes.get( i ) ) ) { + typesToRemove.add( type ); + } + else if ( TypeHelper.isAssignable( assignableTypes.get( i ), type ) ) { + typesToRemove.add( assignableTypes.get( i ) ); + } + } + assignableTypes.removeAll( typesToRemove ); + } while ( typesToRemove.size() > 0 ); + } + + private static final class CacheKey { + // These members are not final for optimization purposes + private ConstraintAnnotationDescriptor annotationDescriptor; + private Type validatedType; + private ConstraintValidatorFactory constraintValidatorFactory; + private HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext; + private int hashCode; + + private CacheKey(ConstraintAnnotationDescriptor annotationDescriptor, Type validatorType, ConstraintValidatorFactory constraintValidatorFactory, + HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext) { + this.annotationDescriptor = annotationDescriptor; + this.validatedType = validatorType; + this.constraintValidatorFactory = constraintValidatorFactory; + this.constraintValidatorInitializationContext = constraintValidatorInitializationContext; + this.hashCode = createHashCode(); + } + + public ConstraintValidatorFactory getConstraintValidatorFactory() { + return constraintValidatorFactory; + } + + public HibernateConstraintValidatorInitializationContext getConstraintValidatorInitializationContext() { + return constraintValidatorInitializationContext; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + // no need to check for the type here considering it's only used in a typed map + if ( o == null ) { + return false; + } + + CacheKey other = (CacheKey) o; + + if ( !annotationDescriptor.equals( other.annotationDescriptor ) ) { + return false; + } + if ( !validatedType.equals( other.validatedType ) ) { + return false; + } + if ( !constraintValidatorFactory.equals( other.constraintValidatorFactory ) ) { + return false; + } + if ( !constraintValidatorInitializationContext.equals( other.constraintValidatorInitializationContext ) ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return hashCode; + } + + private int createHashCode() { + int result = annotationDescriptor.hashCode(); + result = 31 * result + validatedType.hashCode(); + result = 31 * result + constraintValidatorFactory.hashCode(); + result = 31 * result + constraintValidatorInitializationContext.hashCode(); + return result; + } + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/constraintvalidation/ConstraintValidatorManagerTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/constraintvalidation/ConstraintValidatorManagerTest.java index 26f5df550f..42a9a4badf 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/constraintvalidation/ConstraintValidatorManagerTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/constraintvalidation/ConstraintValidatorManagerTest.java @@ -36,7 +36,7 @@ import org.hibernate.validator.internal.constraintvalidators.bv.NotNullValidator; import org.hibernate.validator.internal.engine.DefaultClockProvider; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorFactoryImpl; -import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManagerImpl; import org.hibernate.validator.internal.engine.scripting.DefaultScriptEvaluatorFactory; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; @@ -49,14 +49,14 @@ * @author Gunnar Morling */ public class ConstraintValidatorManagerTest { - private ConstraintValidatorManager constraintValidatorManager; + private ConstraintValidatorManagerImpl constraintValidatorManager; private ConstraintValidatorFactory constraintValidatorFactory; private Validator validator; @BeforeMethod public void setUp() { constraintValidatorFactory = new ConstraintValidatorFactoryImpl(); - constraintValidatorManager = new ConstraintValidatorManager( constraintValidatorFactory, getDummyConstraintValidatorInitializationContext() ); + constraintValidatorManager = new ConstraintValidatorManagerImpl( constraintValidatorFactory, getDummyConstraintValidatorInitializationContext() ); validator = getValidator(); } From 81fe23a2a02e6ff3e9df7e1d5c2560204259d57d Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 27 Nov 2018 17:44:58 +0100 Subject: [PATCH 137/393] HV-1667 Create an interface for BeanMetaDataManager --- .../internal/engine/ValidatorFactoryImpl.java | 3 +- .../metadata/BeanMetaDataManager.java | 223 +--------------- .../metadata/BeanMetaDataManagerImpl.java | 239 ++++++++++++++++++ .../internal/engine/path/PathImplTest.java | 4 +- .../metadata/BeanMetaDataManagerTest.java | 6 +- .../aggregated/ExecutableMetaDataTest.java | 3 +- .../aggregated/ParameterMetaDataTest.java | 5 +- .../aggregated/PropertyMetaDataTest.java | 3 +- 8 files changed, 256 insertions(+), 230 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java index bb3d100513..3b06c4ce33 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java @@ -44,6 +44,7 @@ import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; +import org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; import org.hibernate.validator.internal.metadata.provider.ProgrammaticMetaDataProvider; @@ -311,7 +312,7 @@ Validator createValidator(ConstraintValidatorFactory constraintValidatorFactory, BeanMetaDataManager beanMetaDataManager = beanMetaDataManagers.computeIfAbsent( new BeanMetaDataManagerKey( validatorFactoryScopedContext.getParameterNameProvider(), valueExtractorManager, methodValidationConfiguration ), - key -> new BeanMetaDataManager( + key -> new BeanMetaDataManagerImpl( constraintHelper, executableHelper, typeResolutionHelper, diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java index cab11e9a73..127b7a3652 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManager.java @@ -6,234 +6,17 @@ */ package org.hibernate.validator.internal.metadata; -import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; -import static org.hibernate.validator.internal.util.ConcurrentReferenceHashMap.Option.IDENTITY_COMPARISONS; -import static org.hibernate.validator.internal.util.ConcurrentReferenceHashMap.ReferenceType.SOFT; -import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES; - -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; - -import javax.validation.valueextraction.ValueExtractor; - -import org.hibernate.validator.internal.engine.MethodValidationConfiguration; -import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; -import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl; -import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataBuilder; -import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions; -import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; -import org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider; -import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; -import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; -import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; -import org.hibernate.validator.internal.util.CollectionHelper; -import org.hibernate.validator.internal.util.ConcurrentReferenceHashMap; -import org.hibernate.validator.internal.util.Contracts; -import org.hibernate.validator.internal.util.ExecutableHelper; -import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; -import org.hibernate.validator.internal.util.TypeResolutionHelper; -import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper; -import org.hibernate.validator.internal.util.stereotypes.Immutable; /** * This manager is in charge of providing all constraint related meta data * required by the validation engine. - *

- * Actual retrieval of meta data is delegated to {@link MetaDataProvider} - * implementations which load meta-data based e.g. based on annotations or XML. - *

- *

- * For performance reasons a cache is used which stores all meta data once - * loaded for repeated retrieval. Upon initialization this cache is populated - * with meta data provided by the given eager providers. If the cache - * doesn't contain the meta data for a requested type it will be retrieved on - * demand using the annotation based provider. - *

* - * @author Gunnar Morling - * @author Chris Beckey <cbeckey@paypal.com> * @author Guillaume Smet */ -public class BeanMetaDataManager { - /** - * The default initial capacity for this cache. - */ - private static final int DEFAULT_INITIAL_CAPACITY = 16; - - /** - * The default load factor for this cache. - */ - private static final float DEFAULT_LOAD_FACTOR = 0.75f; - - /** - * The default concurrency level for this cache. - */ - private static final int DEFAULT_CONCURRENCY_LEVEL = 16; - - /** - * Additional metadata providers used for meta data retrieval if - * the XML and/or programmatic configuration is used. - */ - @Immutable - private final List metaDataProviders; - - /** - * Helper for builtin constraints and their validator implementations - */ - private final ConstraintHelper constraintHelper; - - /** - * Used for resolving generic type information. - */ - private final TypeResolutionHelper typeResolutionHelper; - - /** - * The {@link ValueExtractor} manager. - */ - private final ValueExtractorManager valueExtractorManager; - - private final ExecutableParameterNameProvider parameterNameProvider; - - /** - * Used to cache the constraint meta data for validated entities - */ - private final ConcurrentReferenceHashMap, BeanMetaData> beanMetaDataCache; - - /** - * Used for resolving type parameters. Thread-safe. - */ - private final ExecutableHelper executableHelper; - - private final ValidationOrderGenerator validationOrderGenerator; - - /** - * the three properties in this field affect the invocation of rules associated to section 4.5.5 - * of the specification. By default they are all false, if true they allow - * for relaxation of the Liskov Substitution Principal. - */ - private final MethodValidationConfiguration methodValidationConfiguration; - - public BeanMetaDataManager(ConstraintHelper constraintHelper, - ExecutableHelper executableHelper, - TypeResolutionHelper typeResolutionHelper, - ExecutableParameterNameProvider parameterNameProvider, - ValueExtractorManager valueExtractorManager, - JavaBeanHelper javaBeanHelper, - ValidationOrderGenerator validationOrderGenerator, - List optionalMetaDataProviders, - MethodValidationConfiguration methodValidationConfiguration) { - this.constraintHelper = constraintHelper; - this.executableHelper = executableHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; - this.parameterNameProvider = parameterNameProvider; - this.validationOrderGenerator = validationOrderGenerator; - - this.methodValidationConfiguration = methodValidationConfiguration; - - this.beanMetaDataCache = new ConcurrentReferenceHashMap<>( - DEFAULT_INITIAL_CAPACITY, - DEFAULT_LOAD_FACTOR, - DEFAULT_CONCURRENCY_LEVEL, - SOFT, - SOFT, - EnumSet.of( IDENTITY_COMPARISONS ) - ); - - AnnotationProcessingOptions annotationProcessingOptions = getAnnotationProcessingOptionsFromNonDefaultProviders( optionalMetaDataProviders ); - AnnotationMetaDataProvider defaultProvider = new AnnotationMetaDataProvider( - constraintHelper, - typeResolutionHelper, - valueExtractorManager, - javaBeanHelper, - annotationProcessingOptions - ); - List tmpMetaDataProviders = new ArrayList<>( optionalMetaDataProviders.size() + 1 ); - // We add the annotation based metadata provider at the first position so that the entire metadata model is assembled - // first. - // The other optional metadata providers will then contribute their additional metadata to the preexisting model. - // This helps to mitigate issues like HV-1450. - tmpMetaDataProviders.add( defaultProvider ); - tmpMetaDataProviders.addAll( optionalMetaDataProviders ); - - this.metaDataProviders = CollectionHelper.toImmutableList( tmpMetaDataProviders ); - } - - @SuppressWarnings("unchecked") - public BeanMetaData getBeanMetaData(Class beanClass) { - Contracts.assertNotNull( beanClass, MESSAGES.beanTypeCannotBeNull() ); - - BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataCache.computeIfAbsent( beanClass, - bc -> createBeanMetaData( bc ) ); - - return beanMetaData; - } - - public void clear() { - beanMetaDataCache.clear(); - } - - public int numberOfCachedBeanMetaDataInstances() { - return beanMetaDataCache.size(); - } - - /** - * Creates a {@link org.hibernate.validator.internal.metadata.aggregated.BeanMetaData} containing the meta data from all meta - * data providers for the given type and its hierarchy. - * - * @param The type of interest. - * @param clazz The type's class. - * - * @return A bean meta data object for the given type. - */ - private BeanMetaDataImpl createBeanMetaData(Class clazz) { - BeanMetaDataBuilder builder = BeanMetaDataBuilder.getInstance( - constraintHelper, executableHelper, typeResolutionHelper, valueExtractorManager, parameterNameProvider, validationOrderGenerator, clazz, methodValidationConfiguration ); - - for ( MetaDataProvider provider : metaDataProviders ) { - for ( BeanConfiguration beanConfiguration : getBeanConfigurationForHierarchy( provider, clazz ) ) { - builder.add( beanConfiguration ); - } - } - - return builder.build(); - } - - /** - * @return returns the annotation ignores from the non annotation based meta data providers - */ - private AnnotationProcessingOptions getAnnotationProcessingOptionsFromNonDefaultProviders(List optionalMetaDataProviders) { - AnnotationProcessingOptions options = new AnnotationProcessingOptionsImpl(); - for ( MetaDataProvider metaDataProvider : optionalMetaDataProviders ) { - options.merge( metaDataProvider.getAnnotationProcessingOptions() ); - } - - return options; - } - - /** - * Returns a list with the configurations for all types contained in the given type's hierarchy (including - * implemented interfaces) starting at the specified type. - * - * @param beanClass The type of interest. - * @param The type of the class to get the configurations for. - * @return A set with the configurations for the complete hierarchy of the given type. May be empty, but never - * {@code null}. - */ - private List> getBeanConfigurationForHierarchy(MetaDataProvider provider, Class beanClass) { - List> configurations = newArrayList(); +public interface BeanMetaDataManager { - for ( Class clazz : ClassHierarchyHelper.getHierarchy( beanClass ) ) { - BeanConfiguration configuration = provider.getBeanConfiguration( clazz ); - if ( configuration != null ) { - configurations.add( configuration ); - } - } + BeanMetaData getBeanMetaData(Class beanClass); - return configurations; - } + void clear(); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java new file mode 100644 index 0000000000..260c1ba6e0 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java @@ -0,0 +1,239 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.metadata; + +import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; +import static org.hibernate.validator.internal.util.ConcurrentReferenceHashMap.Option.IDENTITY_COMPARISONS; +import static org.hibernate.validator.internal.util.ConcurrentReferenceHashMap.ReferenceType.SOFT; +import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; + +import javax.validation.valueextraction.ValueExtractor; + +import org.hibernate.validator.internal.engine.MethodValidationConfiguration; +import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataBuilder; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider; +import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; +import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; +import org.hibernate.validator.internal.util.CollectionHelper; +import org.hibernate.validator.internal.util.ConcurrentReferenceHashMap; +import org.hibernate.validator.internal.util.Contracts; +import org.hibernate.validator.internal.util.ExecutableHelper; +import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper; +import org.hibernate.validator.internal.util.stereotypes.Immutable; + +/** + * This manager is in charge of providing all constraint related meta data + * required by the validation engine. + *

+ * Actual retrieval of meta data is delegated to {@link MetaDataProvider} + * implementations which load meta-data based e.g. based on annotations or XML. + *

+ * For performance reasons a cache is used which stores all meta data once + * loaded for repeated retrieval. Upon initialization this cache is populated + * with meta data provided by the given eager providers. If the cache + * doesn't contain the meta data for a requested type it will be retrieved on + * demand using the annotation based provider. + * + * @author Gunnar Morling + * @author Chris Beckey <cbeckey@paypal.com> + * @author Guillaume Smet +*/ +public class BeanMetaDataManagerImpl implements BeanMetaDataManager { + /** + * The default initial capacity for this cache. + */ + private static final int DEFAULT_INITIAL_CAPACITY = 16; + + /** + * The default load factor for this cache. + */ + private static final float DEFAULT_LOAD_FACTOR = 0.75f; + + /** + * The default concurrency level for this cache. + */ + private static final int DEFAULT_CONCURRENCY_LEVEL = 16; + + /** + * Additional metadata providers used for meta data retrieval if + * the XML and/or programmatic configuration is used. + */ + @Immutable + private final List metaDataProviders; + + /** + * Helper for builtin constraints and their validator implementations + */ + private final ConstraintHelper constraintHelper; + + /** + * Used for resolving generic type information. + */ + private final TypeResolutionHelper typeResolutionHelper; + + /** + * The {@link ValueExtractor} manager. + */ + private final ValueExtractorManager valueExtractorManager; + + private final ExecutableParameterNameProvider parameterNameProvider; + + /** + * Used to cache the constraint meta data for validated entities + */ + private final ConcurrentReferenceHashMap, BeanMetaData> beanMetaDataCache; + + /** + * Used for resolving type parameters. Thread-safe. + */ + private final ExecutableHelper executableHelper; + + private final ValidationOrderGenerator validationOrderGenerator; + + /** + * the three properties in this field affect the invocation of rules associated to section 4.5.5 + * of the specification. By default they are all false, if true they allow + * for relaxation of the Liskov Substitution Principal. + */ + private final MethodValidationConfiguration methodValidationConfiguration; + + public BeanMetaDataManagerImpl(ConstraintHelper constraintHelper, + ExecutableHelper executableHelper, + TypeResolutionHelper typeResolutionHelper, + ExecutableParameterNameProvider parameterNameProvider, + ValueExtractorManager valueExtractorManager, + JavaBeanHelper javaBeanHelper, + ValidationOrderGenerator validationOrderGenerator, + List optionalMetaDataProviders, + MethodValidationConfiguration methodValidationConfiguration) { + this.constraintHelper = constraintHelper; + this.executableHelper = executableHelper; + this.typeResolutionHelper = typeResolutionHelper; + this.valueExtractorManager = valueExtractorManager; + this.parameterNameProvider = parameterNameProvider; + this.validationOrderGenerator = validationOrderGenerator; + + this.methodValidationConfiguration = methodValidationConfiguration; + + this.beanMetaDataCache = new ConcurrentReferenceHashMap<>( + DEFAULT_INITIAL_CAPACITY, + DEFAULT_LOAD_FACTOR, + DEFAULT_CONCURRENCY_LEVEL, + SOFT, + SOFT, + EnumSet.of( IDENTITY_COMPARISONS ) + ); + + AnnotationProcessingOptions annotationProcessingOptions = getAnnotationProcessingOptionsFromNonDefaultProviders( optionalMetaDataProviders ); + AnnotationMetaDataProvider defaultProvider = new AnnotationMetaDataProvider( + constraintHelper, + typeResolutionHelper, + valueExtractorManager, + javaBeanHelper, + annotationProcessingOptions + ); + List tmpMetaDataProviders = new ArrayList<>( optionalMetaDataProviders.size() + 1 ); + // We add the annotation based metadata provider at the first position so that the entire metadata model is assembled + // first. + // The other optional metadata providers will then contribute their additional metadata to the preexisting model. + // This helps to mitigate issues like HV-1450. + tmpMetaDataProviders.add( defaultProvider ); + tmpMetaDataProviders.addAll( optionalMetaDataProviders ); + + this.metaDataProviders = CollectionHelper.toImmutableList( tmpMetaDataProviders ); + } + + @Override + @SuppressWarnings("unchecked") + public BeanMetaData getBeanMetaData(Class beanClass) { + Contracts.assertNotNull( beanClass, MESSAGES.beanTypeCannotBeNull() ); + + BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataCache.computeIfAbsent( beanClass, + bc -> createBeanMetaData( bc ) ); + + return beanMetaData; + } + + @Override + public void clear() { + beanMetaDataCache.clear(); + } + + public int numberOfCachedBeanMetaDataInstances() { + return beanMetaDataCache.size(); + } + + /** + * Creates a {@link org.hibernate.validator.internal.metadata.aggregated.BeanMetaData} containing the meta data from all meta + * data providers for the given type and its hierarchy. + * + * @param The type of interest. + * @param clazz The type's class. + * + * @return A bean meta data object for the given type. + */ + private BeanMetaDataImpl createBeanMetaData(Class clazz) { + BeanMetaDataBuilder builder = BeanMetaDataBuilder.getInstance( + constraintHelper, executableHelper, typeResolutionHelper, valueExtractorManager, parameterNameProvider, validationOrderGenerator, clazz, methodValidationConfiguration ); + + for ( MetaDataProvider provider : metaDataProviders ) { + for ( BeanConfiguration beanConfiguration : getBeanConfigurationForHierarchy( provider, clazz ) ) { + builder.add( beanConfiguration ); + } + } + + return builder.build(); + } + + /** + * @return returns the annotation ignores from the non annotation based meta data providers + */ + private AnnotationProcessingOptions getAnnotationProcessingOptionsFromNonDefaultProviders(List optionalMetaDataProviders) { + AnnotationProcessingOptions options = new AnnotationProcessingOptionsImpl(); + for ( MetaDataProvider metaDataProvider : optionalMetaDataProviders ) { + options.merge( metaDataProvider.getAnnotationProcessingOptions() ); + } + + return options; + } + + /** + * Returns a list with the configurations for all types contained in the given type's hierarchy (including + * implemented interfaces) starting at the specified type. + * + * @param beanClass The type of interest. + * @param The type of the class to get the configurations for. + * @return A set with the configurations for the complete hierarchy of the given type. May be empty, but never + * {@code null}. + */ + private List> getBeanConfigurationForHierarchy(MetaDataProvider provider, Class beanClass) { + List> configurations = newArrayList(); + + for ( Class clazz : ClassHierarchyHelper.getHierarchy( beanClass ) ) { + BeanConfiguration configuration = provider.getBeanConfiguration( clazz ); + if ( configuration != null ) { + configurations.add( configuration ); + } + } + + return configurations; + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java index 3f982953bc..ae86af9aa6 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java @@ -33,6 +33,7 @@ import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; +import org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl; import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; @@ -42,7 +43,6 @@ import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.testutils.ValidatorUtil; - import org.testng.annotations.Test; /** @@ -193,7 +193,7 @@ public void testNonStringMapKey() { public void testCreationOfExecutablePath() throws Exception { Method executable = Container.class.getMethod( "addItem", Key.class, Item.class ); - BeanMetaDataManager beanMetaDataManager = new BeanMetaDataManager( + BeanMetaDataManager beanMetaDataManager = new BeanMetaDataManagerImpl( new ConstraintHelper(), new ExecutableHelper( new TypeResolutionHelper() ), new TypeResolutionHelper(), diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java index e66c711745..67ed249488 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java @@ -24,7 +24,7 @@ import org.hibernate.validator.internal.engine.MethodValidationConfiguration; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.BeanMetaDataManager; +import org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; @@ -48,11 +48,11 @@ public class BeanMetaDataManagerTest { private static final int LOOP_COUNT = 100000; private static final int ARRAY_ALLOCATION_SIZE = 100000; - private BeanMetaDataManager metaDataManager; + private BeanMetaDataManagerImpl metaDataManager; @BeforeMethod public void setUpBeanMetaDataManager() { - metaDataManager = new BeanMetaDataManager( + metaDataManager = new BeanMetaDataManagerImpl( new ConstraintHelper(), new ExecutableHelper( new TypeResolutionHelper() ), new TypeResolutionHelper(), diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java index 67d2e47713..ab4b283fb3 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java @@ -27,6 +27,7 @@ import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; +import org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; @@ -57,7 +58,7 @@ public class ExecutableMetaDataTest { @BeforeMethod public void setupBeanMetaData() { - beanMetaDataManager = new BeanMetaDataManager( + beanMetaDataManager = new BeanMetaDataManagerImpl( new ConstraintHelper(), new ExecutableHelper( new TypeResolutionHelper() ), new TypeResolutionHelper(), diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java index adf433af8c..5748cc5048 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java @@ -28,6 +28,7 @@ import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; +import org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; import org.hibernate.validator.internal.metadata.aggregated.ParameterMetaData; @@ -57,7 +58,7 @@ public class ParameterMetaDataTest { @BeforeMethod public void setupBeanMetaData() { - BeanMetaDataManager beanMetaDataManager = new BeanMetaDataManager( + BeanMetaDataManager beanMetaDataManager = new BeanMetaDataManagerImpl( new ConstraintHelper(), new ExecutableHelper( new TypeResolutionHelper() ), new TypeResolutionHelper(), @@ -128,7 +129,7 @@ public void parameterNameInInheritanceHierarchy() throws Exception { // // The failure rate on my current VM before fixing the bug is 50%. // Running it in a loop does not improve the odds of failure: all tests will pass or fail for all loop run. - BeanMetaDataManager beanMetaDataManager = new BeanMetaDataManager( + BeanMetaDataManager beanMetaDataManager = new BeanMetaDataManagerImpl( new ConstraintHelper(), new ExecutableHelper( new TypeResolutionHelper() ), new TypeResolutionHelper(), diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java index 4f3c2616aa..fe7a328cc4 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java @@ -21,6 +21,7 @@ import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; +import org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl; import org.hibernate.validator.internal.metadata.aggregated.PropertyMetaData; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; @@ -41,7 +42,7 @@ public class PropertyMetaDataTest { @BeforeMethod public void setupBeanMetaDataManager() { - beanMetaDataManager = new BeanMetaDataManager( + beanMetaDataManager = new BeanMetaDataManagerImpl( new ConstraintHelper(), new ExecutableHelper( new TypeResolutionHelper() ), new TypeResolutionHelper(), From 0eca695a617e7bb2419436c8c65af24f0dd6dd26 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 27 Nov 2018 17:41:37 +0100 Subject: [PATCH 138/393] HV-1667 Allow specific implementations of configuration classes and interfaces --- .../BaseHibernateValidatorConfiguration.java | 338 +++++++++ .../HibernateValidatorConfiguration.java | 324 +------- .../engine/AbstractConfigurationImpl.java | 693 ++++++++++++++++++ .../internal/engine/ConfigurationImpl.java | 660 +---------------- .../ValidatorFactoryConfigurationHelper.java | 12 +- 5 files changed, 1042 insertions(+), 985 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java diff --git a/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java new file mode 100644 index 0000000000..0b2450ddb4 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java @@ -0,0 +1,338 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator; + +import java.time.Duration; +import java.util.Set; + +import javax.validation.Configuration; +import javax.validation.TraversableResolver; +import javax.validation.constraints.Future; +import javax.validation.constraints.FutureOrPresent; +import javax.validation.constraints.Past; +import javax.validation.constraints.PastOrPresent; +import javax.validation.valueextraction.ValueExtractor; + +import org.hibernate.validator.cfg.ConstraintMapping; +import org.hibernate.validator.constraints.ParameterScriptAssert; +import org.hibernate.validator.constraints.ScriptAssert; +import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; +import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; +import org.hibernate.validator.spi.scripting.ScriptEvaluator; +import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; + +/** + * Base interface for Hibernate Validator specific configurations. + *

+ * Should not be used directly, prefer {@link HibernateValidatorConfiguration}. + * + * @author Emmanuel Bernard + * @author Gunnar Morling + * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI + * @author Hardy Ferentschik + * @author Chris Beckey <cbeckey@paypal.com> + */ +public interface BaseHibernateValidatorConfiguration> extends Configuration { + /** + * Property corresponding to the {@link #failFast} method. + * Accepts {@code true} or {@code false}. Defaults to {@code false}. + */ + String FAIL_FAST = "hibernate.validator.fail_fast"; + + /** + * Property corresponding to the {@link #allowOverridingMethodAlterParameterConstraint} method. + * Accepts {@code true} or {@code false}. + * Defaults to {@code false}. + */ + String ALLOW_PARAMETER_CONSTRAINT_OVERRIDE = "hibernate.validator.allow_parameter_constraint_override"; + + /** + * Property corresponding to the {@link #allowMultipleCascadedValidationOnReturnValues} method. + * Accepts {@code true} or {@code false}. + * Defaults to {@code false}. + */ + String ALLOW_MULTIPLE_CASCADED_VALIDATION_ON_RESULT = "hibernate.validator.allow_multiple_cascaded_validation_on_result"; + + /** + * Property corresponding to the {@link #allowParallelMethodsDefineParameterConstraints} method. + * Accepts {@code true} or {@code false}. + * Defaults to {@code false}. + */ + String ALLOW_PARALLEL_METHODS_DEFINE_PARAMETER_CONSTRAINTS = "hibernate.validator.allow_parallel_method_parameter_constraint"; + + /** + * @deprecated planned for removal. Use hibernate.validator.constraint_mapping_contributors instead. + * @since 5.2 + */ + @Deprecated + String CONSTRAINT_MAPPING_CONTRIBUTOR = "hibernate.validator.constraint_mapping_contributor"; + + /** + * Property for configuring constraint mapping contributors, allowing to set up one or more constraint mappings for + * the default validator factory. Accepts a String with the comma separated fully-qualified class names of one or more + * {@link org.hibernate.validator.spi.cfg.ConstraintMappingContributor} implementations. + * + * @since 5.3 + */ + String CONSTRAINT_MAPPING_CONTRIBUTORS = "hibernate.validator.constraint_mapping_contributors"; + + /** + * Property corresponding to the {@link #enableTraversableResolverResultCache(boolean)}. + * Accepts {@code true} or {@code false}. + * Defaults to {@code true}. + * + * @since 6.0.3 + */ + String ENABLE_TRAVERSABLE_RESOLVER_RESULT_CACHE = "hibernate.validator.enable_traversable_resolver_result_cache"; + + /** + * Property for configuring the script evaluator factory, allowing to set up which factory will be used to create + * {@link ScriptEvaluator}s for evaluation of script expressions in + * {@link ScriptAssert} and {@link ParameterScriptAssert} + * constraints. A fully qualified name of a class implementing {@link ScriptEvaluatorFactory} is expected as a value. + * + * @since 6.0.3 + */ + @Incubating + String SCRIPT_EVALUATOR_FACTORY_CLASSNAME = "hibernate.validator.script_evaluator_factory"; + + /** + * Property for configuring temporal validation tolerance, allowing to set the acceptable margin of error when + * comparing date/time in temporal constraints. In milliseconds. + * + * @since 6.0.5 + */ + @Incubating + String TEMPORAL_VALIDATION_TOLERANCE = "hibernate.validator.temporal_validation_tolerance"; + + /** + * Property for configuring the getter property selection strategy, allowing to set which rules will be applied + * to determine if a method is a valid JavaBean getter. + * + * @since 6.1.0 + */ + @Incubating + String GETTER_PROPERTY_SELECTION_STRATEGY_CLASSNAME = "hibernate.validator.getter_property_selection_strategy"; + + /** + *

+ * Returns the {@link ResourceBundleLocator} used by the + * {@link Configuration#getDefaultMessageInterpolator() default message + * interpolator} to load user-provided resource bundles. In conformance with + * the specification this default locator retrieves the bundle + * "ValidationMessages". + *

+ *

+ * This locator can be used as delegate for custom locators when setting a + * customized {@link org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator}: + *

+ *
+	 * {@code
+	 * 	HibernateValidatorConfiguration configure =
+	 *    Validation.byProvider(HibernateValidator.class).configure();
+	 *
+	 *  ResourceBundleLocator defaultResourceBundleLocator =
+	 *    configure.getDefaultBundleLocator();
+	 *  ResourceBundleLocator myResourceBundleLocator =
+	 *    new MyResourceBundleLocator(defaultResourceBundleLocator);
+	 *
+	 *  configure.messageInterpolator(
+	 *    new ResourceBundleMessageInterpolator(myResourceBundleLocator));
+	 * }
+	 * 
+ * + * @return The default {@link ResourceBundleLocator}. Never null. + */ + ResourceBundleLocator getDefaultResourceBundleLocator(); + + /** + * Creates a new constraint mapping which can be used to programmatically configure the constraints for given types. After + * the mapping has been set up, it must be added to this configuration via {@link #addMapping(ConstraintMapping)}. + * + * @return A new constraint mapping. + */ + ConstraintMapping createConstraintMapping(); + + /** + * Returns the default {@link ValueExtractor} implementations as per the + * specification. + * + * @return the default {@code ValueExtractor} implementations compliant + * with the specification + * + * @since 6.0 + */ + @Incubating + Set> getDefaultValueExtractors(); + + /** + * Adds the specified {@link ConstraintMapping} instance to the configuration. Constraints configured in {@code mapping} + * will be added to the constraints configured via annotations and/or xml. + * + * @param mapping {@code ConstraintMapping} instance containing programmatic configured constraints + * + * @return {@code this} following the chaining method pattern + * + * @throws IllegalArgumentException if {@code mapping} is {@code null} + */ + S addMapping(ConstraintMapping mapping); + + /** + * En- or disables the fail fast mode. When fail fast is enabled the validation + * will stop on the first constraint violation detected. + * + * @param failFast {@code true} to enable fail fast, {@code false} otherwise. + * + * @return {@code this} following the chaining method pattern + */ + S failFast(boolean failFast); + + /** + * Sets the class loader to be used for loading user-provided resources: + *
    + *
  • XML descriptors ({@code META-INF/validation.xml} as well as XML constraint mappings)
  • + *
  • classes specified by name in XML descriptors (e.g. custom message interpolators etc.)
  • + *
  • the {@code ValidationMessages} resource bundle
  • + *
+ * If no class loader is given, these resources will be obtained through the thread context class loader and as a + * last fallback through Hibernate Validator's own class loader. + * + * @param externalClassLoader The class loader for loading user-provided resources. + * + * @return {@code this} following the chaining method pattern + * + * @since 5.2 + */ + S externalClassLoader(ClassLoader externalClassLoader); + + /** + * Define whether overriding methods that override constraints should throw a {@code ConstraintDefinitionException}. + * The default value is {@code false}, i.e. do not allow. + *

+ * See Section 4.5.5 of the JSR 380 specification, specifically + *

+	 * "In sub types (be it sub classes/interfaces or interface implementations), no parameter constraints may
+	 * be declared on overridden or implemented methods, nor may parameters be marked for cascaded validation.
+	 * This would pose a strengthening of preconditions to be fulfilled by the caller."
+	 * 
+ * + * @param allow flag determining whether validation will allow overriding to alter parameter constraints. + * + * @return {@code this} following the chaining method pattern + * + * @since 5.3 + */ + S allowOverridingMethodAlterParameterConstraint(boolean allow); + + /** + * Define whether more than one constraint on a return value may be marked for cascading validation are allowed. + * The default value is {@code false}, i.e. do not allow. + *

+ * See Section 4.5.5 of the JSR 380 specification, specifically + *

+	 * "One must not mark a method return value for cascaded validation more than once in a line of a class hierarchy.
+	 * In other words, overriding methods on sub types (be it sub classes/interfaces or interface implementations)
+	 * cannot mark the return value for cascaded validation if the return value has already been marked on the
+	 * overridden method of the super type or interface."
+	 * 
+ * + * @param allow flag determining whether validation will allow multiple cascaded validation on return values. + * + * @return {@code this} following the chaining method pattern + * + * @since 5.3 + */ + S allowMultipleCascadedValidationOnReturnValues(boolean allow); + + /** + * Define whether parallel methods that define constraints should throw a {@code ConstraintDefinitionException}. The + * default value is {@code false}, i.e. do not allow. + *

+ * See Section 4.5.5 of the JSR 380 specification, specifically + *

+	 * "If a sub type overrides/implements a method originally defined in several parallel types of the hierarchy
+	 * (e.g. two interfaces not extending each other, or a class and an interface not implemented by said class),
+	 * no parameter constraints may be declared for that method at all nor parameters be marked for cascaded validation.
+	 * This again is to avoid an unexpected strengthening of preconditions to be fulfilled by the caller."
+	 * 
+ * + * @param allow flag determining whether validation will allow parameter constraints in parallel hierarchies + * + * @return {@code this} following the chaining method pattern + * + * @since 5.3 + */ + S allowParallelMethodsDefineParameterConstraints(boolean allow); + + /** + * Define whether the per validation call caching of {@link TraversableResolver} results is enabled. The default + * value is {@code true}, i.e. the caching is enabled. + *

+ * This behavior was initially introduced to cache the {@code JPATraversableResolver} results but the map lookups it + * introduces can be counterproductive when the {@code TraversableResolver} calls are very fast. + * + * @param enabled flag determining whether per validation call caching is enabled for {@code TraversableResolver} + * results. + * + * @return {@code this} following the chaining method pattern + * + * @since 6.0.3 + */ + S enableTraversableResolverResultCache(boolean enabled); + + /** + * Allows to specify a custom {@link ScriptEvaluatorFactory} responsible for creating {@link ScriptEvaluator}s + * used to evaluate script expressions for {@link ScriptAssert} and {@link ParameterScriptAssert} constraints. + * + * @param scriptEvaluatorFactory the {@link ScriptEvaluatorFactory} to be used + * + * @return {@code this} following the chaining method pattern + * + * @since 6.0.3 + */ + @Incubating + S scriptEvaluatorFactory(ScriptEvaluatorFactory scriptEvaluatorFactory); + + /** + * Allows to set the acceptable margin of error when comparing date/time in temporal constraints such as + * {@link Past}/{@link PastOrPresent} and {@link Future}/{@link FutureOrPresent}. + * + * @param temporalValidationTolerance the acceptable tolerance + * + * @return {@code this} following the chaining method pattern + * + * @since 6.0.5 + */ + @Incubating + S temporalValidationTolerance(Duration temporalValidationTolerance); + + /** + * Allows to set a payload which will be passed to the constraint validators. If the method is called multiple + * times, only the payload passed last will be propagated. + * + * @param constraintValidatorPayload the payload passed to constraint validators + * + * @return {@code this} following the chaining method pattern + * + * @since 6.0.8 + */ + @Incubating + S constraintValidatorPayload(Object constraintValidatorPayload); + + /** + * Allows to set a getter property selection strategy defining the rules determining if a method is a getter + * or not. + * + * @param getterPropertySelectionStrategy the {@link GetterPropertySelectionStrategy} to be used + * + * @return {@code this} following the chaining method pattern + * + * @since 6.1.0 + */ + @Incubating + S getterPropertySelectionStrategy(GetterPropertySelectionStrategy getterPropertySelectionStrategy); +} diff --git a/engine/src/main/java/org/hibernate/validator/HibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/HibernateValidatorConfiguration.java index 37ef2cba01..186a7e150e 100644 --- a/engine/src/main/java/org/hibernate/validator/HibernateValidatorConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/HibernateValidatorConfiguration.java @@ -6,332 +6,12 @@ */ package org.hibernate.validator; -import java.time.Duration; -import java.util.Set; - -import javax.validation.Configuration; -import javax.validation.TraversableResolver; -import javax.validation.constraints.Future; -import javax.validation.constraints.FutureOrPresent; -import javax.validation.constraints.Past; -import javax.validation.constraints.PastOrPresent; -import javax.validation.valueextraction.ValueExtractor; - -import org.hibernate.validator.cfg.ConstraintMapping; -import org.hibernate.validator.constraints.ParameterScriptAssert; -import org.hibernate.validator.constraints.ScriptAssert; -import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; -import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; -import org.hibernate.validator.spi.scripting.ScriptEvaluator; -import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; - /** * Uniquely identifies Hibernate Validator in the Bean Validation bootstrap * strategy. Also contains Hibernate Validator specific configurations. * - * @author Emmanuel Bernard - * @author Gunnar Morling - * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI - * @author Hardy Ferentschik - * @author Chris Beckey <cbeckey@paypal.com> + * @author Guillaume Smet */ -public interface HibernateValidatorConfiguration extends Configuration { - /** - * Property corresponding to the {@link #failFast} method. - * Accepts {@code true} or {@code false}. Defaults to {@code false}. - */ - String FAIL_FAST = "hibernate.validator.fail_fast"; - - /** - * Property corresponding to the {@link #allowOverridingMethodAlterParameterConstraint} method. - * Accepts {@code true} or {@code false}. - * Defaults to {@code false}. - */ - String ALLOW_PARAMETER_CONSTRAINT_OVERRIDE = "hibernate.validator.allow_parameter_constraint_override"; - - /** - * Property corresponding to the {@link #allowMultipleCascadedValidationOnReturnValues} method. - * Accepts {@code true} or {@code false}. - * Defaults to {@code false}. - */ - String ALLOW_MULTIPLE_CASCADED_VALIDATION_ON_RESULT = "hibernate.validator.allow_multiple_cascaded_validation_on_result"; - - /** - * Property corresponding to the {@link #allowParallelMethodsDefineParameterConstraints} method. - * Accepts {@code true} or {@code false}. - * Defaults to {@code false}. - */ - String ALLOW_PARALLEL_METHODS_DEFINE_PARAMETER_CONSTRAINTS = "hibernate.validator.allow_parallel_method_parameter_constraint"; - - /** - * @deprecated planned for removal. Use hibernate.validator.constraint_mapping_contributors instead. - * @since 5.2 - */ - @Deprecated - String CONSTRAINT_MAPPING_CONTRIBUTOR = "hibernate.validator.constraint_mapping_contributor"; - - /** - * Property for configuring constraint mapping contributors, allowing to set up one or more constraint mappings for - * the default validator factory. Accepts a String with the comma separated fully-qualified class names of one or more - * {@link org.hibernate.validator.spi.cfg.ConstraintMappingContributor} implementations. - * - * @since 5.3 - */ - String CONSTRAINT_MAPPING_CONTRIBUTORS = "hibernate.validator.constraint_mapping_contributors"; - - /** - * Property corresponding to the {@link #enableTraversableResolverResultCache(boolean)}. - * Accepts {@code true} or {@code false}. - * Defaults to {@code true}. - * - * @since 6.0.3 - */ - String ENABLE_TRAVERSABLE_RESOLVER_RESULT_CACHE = "hibernate.validator.enable_traversable_resolver_result_cache"; - - /** - * Property for configuring the script evaluator factory, allowing to set up which factory will be used to create - * {@link ScriptEvaluator}s for evaluation of script expressions in - * {@link ScriptAssert} and {@link ParameterScriptAssert} - * constraints. A fully qualified name of a class implementing {@link ScriptEvaluatorFactory} is expected as a value. - * - * @since 6.0.3 - */ - @Incubating - String SCRIPT_EVALUATOR_FACTORY_CLASSNAME = "hibernate.validator.script_evaluator_factory"; - - /** - * Property for configuring temporal validation tolerance, allowing to set the acceptable margin of error when - * comparing date/time in temporal constraints. In milliseconds. - * - * @since 6.0.5 - */ - @Incubating - String TEMPORAL_VALIDATION_TOLERANCE = "hibernate.validator.temporal_validation_tolerance"; - - /** - * Property for configuring the getter property selection strategy, allowing to set which rules will be applied - * to determine if a method is a valid JavaBean getter. - * - * @since 6.1.0 - */ - @Incubating - String GETTER_PROPERTY_SELECTION_STRATEGY_CLASSNAME = "hibernate.validator.getter_property_selection_strategy"; - - /** - *

- * Returns the {@link ResourceBundleLocator} used by the - * {@link Configuration#getDefaultMessageInterpolator() default message - * interpolator} to load user-provided resource bundles. In conformance with - * the specification this default locator retrieves the bundle - * "ValidationMessages". - *

- *

- * This locator can be used as delegate for custom locators when setting a - * customized {@link org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator}: - *

- *
-	 * {@code
-	 * 	HibernateValidatorConfiguration configure =
-	 *    Validation.byProvider(HibernateValidator.class).configure();
-	 *
-	 *  ResourceBundleLocator defaultResourceBundleLocator =
-	 *    configure.getDefaultBundleLocator();
-	 *  ResourceBundleLocator myResourceBundleLocator =
-	 *    new MyResourceBundleLocator(defaultResourceBundleLocator);
-	 *
-	 *  configure.messageInterpolator(
-	 *    new ResourceBundleMessageInterpolator(myResourceBundleLocator));
-	 * }
-	 * 
- * - * @return The default {@link ResourceBundleLocator}. Never null. - */ - ResourceBundleLocator getDefaultResourceBundleLocator(); - - /** - * Creates a new constraint mapping which can be used to programmatically configure the constraints for given types. After - * the mapping has been set up, it must be added to this configuration via {@link #addMapping(ConstraintMapping)}. - * - * @return A new constraint mapping. - */ - ConstraintMapping createConstraintMapping(); - - /** - * Returns the default {@link ValueExtractor} implementations as per the - * specification. - * - * @return the default {@code ValueExtractor} implementations compliant - * with the specification - * - * @since 6.0 - */ - @Incubating - Set> getDefaultValueExtractors(); - - /** - * Adds the specified {@link ConstraintMapping} instance to the configuration. Constraints configured in {@code mapping} - * will be added to the constraints configured via annotations and/or xml. - * - * @param mapping {@code ConstraintMapping} instance containing programmatic configured constraints - * - * @return {@code this} following the chaining method pattern - * - * @throws IllegalArgumentException if {@code mapping} is {@code null} - */ - HibernateValidatorConfiguration addMapping(ConstraintMapping mapping); - - /** - * En- or disables the fail fast mode. When fail fast is enabled the validation - * will stop on the first constraint violation detected. - * - * @param failFast {@code true} to enable fail fast, {@code false} otherwise. - * - * @return {@code this} following the chaining method pattern - */ - HibernateValidatorConfiguration failFast(boolean failFast); - - /** - * Sets the class loader to be used for loading user-provided resources: - *
    - *
  • XML descriptors ({@code META-INF/validation.xml} as well as XML constraint mappings)
  • - *
  • classes specified by name in XML descriptors (e.g. custom message interpolators etc.)
  • - *
  • the {@code ValidationMessages} resource bundle
  • - *
- * If no class loader is given, these resources will be obtained through the thread context class loader and as a - * last fallback through Hibernate Validator's own class loader. - * - * @param externalClassLoader The class loader for loading user-provided resources. - * - * @return {@code this} following the chaining method pattern - * - * @since 5.2 - */ - HibernateValidatorConfiguration externalClassLoader(ClassLoader externalClassLoader); - - /** - * Define whether overriding methods that override constraints should throw a {@code ConstraintDefinitionException}. - * The default value is {@code false}, i.e. do not allow. - *

- * See Section 4.5.5 of the JSR 380 specification, specifically - *

-	 * "In sub types (be it sub classes/interfaces or interface implementations), no parameter constraints may
-	 * be declared on overridden or implemented methods, nor may parameters be marked for cascaded validation.
-	 * This would pose a strengthening of preconditions to be fulfilled by the caller."
-	 * 
- * - * @param allow flag determining whether validation will allow overriding to alter parameter constraints. - * - * @return {@code this} following the chaining method pattern - * - * @since 5.3 - */ - HibernateValidatorConfiguration allowOverridingMethodAlterParameterConstraint(boolean allow); - - /** - * Define whether more than one constraint on a return value may be marked for cascading validation are allowed. - * The default value is {@code false}, i.e. do not allow. - *

- * See Section 4.5.5 of the JSR 380 specification, specifically - *

-	 * "One must not mark a method return value for cascaded validation more than once in a line of a class hierarchy.
-	 * In other words, overriding methods on sub types (be it sub classes/interfaces or interface implementations)
-	 * cannot mark the return value for cascaded validation if the return value has already been marked on the
-	 * overridden method of the super type or interface."
-	 * 
- * - * @param allow flag determining whether validation will allow multiple cascaded validation on return values. - * - * @return {@code this} following the chaining method pattern - * - * @since 5.3 - */ - HibernateValidatorConfiguration allowMultipleCascadedValidationOnReturnValues(boolean allow); - - /** - * Define whether parallel methods that define constraints should throw a {@code ConstraintDefinitionException}. The - * default value is {@code false}, i.e. do not allow. - *

- * See Section 4.5.5 of the JSR 380 specification, specifically - *

-	 * "If a sub type overrides/implements a method originally defined in several parallel types of the hierarchy
-	 * (e.g. two interfaces not extending each other, or a class and an interface not implemented by said class),
-	 * no parameter constraints may be declared for that method at all nor parameters be marked for cascaded validation.
-	 * This again is to avoid an unexpected strengthening of preconditions to be fulfilled by the caller."
-	 * 
- * - * @param allow flag determining whether validation will allow parameter constraints in parallel hierarchies - * - * @return {@code this} following the chaining method pattern - * - * @since 5.3 - */ - HibernateValidatorConfiguration allowParallelMethodsDefineParameterConstraints(boolean allow); - - /** - * Define whether the per validation call caching of {@link TraversableResolver} results is enabled. The default - * value is {@code true}, i.e. the caching is enabled. - *

- * This behavior was initially introduced to cache the {@code JPATraversableResolver} results but the map lookups it - * introduces can be counterproductive when the {@code TraversableResolver} calls are very fast. - * - * @param enabled flag determining whether per validation call caching is enabled for {@code TraversableResolver} - * results. - * - * @return {@code this} following the chaining method pattern - * - * @since 6.0.3 - */ - HibernateValidatorConfiguration enableTraversableResolverResultCache(boolean enabled); - - /** - * Allows to specify a custom {@link ScriptEvaluatorFactory} responsible for creating {@link ScriptEvaluator}s - * used to evaluate script expressions for {@link ScriptAssert} and {@link ParameterScriptAssert} constraints. - * - * @param scriptEvaluatorFactory the {@link ScriptEvaluatorFactory} to be used - * - * @return {@code this} following the chaining method pattern - * - * @since 6.0.3 - */ - @Incubating - HibernateValidatorConfiguration scriptEvaluatorFactory(ScriptEvaluatorFactory scriptEvaluatorFactory); - - /** - * Allows to set the acceptable margin of error when comparing date/time in temporal constraints such as - * {@link Past}/{@link PastOrPresent} and {@link Future}/{@link FutureOrPresent}. - * - * @param temporalValidationTolerance the acceptable tolerance - * - * @return {@code this} following the chaining method pattern - * - * @since 6.0.5 - */ - @Incubating - HibernateValidatorConfiguration temporalValidationTolerance(Duration temporalValidationTolerance); - - /** - * Allows to set a payload which will be passed to the constraint validators. If the method is called multiple - * times, only the payload passed last will be propagated. - * - * @param constraintValidatorPayload the payload passed to constraint validators - * - * @return {@code this} following the chaining method pattern - * - * @since 6.0.8 - */ - @Incubating - HibernateValidatorConfiguration constraintValidatorPayload(Object constraintValidatorPayload); +public interface HibernateValidatorConfiguration extends BaseHibernateValidatorConfiguration { - /** - * Allows to set a getter property selection strategy defining the rules determining if a method is a getter - * or not. - * - * @param getterPropertySelectionStrategy the {@link GetterPropertySelectionStrategy} to be used - * - * @return {@code this} following the chaining method pattern - * - * @since 6.1.0 - */ - @Incubating - HibernateValidatorConfiguration getterPropertySelectionStrategy(GetterPropertySelectionStrategy getterPropertySelectionStrategy); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java new file mode 100644 index 0000000000..728db7c919 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java @@ -0,0 +1,693 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine; + +import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; +import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.invoke.MethodHandles; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.time.Duration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.validation.BootstrapConfiguration; +import javax.validation.ClockProvider; +import javax.validation.ConstraintValidatorFactory; +import javax.validation.MessageInterpolator; +import javax.validation.ParameterNameProvider; +import javax.validation.TraversableResolver; +import javax.validation.ValidationProviderResolver; +import javax.validation.ValidatorFactory; +import javax.validation.spi.BootstrapState; +import javax.validation.spi.ConfigurationState; +import javax.validation.spi.ValidationProvider; +import javax.validation.valueextraction.ValueExtractor; + +import org.hibernate.validator.BaseHibernateValidatorConfiguration; +import org.hibernate.validator.cfg.ConstraintMapping; +import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorFactoryImpl; +import org.hibernate.validator.internal.engine.resolver.TraversableResolvers; +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorDescriptor; +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; +import org.hibernate.validator.internal.util.Contracts; +import org.hibernate.validator.internal.util.Version; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader; +import org.hibernate.validator.internal.util.privilegedactions.GetInstancesFromServiceLoader; +import org.hibernate.validator.internal.util.privilegedactions.SetContextClassLoader; +import org.hibernate.validator.internal.xml.config.ValidationBootstrapParameters; +import org.hibernate.validator.internal.xml.config.ValidationXmlParser; +import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; +import org.hibernate.validator.resourceloading.PlatformResourceBundleLocator; +import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; +import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; +import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; + +/** + * Hibernate specific {@code Configuration} implementation. + * + * @author Emmanuel Bernard + * @author Hardy Ferentschik + * @author Gunnar Morling + * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI + * @author Chris Beckey <cbeckey@paypal.com> + */ +public abstract class AbstractConfigurationImpl> + implements BaseHibernateValidatorConfiguration, ConfigurationState { + + static { + Version.touch(); + } + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + private final ResourceBundleLocator defaultResourceBundleLocator; + + /** + * Built lazily so RBMI and its dependency on EL is only initialized if actually needed + */ + private MessageInterpolator defaultMessageInterpolator; + private MessageInterpolator messageInterpolator; + + private final TraversableResolver defaultTraversableResolver; + private final ConstraintValidatorFactory defaultConstraintValidatorFactory; + private final ParameterNameProvider defaultParameterNameProvider; + private final ClockProvider defaultClockProvider; + + private ValidationProviderResolver providerResolver; + private final ValidationBootstrapParameters validationBootstrapParameters; + private boolean ignoreXmlConfiguration = false; + private final Set configurationStreams = newHashSet(); + private BootstrapConfiguration bootstrapConfiguration; + + private final Map valueExtractorDescriptors = new HashMap<>(); + + // HV-specific options + private final Set programmaticMappings = newHashSet(); + private boolean failFast; + private ClassLoader externalClassLoader; + private final MethodValidationConfiguration.Builder methodValidationConfigurationBuilder = new MethodValidationConfiguration.Builder(); + private boolean traversableResolverResultCacheEnabled = true; + private ScriptEvaluatorFactory scriptEvaluatorFactory; + private Duration temporalValidationTolerance; + private Object constraintValidatorPayload; + private GetterPropertySelectionStrategy getterPropertySelectionStrategy; + + protected AbstractConfigurationImpl(BootstrapState state) { + this(); + if ( state.getValidationProviderResolver() == null ) { + this.providerResolver = state.getDefaultValidationProviderResolver(); + } + else { + this.providerResolver = state.getValidationProviderResolver(); + } + } + + protected AbstractConfigurationImpl(ValidationProvider provider) { + this(); + if ( provider == null ) { + throw LOG.getInconsistentConfigurationException(); + } + this.providerResolver = null; + validationBootstrapParameters.setProvider( provider ); + } + + private AbstractConfigurationImpl() { + this.validationBootstrapParameters = new ValidationBootstrapParameters(); + + this.defaultResourceBundleLocator = new PlatformResourceBundleLocator( + ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES + ); + this.defaultTraversableResolver = TraversableResolvers.getDefault(); + this.defaultConstraintValidatorFactory = new ConstraintValidatorFactoryImpl(); + this.defaultParameterNameProvider = new DefaultParameterNameProvider(); + this.defaultClockProvider = DefaultClockProvider.INSTANCE; + } + + @Override + public final T ignoreXmlConfiguration() { + ignoreXmlConfiguration = true; + return thisAsT(); + } + + @Override + public final T messageInterpolator(MessageInterpolator interpolator) { + if ( LOG.isDebugEnabled() ) { + if ( interpolator != null ) { + LOG.debug( "Setting custom MessageInterpolator of type " + interpolator.getClass().getName() ); + } + } + this.validationBootstrapParameters.setMessageInterpolator( interpolator ); + return thisAsT(); + } + + @Override + public final T traversableResolver(TraversableResolver resolver) { + if ( LOG.isDebugEnabled() ) { + if ( resolver != null ) { + LOG.debug( "Setting custom TraversableResolver of type " + resolver.getClass().getName() ); + } + } + this.validationBootstrapParameters.setTraversableResolver( resolver ); + return thisAsT(); + } + + @Override + public final T enableTraversableResolverResultCache(boolean enabled) { + this.traversableResolverResultCacheEnabled = enabled; + return thisAsT(); + } + + public final boolean isTraversableResolverResultCacheEnabled() { + return traversableResolverResultCacheEnabled; + } + + @Override + public final T constraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) { + if ( LOG.isDebugEnabled() ) { + if ( constraintValidatorFactory != null ) { + LOG.debug( + "Setting custom ConstraintValidatorFactory of type " + constraintValidatorFactory.getClass() + .getName() + ); + } + } + this.validationBootstrapParameters.setConstraintValidatorFactory( constraintValidatorFactory ); + return thisAsT(); + } + + @Override + public T parameterNameProvider(ParameterNameProvider parameterNameProvider) { + if ( LOG.isDebugEnabled() ) { + if ( parameterNameProvider != null ) { + LOG.debug( + "Setting custom ParameterNameProvider of type " + parameterNameProvider.getClass() + .getName() + ); + } + } + this.validationBootstrapParameters.setParameterNameProvider( parameterNameProvider ); + return thisAsT(); + } + + @Override + public T clockProvider(ClockProvider clockProvider) { + if ( LOG.isDebugEnabled() ) { + if ( clockProvider != null ) { + LOG.debug( "Setting custom ClockProvider of type " + clockProvider.getClass().getName() ); + } + } + this.validationBootstrapParameters.setClockProvider( clockProvider ); + return thisAsT(); + } + + @Override + public T addValueExtractor(ValueExtractor extractor) { + Contracts.assertNotNull( extractor, MESSAGES.parameterMustNotBeNull( "extractor" ) ); + + ValueExtractorDescriptor descriptor = new ValueExtractorDescriptor( extractor ); + ValueExtractorDescriptor previous = valueExtractorDescriptors.put( descriptor.getKey(), descriptor ); + + if ( previous != null ) { + throw LOG.getValueExtractorForTypeAndTypeUseAlreadyPresentException( extractor, previous.getValueExtractor() ); + } + + if ( LOG.isDebugEnabled() ) { + LOG.debug( "Adding value extractor " + extractor ); + } + + return thisAsT(); + } + + @Override + public final T addMapping(InputStream stream) { + Contracts.assertNotNull( stream, MESSAGES.inputStreamCannotBeNull() ); + + validationBootstrapParameters.addMapping( stream.markSupported() ? stream : new BufferedInputStream( stream ) ); + return thisAsT(); + } + + @Override + public final T failFast(boolean failFast) { + this.failFast = failFast; + return thisAsT(); + } + + @Override + public T allowOverridingMethodAlterParameterConstraint(boolean allow) { + this.methodValidationConfigurationBuilder.allowOverridingMethodAlterParameterConstraint( allow ); + return thisAsT(); + } + + public boolean isAllowOverridingMethodAlterParameterConstraint() { + return this.methodValidationConfigurationBuilder.isAllowOverridingMethodAlterParameterConstraint(); + } + + @Override + public T allowMultipleCascadedValidationOnReturnValues(boolean allow) { + this.methodValidationConfigurationBuilder.allowMultipleCascadedValidationOnReturnValues( allow ); + return thisAsT(); + } + + public boolean isAllowMultipleCascadedValidationOnReturnValues() { + return this.methodValidationConfigurationBuilder.isAllowMultipleCascadedValidationOnReturnValues(); + } + + @Override + public T allowParallelMethodsDefineParameterConstraints(boolean allow) { + this.methodValidationConfigurationBuilder.allowParallelMethodsDefineParameterConstraints( allow ); + return thisAsT(); + } + + @Override + public T scriptEvaluatorFactory(ScriptEvaluatorFactory scriptEvaluatorFactory) { + Contracts.assertNotNull( scriptEvaluatorFactory, MESSAGES.parameterMustNotBeNull( "scriptEvaluatorFactory" ) ); + + this.scriptEvaluatorFactory = scriptEvaluatorFactory; + return thisAsT(); + } + + @Override + public T temporalValidationTolerance(Duration temporalValidationTolerance) { + Contracts.assertNotNull( temporalValidationTolerance, MESSAGES.parameterMustNotBeNull( "temporalValidationTolerance" ) ); + + this.temporalValidationTolerance = temporalValidationTolerance.abs(); + return thisAsT(); + } + + @Override + public T constraintValidatorPayload(Object constraintValidatorPayload) { + Contracts.assertNotNull( constraintValidatorPayload, MESSAGES.parameterMustNotBeNull( "constraintValidatorPayload" ) ); + + this.constraintValidatorPayload = constraintValidatorPayload; + return thisAsT(); + } + + @Override + public T getterPropertySelectionStrategy(GetterPropertySelectionStrategy getterPropertySelectionStrategy) { + Contracts.assertNotNull( getterPropertySelectionStrategy, MESSAGES.parameterMustNotBeNull( "getterPropertySelectionStrategy" ) ); + + this.getterPropertySelectionStrategy = getterPropertySelectionStrategy; + return thisAsT(); + } + + public boolean isAllowParallelMethodsDefineParameterConstraints() { + return this.methodValidationConfigurationBuilder.isAllowParallelMethodsDefineParameterConstraints(); + } + + public MethodValidationConfiguration getMethodValidationConfiguration() { + return this.methodValidationConfigurationBuilder.build(); + } + + @Override + public final DefaultConstraintMapping createConstraintMapping() { + GetterPropertySelectionStrategy getterPropertySelectionStrategyToUse = null; + if ( getterPropertySelectionStrategy == null ) { + getterPropertySelectionStrategyToUse = new DefaultGetterPropertySelectionStrategy(); + } + else { + getterPropertySelectionStrategyToUse = getterPropertySelectionStrategy; + } + + return new DefaultConstraintMapping( new JavaBeanHelper( getterPropertySelectionStrategyToUse ) ); + } + + @Override + public final T addMapping(ConstraintMapping mapping) { + Contracts.assertNotNull( mapping, MESSAGES.parameterMustNotBeNull( "mapping" ) ); + + this.programmaticMappings.add( (DefaultConstraintMapping) mapping ); + return thisAsT(); + } + + @Override + public final T addProperty(String name, String value) { + if ( value != null ) { + validationBootstrapParameters.addConfigProperty( name, value ); + } + return thisAsT(); + } + + @Override + public T externalClassLoader(ClassLoader externalClassLoader) { + Contracts.assertNotNull( externalClassLoader, MESSAGES.parameterMustNotBeNull( "externalClassLoader" ) ); + this.externalClassLoader = externalClassLoader; + + return thisAsT(); + } + + @Override + public final ValidatorFactory buildValidatorFactory() { + loadValueExtractorsFromServiceLoader(); + parseValidationXml(); + + for ( ValueExtractorDescriptor valueExtractorDescriptor : valueExtractorDescriptors.values() ) { + validationBootstrapParameters.addValueExtractorDescriptor( valueExtractorDescriptor ); + } + + ValidatorFactory factory = null; + try { + if ( isSpecificProvider() ) { + factory = validationBootstrapParameters.getProvider().buildValidatorFactory( this ); + } + else { + final Class> providerClass = validationBootstrapParameters.getProviderClass(); + if ( providerClass != null ) { + for ( ValidationProvider provider : providerResolver.getValidationProviders() ) { + if ( providerClass.isAssignableFrom( provider.getClass() ) ) { + factory = provider.buildValidatorFactory( this ); + break; + } + } + if ( factory == null ) { + throw LOG.getUnableToFindProviderException( providerClass ); + } + } + else { + List> providers = providerResolver.getValidationProviders(); + assert providers.size() != 0; // I run therefore I am + factory = providers.get( 0 ).buildValidatorFactory( this ); + } + } + } + finally { + // close all input streams opened by this configuration + for ( InputStream in : configurationStreams ) { + try { + in.close(); + } + catch (IOException io) { + LOG.unableToCloseInputStream(); + } + } + } + + return factory; + } + + @Override + public final boolean isIgnoreXmlConfiguration() { + return ignoreXmlConfiguration; + } + + @Override + public final MessageInterpolator getMessageInterpolator() { + if ( messageInterpolator == null ) { + // apply explicitly given MI, otherwise use default one + MessageInterpolator interpolator = validationBootstrapParameters.getMessageInterpolator(); + if ( interpolator != null ) { + messageInterpolator = interpolator; + } + else { + messageInterpolator = getDefaultMessageInterpolatorConfiguredWithClassLoader(); + } + } + + return messageInterpolator; + } + + @Override + public final Set getMappingStreams() { + return validationBootstrapParameters.getMappings(); + } + + public final boolean getFailFast() { + return failFast; + } + + @Override + public final ConstraintValidatorFactory getConstraintValidatorFactory() { + return validationBootstrapParameters.getConstraintValidatorFactory(); + } + + @Override + public final TraversableResolver getTraversableResolver() { + return validationBootstrapParameters.getTraversableResolver(); + } + + @Override + public BootstrapConfiguration getBootstrapConfiguration() { + if ( bootstrapConfiguration == null ) { + bootstrapConfiguration = new ValidationXmlParser( externalClassLoader ).parseValidationXml(); + } + return bootstrapConfiguration; + } + + @Override + public ParameterNameProvider getParameterNameProvider() { + return validationBootstrapParameters.getParameterNameProvider(); + } + + @Override + public ClockProvider getClockProvider() { + return validationBootstrapParameters.getClockProvider(); + } + + public ScriptEvaluatorFactory getScriptEvaluatorFactory() { + return scriptEvaluatorFactory; + } + + public Duration getTemporalValidationTolerance() { + return temporalValidationTolerance; + } + + public Object getConstraintValidatorPayload() { + return constraintValidatorPayload; + } + + public GetterPropertySelectionStrategy getGetterPropertySelectionStrategy() { + return getterPropertySelectionStrategy; + } + + @Override + public Set> getValueExtractors() { + return validationBootstrapParameters.getValueExtractorDescriptors() + .values() + .stream() + .map( ValueExtractorDescriptor::getValueExtractor ) + .collect( Collectors.toSet() ); + } + + @Override + public final Map getProperties() { + return validationBootstrapParameters.getConfigProperties(); + } + + public ClassLoader getExternalClassLoader() { + return externalClassLoader; + } + + @Override + public final MessageInterpolator getDefaultMessageInterpolator() { + if ( defaultMessageInterpolator == null ) { + defaultMessageInterpolator = new ResourceBundleMessageInterpolator( defaultResourceBundleLocator ); + } + + return defaultMessageInterpolator; + } + + @Override + public final TraversableResolver getDefaultTraversableResolver() { + return defaultTraversableResolver; + } + + @Override + public final ConstraintValidatorFactory getDefaultConstraintValidatorFactory() { + return defaultConstraintValidatorFactory; + } + + @Override + public final ResourceBundleLocator getDefaultResourceBundleLocator() { + return defaultResourceBundleLocator; + } + + @Override + public ParameterNameProvider getDefaultParameterNameProvider() { + return defaultParameterNameProvider; + } + + @Override + public ClockProvider getDefaultClockProvider() { + return defaultClockProvider; + } + + @Override + public Set> getDefaultValueExtractors() { + return ValueExtractorManager.getDefaultValueExtractors(); + } + + public final Set getProgrammaticMappings() { + return programmaticMappings; + } + + private boolean isSpecificProvider() { + return validationBootstrapParameters.getProvider() != null; + } + + /** + * Tries to check whether a validation.xml file exists and parses it + */ + private void parseValidationXml() { + if ( ignoreXmlConfiguration ) { + LOG.ignoringXmlConfiguration(); + + if ( validationBootstrapParameters.getTraversableResolver() == null ) { + validationBootstrapParameters.setTraversableResolver( defaultTraversableResolver ); + } + if ( validationBootstrapParameters.getConstraintValidatorFactory() == null ) { + validationBootstrapParameters.setConstraintValidatorFactory( defaultConstraintValidatorFactory ); + } + if ( validationBootstrapParameters.getParameterNameProvider() == null ) { + validationBootstrapParameters.setParameterNameProvider( defaultParameterNameProvider ); + } + if ( validationBootstrapParameters.getClockProvider() == null ) { + validationBootstrapParameters.setClockProvider( defaultClockProvider ); + } + } + else { + ValidationBootstrapParameters xmlParameters = new ValidationBootstrapParameters( + getBootstrapConfiguration(), externalClassLoader + ); + applyXmlSettings( xmlParameters ); + } + } + + @SuppressWarnings("rawtypes") + private void loadValueExtractorsFromServiceLoader() { + List valueExtractors = run( GetInstancesFromServiceLoader.action( + externalClassLoader != null ? externalClassLoader : run( GetClassLoader.fromContext() ), + ValueExtractor.class + ) ); + + for ( ValueExtractor valueExtractor : valueExtractors ) { + validationBootstrapParameters.addValueExtractorDescriptor( new ValueExtractorDescriptor( valueExtractor ) ); + } + } + + private void applyXmlSettings(ValidationBootstrapParameters xmlParameters) { + validationBootstrapParameters.setProviderClass( xmlParameters.getProviderClass() ); + + if ( validationBootstrapParameters.getMessageInterpolator() == null ) { + if ( xmlParameters.getMessageInterpolator() != null ) { + validationBootstrapParameters.setMessageInterpolator( xmlParameters.getMessageInterpolator() ); + } + } + + if ( validationBootstrapParameters.getTraversableResolver() == null ) { + if ( xmlParameters.getTraversableResolver() != null ) { + validationBootstrapParameters.setTraversableResolver( xmlParameters.getTraversableResolver() ); + } + else { + validationBootstrapParameters.setTraversableResolver( defaultTraversableResolver ); + } + } + + if ( validationBootstrapParameters.getConstraintValidatorFactory() == null ) { + if ( xmlParameters.getConstraintValidatorFactory() != null ) { + validationBootstrapParameters.setConstraintValidatorFactory( + xmlParameters.getConstraintValidatorFactory() + ); + } + else { + validationBootstrapParameters.setConstraintValidatorFactory( defaultConstraintValidatorFactory ); + } + } + + if ( validationBootstrapParameters.getParameterNameProvider() == null ) { + if ( xmlParameters.getParameterNameProvider() != null ) { + validationBootstrapParameters.setParameterNameProvider( xmlParameters.getParameterNameProvider() ); + } + else { + validationBootstrapParameters.setParameterNameProvider( defaultParameterNameProvider ); + } + } + + if ( validationBootstrapParameters.getClockProvider() == null ) { + if ( xmlParameters.getClockProvider() != null ) { + validationBootstrapParameters.setClockProvider( xmlParameters.getClockProvider() ); + } + else { + validationBootstrapParameters.setClockProvider( defaultClockProvider ); + } + } + + for ( ValueExtractorDescriptor valueExtractorDescriptor : xmlParameters.getValueExtractorDescriptors().values() ) { + validationBootstrapParameters.addValueExtractorDescriptor( valueExtractorDescriptor ); + } + + validationBootstrapParameters.addAllMappings( xmlParameters.getMappings() ); + configurationStreams.addAll( xmlParameters.getMappings() ); + + for ( Map.Entry entry : xmlParameters.getConfigProperties().entrySet() ) { + if ( validationBootstrapParameters.getConfigProperties().get( entry.getKey() ) == null ) { + validationBootstrapParameters.addConfigProperty( entry.getKey(), entry.getValue() ); + } + } + } + + /** + * Returns the default message interpolator, configured with the given user class loader, if present. + */ + private MessageInterpolator getDefaultMessageInterpolatorConfiguredWithClassLoader() { + if ( externalClassLoader != null ) { + PlatformResourceBundleLocator userResourceBundleLocator = new PlatformResourceBundleLocator( + ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, + externalClassLoader + ); + PlatformResourceBundleLocator contributorResourceBundleLocator = new PlatformResourceBundleLocator( + ResourceBundleMessageInterpolator.CONTRIBUTOR_VALIDATION_MESSAGES, + externalClassLoader, + true + ); + + // Within RBMI, the expression factory implementation is loaded from the TCCL; thus we set the TCCL to the + // given external class loader for this call + final ClassLoader originalContextClassLoader = run( GetClassLoader.fromContext() ); + + try { + run( SetContextClassLoader.action( externalClassLoader ) ); + return new ResourceBundleMessageInterpolator( + userResourceBundleLocator, + contributorResourceBundleLocator + ); + } + finally { + run( SetContextClassLoader.action( originalContextClassLoader ) ); + } + } + else { + return getDefaultMessageInterpolator(); + } + } + + @SuppressWarnings("unchecked") + protected T thisAsT() { + return (T) this; + } + + /** + * Runs the given privileged action, using a privileged block if required. + *

+ * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary + * privileged actions within HV's protection domain. + */ + private static T run(PrivilegedAction action) { + return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java index 986bbe5b51..f6292695e8 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java @@ -6,58 +6,11 @@ */ package org.hibernate.validator.internal.engine; -import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; -import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.invoke.MethodHandles; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.time.Duration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import javax.validation.BootstrapConfiguration; -import javax.validation.ClockProvider; -import javax.validation.ConstraintValidatorFactory; -import javax.validation.MessageInterpolator; -import javax.validation.ParameterNameProvider; -import javax.validation.TraversableResolver; -import javax.validation.ValidationProviderResolver; -import javax.validation.ValidatorFactory; import javax.validation.spi.BootstrapState; import javax.validation.spi.ConfigurationState; import javax.validation.spi.ValidationProvider; -import javax.validation.valueextraction.ValueExtractor; import org.hibernate.validator.HibernateValidatorConfiguration; -import org.hibernate.validator.cfg.ConstraintMapping; -import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping; -import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorFactoryImpl; -import org.hibernate.validator.internal.engine.resolver.TraversableResolvers; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorDescriptor; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; -import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; -import org.hibernate.validator.internal.util.Contracts; -import org.hibernate.validator.internal.util.Version; -import org.hibernate.validator.internal.util.logging.Log; -import org.hibernate.validator.internal.util.logging.LoggerFactory; -import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader; -import org.hibernate.validator.internal.util.privilegedactions.GetInstancesFromServiceLoader; -import org.hibernate.validator.internal.util.privilegedactions.SetContextClassLoader; -import org.hibernate.validator.internal.xml.config.ValidationBootstrapParameters; -import org.hibernate.validator.internal.xml.config.ValidationXmlParser; -import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; -import org.hibernate.validator.resourceloading.PlatformResourceBundleLocator; -import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; -import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; -import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; /** * Hibernate specific {@code Configuration} implementation. @@ -68,620 +21,13 @@ * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI * @author Chris Beckey <cbeckey@paypal.com> */ -public class ConfigurationImpl implements HibernateValidatorConfiguration, ConfigurationState { - - static { - Version.touch(); - } - - private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - - private final ResourceBundleLocator defaultResourceBundleLocator; - - /** - * Built lazily so RBMI and its dependency on EL is only initialized if actually needed - */ - private MessageInterpolator defaultMessageInterpolator; - private MessageInterpolator messageInterpolator; - - private final TraversableResolver defaultTraversableResolver; - private final ConstraintValidatorFactory defaultConstraintValidatorFactory; - private final ParameterNameProvider defaultParameterNameProvider; - private final ClockProvider defaultClockProvider; - - private ValidationProviderResolver providerResolver; - private final ValidationBootstrapParameters validationBootstrapParameters; - private boolean ignoreXmlConfiguration = false; - private final Set configurationStreams = newHashSet(); - private BootstrapConfiguration bootstrapConfiguration; - - private final Map valueExtractorDescriptors = new HashMap<>(); - - // HV-specific options - private final Set programmaticMappings = newHashSet(); - private boolean failFast; - private ClassLoader externalClassLoader; - private final MethodValidationConfiguration.Builder methodValidationConfigurationBuilder = new MethodValidationConfiguration.Builder(); - private boolean traversableResolverResultCacheEnabled = true; - private ScriptEvaluatorFactory scriptEvaluatorFactory; - private Duration temporalValidationTolerance; - private Object constraintValidatorPayload; - private GetterPropertySelectionStrategy getterPropertySelectionStrategy; +public class ConfigurationImpl extends AbstractConfigurationImpl implements HibernateValidatorConfiguration, ConfigurationState { public ConfigurationImpl(BootstrapState state) { - this(); - if ( state.getValidationProviderResolver() == null ) { - this.providerResolver = state.getDefaultValidationProviderResolver(); - } - else { - this.providerResolver = state.getValidationProviderResolver(); - } + super( state ); } public ConfigurationImpl(ValidationProvider provider) { - this(); - if ( provider == null ) { - throw LOG.getInconsistentConfigurationException(); - } - this.providerResolver = null; - validationBootstrapParameters.setProvider( provider ); - } - - private ConfigurationImpl() { - this.validationBootstrapParameters = new ValidationBootstrapParameters(); - - this.defaultResourceBundleLocator = new PlatformResourceBundleLocator( - ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES - ); - this.defaultTraversableResolver = TraversableResolvers.getDefault(); - this.defaultConstraintValidatorFactory = new ConstraintValidatorFactoryImpl(); - this.defaultParameterNameProvider = new DefaultParameterNameProvider(); - this.defaultClockProvider = DefaultClockProvider.INSTANCE; - } - - @Override - public final HibernateValidatorConfiguration ignoreXmlConfiguration() { - ignoreXmlConfiguration = true; - return this; - } - - @Override - public final ConfigurationImpl messageInterpolator(MessageInterpolator interpolator) { - if ( LOG.isDebugEnabled() ) { - if ( interpolator != null ) { - LOG.debug( "Setting custom MessageInterpolator of type " + interpolator.getClass().getName() ); - } - } - this.validationBootstrapParameters.setMessageInterpolator( interpolator ); - return this; - } - - @Override - public final ConfigurationImpl traversableResolver(TraversableResolver resolver) { - if ( LOG.isDebugEnabled() ) { - if ( resolver != null ) { - LOG.debug( "Setting custom TraversableResolver of type " + resolver.getClass().getName() ); - } - } - this.validationBootstrapParameters.setTraversableResolver( resolver ); - return this; - } - - @Override - public final ConfigurationImpl enableTraversableResolverResultCache(boolean enabled) { - this.traversableResolverResultCacheEnabled = enabled; - return this; - } - - public final boolean isTraversableResolverResultCacheEnabled() { - return traversableResolverResultCacheEnabled; - } - - @Override - public final ConfigurationImpl constraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) { - if ( LOG.isDebugEnabled() ) { - if ( constraintValidatorFactory != null ) { - LOG.debug( - "Setting custom ConstraintValidatorFactory of type " + constraintValidatorFactory.getClass() - .getName() - ); - } - } - this.validationBootstrapParameters.setConstraintValidatorFactory( constraintValidatorFactory ); - return this; - } - - @Override - public HibernateValidatorConfiguration parameterNameProvider(ParameterNameProvider parameterNameProvider) { - if ( LOG.isDebugEnabled() ) { - if ( parameterNameProvider != null ) { - LOG.debug( - "Setting custom ParameterNameProvider of type " + parameterNameProvider.getClass() - .getName() - ); - } - } - this.validationBootstrapParameters.setParameterNameProvider( parameterNameProvider ); - return this; - } - - @Override - public HibernateValidatorConfiguration clockProvider(ClockProvider clockProvider) { - if ( LOG.isDebugEnabled() ) { - if ( clockProvider != null ) { - LOG.debug( "Setting custom ClockProvider of type " + clockProvider.getClass().getName() ); - } - } - this.validationBootstrapParameters.setClockProvider( clockProvider ); - return this; - } - - @Override - public HibernateValidatorConfiguration addValueExtractor(ValueExtractor extractor) { - Contracts.assertNotNull( extractor, MESSAGES.parameterMustNotBeNull( "extractor" ) ); - - ValueExtractorDescriptor descriptor = new ValueExtractorDescriptor( extractor ); - ValueExtractorDescriptor previous = valueExtractorDescriptors.put( descriptor.getKey(), descriptor ); - - if ( previous != null ) { - throw LOG.getValueExtractorForTypeAndTypeUseAlreadyPresentException( extractor, previous.getValueExtractor() ); - } - - if ( LOG.isDebugEnabled() ) { - LOG.debug( "Adding value extractor " + extractor ); - } - - return this; - } - - @Override - public final HibernateValidatorConfiguration addMapping(InputStream stream) { - Contracts.assertNotNull( stream, MESSAGES.inputStreamCannotBeNull() ); - - validationBootstrapParameters.addMapping( stream.markSupported() ? stream : new BufferedInputStream( stream ) ); - return this; - } - - @Override - public final HibernateValidatorConfiguration failFast(boolean failFast) { - this.failFast = failFast; - return this; - } - - @Override - public HibernateValidatorConfiguration allowOverridingMethodAlterParameterConstraint(boolean allow) { - this.methodValidationConfigurationBuilder.allowOverridingMethodAlterParameterConstraint( allow ); - return this; - } - - public boolean isAllowOverridingMethodAlterParameterConstraint() { - return this.methodValidationConfigurationBuilder.isAllowOverridingMethodAlterParameterConstraint(); - } - - @Override - public HibernateValidatorConfiguration allowMultipleCascadedValidationOnReturnValues(boolean allow) { - this.methodValidationConfigurationBuilder.allowMultipleCascadedValidationOnReturnValues( allow ); - return this; - } - - public boolean isAllowMultipleCascadedValidationOnReturnValues() { - return this.methodValidationConfigurationBuilder.isAllowMultipleCascadedValidationOnReturnValues(); - } - - @Override - public HibernateValidatorConfiguration allowParallelMethodsDefineParameterConstraints(boolean allow) { - this.methodValidationConfigurationBuilder.allowParallelMethodsDefineParameterConstraints( allow ); - return this; - } - - @Override - public HibernateValidatorConfiguration scriptEvaluatorFactory(ScriptEvaluatorFactory scriptEvaluatorFactory) { - Contracts.assertNotNull( scriptEvaluatorFactory, MESSAGES.parameterMustNotBeNull( "scriptEvaluatorFactory" ) ); - - this.scriptEvaluatorFactory = scriptEvaluatorFactory; - return this; - } - - @Override - public HibernateValidatorConfiguration temporalValidationTolerance(Duration temporalValidationTolerance) { - Contracts.assertNotNull( temporalValidationTolerance, MESSAGES.parameterMustNotBeNull( "temporalValidationTolerance" ) ); - - this.temporalValidationTolerance = temporalValidationTolerance.abs(); - return this; - } - - @Override - public HibernateValidatorConfiguration constraintValidatorPayload(Object constraintValidatorPayload) { - Contracts.assertNotNull( constraintValidatorPayload, MESSAGES.parameterMustNotBeNull( "constraintValidatorPayload" ) ); - - this.constraintValidatorPayload = constraintValidatorPayload; - return this; - } - - @Override - public HibernateValidatorConfiguration getterPropertySelectionStrategy(GetterPropertySelectionStrategy getterPropertySelectionStrategy) { - Contracts.assertNotNull( getterPropertySelectionStrategy, MESSAGES.parameterMustNotBeNull( "getterPropertySelectionStrategy" ) ); - - this.getterPropertySelectionStrategy = getterPropertySelectionStrategy; - return this; - } - - public boolean isAllowParallelMethodsDefineParameterConstraints() { - return this.methodValidationConfigurationBuilder.isAllowParallelMethodsDefineParameterConstraints(); - } - - public MethodValidationConfiguration getMethodValidationConfiguration() { - return this.methodValidationConfigurationBuilder.build(); - } - - @Override - public final DefaultConstraintMapping createConstraintMapping() { - GetterPropertySelectionStrategy getterPropertySelectionStrategyToUse = null; - if ( getterPropertySelectionStrategy == null ) { - getterPropertySelectionStrategyToUse = new DefaultGetterPropertySelectionStrategy(); - } - else { - getterPropertySelectionStrategyToUse = getterPropertySelectionStrategy; - } - - return new DefaultConstraintMapping( new JavaBeanHelper( getterPropertySelectionStrategyToUse ) ); - } - - @Override - public final HibernateValidatorConfiguration addMapping(ConstraintMapping mapping) { - Contracts.assertNotNull( mapping, MESSAGES.parameterMustNotBeNull( "mapping" ) ); - - this.programmaticMappings.add( (DefaultConstraintMapping) mapping ); - return this; - } - - @Override - public final HibernateValidatorConfiguration addProperty(String name, String value) { - if ( value != null ) { - validationBootstrapParameters.addConfigProperty( name, value ); - } - return this; - } - - @Override - public HibernateValidatorConfiguration externalClassLoader(ClassLoader externalClassLoader) { - Contracts.assertNotNull( externalClassLoader, MESSAGES.parameterMustNotBeNull( "externalClassLoader" ) ); - this.externalClassLoader = externalClassLoader; - - return this; - } - - @Override - public final ValidatorFactory buildValidatorFactory() { - loadValueExtractorsFromServiceLoader(); - parseValidationXml(); - - for ( ValueExtractorDescriptor valueExtractorDescriptor : valueExtractorDescriptors.values() ) { - validationBootstrapParameters.addValueExtractorDescriptor( valueExtractorDescriptor ); - } - - ValidatorFactory factory = null; - try { - if ( isSpecificProvider() ) { - factory = validationBootstrapParameters.getProvider().buildValidatorFactory( this ); - } - else { - final Class> providerClass = validationBootstrapParameters.getProviderClass(); - if ( providerClass != null ) { - for ( ValidationProvider provider : providerResolver.getValidationProviders() ) { - if ( providerClass.isAssignableFrom( provider.getClass() ) ) { - factory = provider.buildValidatorFactory( this ); - break; - } - } - if ( factory == null ) { - throw LOG.getUnableToFindProviderException( providerClass ); - } - } - else { - List> providers = providerResolver.getValidationProviders(); - assert providers.size() != 0; // I run therefore I am - factory = providers.get( 0 ).buildValidatorFactory( this ); - } - } - } - finally { - // close all input streams opened by this configuration - for ( InputStream in : configurationStreams ) { - try { - in.close(); - } - catch (IOException io) { - LOG.unableToCloseInputStream(); - } - } - } - - return factory; - } - - @Override - public final boolean isIgnoreXmlConfiguration() { - return ignoreXmlConfiguration; - } - - @Override - public final MessageInterpolator getMessageInterpolator() { - if ( messageInterpolator == null ) { - // apply explicitly given MI, otherwise use default one - MessageInterpolator interpolator = validationBootstrapParameters.getMessageInterpolator(); - if ( interpolator != null ) { - messageInterpolator = interpolator; - } - else { - messageInterpolator = getDefaultMessageInterpolatorConfiguredWithClassLoader(); - } - } - - return messageInterpolator; - } - - @Override - public final Set getMappingStreams() { - return validationBootstrapParameters.getMappings(); - } - - public final boolean getFailFast() { - return failFast; - } - - @Override - public final ConstraintValidatorFactory getConstraintValidatorFactory() { - return validationBootstrapParameters.getConstraintValidatorFactory(); - } - - @Override - public final TraversableResolver getTraversableResolver() { - return validationBootstrapParameters.getTraversableResolver(); - } - - @Override - public BootstrapConfiguration getBootstrapConfiguration() { - if ( bootstrapConfiguration == null ) { - bootstrapConfiguration = new ValidationXmlParser( externalClassLoader ).parseValidationXml(); - } - return bootstrapConfiguration; - } - - @Override - public ParameterNameProvider getParameterNameProvider() { - return validationBootstrapParameters.getParameterNameProvider(); - } - - @Override - public ClockProvider getClockProvider() { - return validationBootstrapParameters.getClockProvider(); - } - - public ScriptEvaluatorFactory getScriptEvaluatorFactory() { - return scriptEvaluatorFactory; - } - - public Duration getTemporalValidationTolerance() { - return temporalValidationTolerance; - } - - public Object getConstraintValidatorPayload() { - return constraintValidatorPayload; - } - - public GetterPropertySelectionStrategy getGetterPropertySelectionStrategy() { - return getterPropertySelectionStrategy; - } - - @Override - public Set> getValueExtractors() { - return validationBootstrapParameters.getValueExtractorDescriptors() - .values() - .stream() - .map( ValueExtractorDescriptor::getValueExtractor ) - .collect( Collectors.toSet() ); - } - - @Override - public final Map getProperties() { - return validationBootstrapParameters.getConfigProperties(); - } - - public ClassLoader getExternalClassLoader() { - return externalClassLoader; - } - - @Override - public final MessageInterpolator getDefaultMessageInterpolator() { - if ( defaultMessageInterpolator == null ) { - defaultMessageInterpolator = new ResourceBundleMessageInterpolator( defaultResourceBundleLocator ); - } - - return defaultMessageInterpolator; - } - - @Override - public final TraversableResolver getDefaultTraversableResolver() { - return defaultTraversableResolver; - } - - @Override - public final ConstraintValidatorFactory getDefaultConstraintValidatorFactory() { - return defaultConstraintValidatorFactory; - } - - @Override - public final ResourceBundleLocator getDefaultResourceBundleLocator() { - return defaultResourceBundleLocator; - } - - @Override - public ParameterNameProvider getDefaultParameterNameProvider() { - return defaultParameterNameProvider; - } - - @Override - public ClockProvider getDefaultClockProvider() { - return defaultClockProvider; - } - - @Override - public Set> getDefaultValueExtractors() { - return ValueExtractorManager.getDefaultValueExtractors(); - } - - public final Set getProgrammaticMappings() { - return programmaticMappings; - } - - private boolean isSpecificProvider() { - return validationBootstrapParameters.getProvider() != null; - } - - /** - * Tries to check whether a validation.xml file exists and parses it - */ - private void parseValidationXml() { - if ( ignoreXmlConfiguration ) { - LOG.ignoringXmlConfiguration(); - - if ( validationBootstrapParameters.getTraversableResolver() == null ) { - validationBootstrapParameters.setTraversableResolver( defaultTraversableResolver ); - } - if ( validationBootstrapParameters.getConstraintValidatorFactory() == null ) { - validationBootstrapParameters.setConstraintValidatorFactory( defaultConstraintValidatorFactory ); - } - if ( validationBootstrapParameters.getParameterNameProvider() == null ) { - validationBootstrapParameters.setParameterNameProvider( defaultParameterNameProvider ); - } - if ( validationBootstrapParameters.getClockProvider() == null ) { - validationBootstrapParameters.setClockProvider( defaultClockProvider ); - } - } - else { - ValidationBootstrapParameters xmlParameters = new ValidationBootstrapParameters( - getBootstrapConfiguration(), externalClassLoader - ); - applyXmlSettings( xmlParameters ); - } - } - - @SuppressWarnings("rawtypes") - private void loadValueExtractorsFromServiceLoader() { - List valueExtractors = run( GetInstancesFromServiceLoader.action( - externalClassLoader != null ? externalClassLoader : run( GetClassLoader.fromContext() ), - ValueExtractor.class - ) ); - - for ( ValueExtractor valueExtractor : valueExtractors ) { - validationBootstrapParameters.addValueExtractorDescriptor( new ValueExtractorDescriptor( valueExtractor ) ); - } - } - - private void applyXmlSettings(ValidationBootstrapParameters xmlParameters) { - validationBootstrapParameters.setProviderClass( xmlParameters.getProviderClass() ); - - if ( validationBootstrapParameters.getMessageInterpolator() == null ) { - if ( xmlParameters.getMessageInterpolator() != null ) { - validationBootstrapParameters.setMessageInterpolator( xmlParameters.getMessageInterpolator() ); - } - } - - if ( validationBootstrapParameters.getTraversableResolver() == null ) { - if ( xmlParameters.getTraversableResolver() != null ) { - validationBootstrapParameters.setTraversableResolver( xmlParameters.getTraversableResolver() ); - } - else { - validationBootstrapParameters.setTraversableResolver( defaultTraversableResolver ); - } - } - - if ( validationBootstrapParameters.getConstraintValidatorFactory() == null ) { - if ( xmlParameters.getConstraintValidatorFactory() != null ) { - validationBootstrapParameters.setConstraintValidatorFactory( - xmlParameters.getConstraintValidatorFactory() - ); - } - else { - validationBootstrapParameters.setConstraintValidatorFactory( defaultConstraintValidatorFactory ); - } - } - - if ( validationBootstrapParameters.getParameterNameProvider() == null ) { - if ( xmlParameters.getParameterNameProvider() != null ) { - validationBootstrapParameters.setParameterNameProvider( xmlParameters.getParameterNameProvider() ); - } - else { - validationBootstrapParameters.setParameterNameProvider( defaultParameterNameProvider ); - } - } - - if ( validationBootstrapParameters.getClockProvider() == null ) { - if ( xmlParameters.getClockProvider() != null ) { - validationBootstrapParameters.setClockProvider( xmlParameters.getClockProvider() ); - } - else { - validationBootstrapParameters.setClockProvider( defaultClockProvider ); - } - } - - for ( ValueExtractorDescriptor valueExtractorDescriptor : xmlParameters.getValueExtractorDescriptors().values() ) { - validationBootstrapParameters.addValueExtractorDescriptor( valueExtractorDescriptor ); - } - - validationBootstrapParameters.addAllMappings( xmlParameters.getMappings() ); - configurationStreams.addAll( xmlParameters.getMappings() ); - - for ( Map.Entry entry : xmlParameters.getConfigProperties().entrySet() ) { - if ( validationBootstrapParameters.getConfigProperties().get( entry.getKey() ) == null ) { - validationBootstrapParameters.addConfigProperty( entry.getKey(), entry.getValue() ); - } - } - } - - /** - * Returns the default message interpolator, configured with the given user class loader, if present. - */ - private MessageInterpolator getDefaultMessageInterpolatorConfiguredWithClassLoader() { - if ( externalClassLoader != null ) { - PlatformResourceBundleLocator userResourceBundleLocator = new PlatformResourceBundleLocator( - ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, - externalClassLoader - ); - PlatformResourceBundleLocator contributorResourceBundleLocator = new PlatformResourceBundleLocator( - ResourceBundleMessageInterpolator.CONTRIBUTOR_VALIDATION_MESSAGES, - externalClassLoader, - true - ); - - // Within RBMI, the expression factory implementation is loaded from the TCCL; thus we set the TCCL to the - // given external class loader for this call - final ClassLoader originalContextClassLoader = run( GetClassLoader.fromContext() ); - - try { - run( SetContextClassLoader.action( externalClassLoader ) ); - return new ResourceBundleMessageInterpolator( - userResourceBundleLocator, - contributorResourceBundleLocator - ); - } - finally { - run( SetContextClassLoader.action( originalContextClassLoader ) ); - } - } - else { - return getDefaultMessageInterpolator(); - } - } - - /** - * Runs the given privileged action, using a privileged block if required. - *

- * NOTE: This must never be changed into a publicly available method to avoid execution of arbitrary - * privileged actions within HV's protection domain. - */ - private static T run(PrivilegedAction action) { - return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run(); + super( provider ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java index 49289c5234..1e4d63ff24 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java @@ -138,7 +138,7 @@ static List getPropertyConfiguredConstraintMapping return contributors; } - static boolean getAllowParallelMethodsDefineParameterConstraints(ConfigurationImpl hibernateSpecificConfig, Map properties) { + static boolean getAllowParallelMethodsDefineParameterConstraints(AbstractConfigurationImpl hibernateSpecificConfig, Map properties) { return checkPropertiesForBoolean( properties, HibernateValidatorConfiguration.ALLOW_PARALLEL_METHODS_DEFINE_PARAMETER_CONSTRAINTS, @@ -146,7 +146,7 @@ static boolean getAllowParallelMethodsDefineParameterConstraints(ConfigurationIm ); } - static boolean getAllowMultipleCascadedValidationOnReturnValues(ConfigurationImpl hibernateSpecificConfig, Map properties) { + static boolean getAllowMultipleCascadedValidationOnReturnValues(AbstractConfigurationImpl hibernateSpecificConfig, Map properties) { return checkPropertiesForBoolean( properties, HibernateValidatorConfiguration.ALLOW_MULTIPLE_CASCADED_VALIDATION_ON_RESULT, @@ -154,7 +154,7 @@ static boolean getAllowMultipleCascadedValidationOnReturnValues(ConfigurationImp ); } - static boolean getAllowOverridingMethodAlterParameterConstraint(ConfigurationImpl hibernateSpecificConfig, Map properties) { + static boolean getAllowOverridingMethodAlterParameterConstraint(AbstractConfigurationImpl hibernateSpecificConfig, Map properties) { return checkPropertiesForBoolean( properties, HibernateValidatorConfiguration.ALLOW_PARAMETER_CONSTRAINT_OVERRIDE, @@ -162,7 +162,7 @@ static boolean getAllowOverridingMethodAlterParameterConstraint(ConfigurationImp ); } - static boolean getTraversableResolverResultCacheEnabled(ConfigurationImpl configuration, Map properties) { + static boolean getTraversableResolverResultCacheEnabled(AbstractConfigurationImpl configuration, Map properties) { return checkPropertiesForBoolean( properties, HibernateValidatorConfiguration.ENABLE_TRAVERSABLE_RESOLVER_RESULT_CACHE, @@ -170,7 +170,7 @@ static boolean getTraversableResolverResultCacheEnabled(ConfigurationImpl config ); } - static boolean getFailFast(ConfigurationImpl configuration, Map properties) { + static boolean getFailFast(AbstractConfigurationImpl configuration, Map properties) { // check whether fail fast is programmatically enabled boolean tmpFailFast = configuration != null ? configuration.getFailFast() : false; @@ -252,7 +252,7 @@ static Object getConstraintValidatorPayload(ConfigurationState configurationStat return null; } - static GetterPropertySelectionStrategy getGetterPropertySelectionStrategy(ConfigurationImpl hibernateSpecificConfig, Map properties, + static GetterPropertySelectionStrategy getGetterPropertySelectionStrategy(AbstractConfigurationImpl hibernateSpecificConfig, Map properties, ClassLoader externalClassLoader) { if ( hibernateSpecificConfig.getGetterPropertySelectionStrategy() != null ) { LOG.usingGetterPropertySelectionStrategy( hibernateSpecificConfig.getGetterPropertySelectionStrategy().getClass() ); From b4c2774b16f0fbf2b45823cc9aa3e2c640558631 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 28 Nov 2018 11:00:19 +0100 Subject: [PATCH 139/393] HV-1667 Introduce a PredefinedScopeValidatorFactoryImpl --- .../BaseHibernateValidatorConfiguration.java | 3 +- .../PredefinedScopeHibernateValidator.java | 44 +++ ...dScopeHibernateValidatorConfiguration.java | 24 ++ ...definedScopeHibernateValidatorFactory.java | 63 ++++ .../PredefinedScopeConfigurationImpl.java | 43 +++ .../PredefinedScopeValidatorContextImpl.java | 107 +++++++ .../PredefinedScopeValidatorFactoryImpl.java | 293 ++++++++++++++++++ .../PredefinedScopeBeanMetaDataManager.java | 166 ++++++++++ .../PredefinedScopeValidatorFactoryTest.java | 74 +++++ 9 files changed, 816 insertions(+), 1 deletion(-) create mode 100644 engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidator.java create mode 100644 engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java create mode 100644 engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorFactory.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorContextImpl.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java diff --git a/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java index 0b2450ddb4..921ab2db44 100644 --- a/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java @@ -28,7 +28,8 @@ /** * Base interface for Hibernate Validator specific configurations. *

- * Should not be used directly, prefer {@link HibernateValidatorConfiguration}. + * Should not be used directly, prefer {@link HibernateValidatorConfiguration} or + * {@link PredefinedScopeHibernateValidatorConfiguration}. * * @author Emmanuel Bernard * @author Gunnar Morling diff --git a/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidator.java b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidator.java new file mode 100644 index 0000000000..3d17248da3 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidator.java @@ -0,0 +1,44 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator; + +import javax.validation.Configuration; +import javax.validation.ValidatorFactory; +import javax.validation.spi.BootstrapState; +import javax.validation.spi.ConfigurationState; +import javax.validation.spi.ValidationProvider; + +import org.hibernate.validator.internal.engine.PredefinedScopeConfigurationImpl; +import org.hibernate.validator.internal.engine.PredefinedScopeValidatorFactoryImpl; + +/** + * Implementation of {@code ValidationProvider} limiting validation to a predefined scope. + *

+ * It allows to collect all the necessary metadata at bootstrap. + * + * @author Guillaume Smet + * + * @since 6.1 + */ +@Incubating +public class PredefinedScopeHibernateValidator implements ValidationProvider { + + @Override + public PredefinedScopeHibernateValidatorConfiguration createSpecializedConfiguration(BootstrapState state) { + return new PredefinedScopeConfigurationImpl( this ); + } + + @Override + public Configuration createGenericConfiguration(BootstrapState state) { + return new PredefinedScopeConfigurationImpl( state ); + } + + @Override + public ValidatorFactory buildValidatorFactory(ConfigurationState configurationState) { + return new PredefinedScopeValidatorFactoryImpl( configurationState ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java new file mode 100644 index 0000000000..3e9e6b0381 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java @@ -0,0 +1,24 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator; + +import java.util.Set; + +/** + * Extension of {@link HibernateValidatorConfiguration} with additional methods dedicated to defining the predefined + * scope of bean validation e.g. validated classes, constraint validators... + * + * @author Guillaume Smet + * + * @since 6.1 + */ +@Incubating +public interface PredefinedScopeHibernateValidatorConfiguration extends BaseHibernateValidatorConfiguration { + + @Incubating + PredefinedScopeHibernateValidatorConfiguration initializeBeanMetaData(Set> beanClassesToInitialize); +} diff --git a/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorFactory.java b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorFactory.java new file mode 100644 index 0000000000..63d4f52437 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorFactory.java @@ -0,0 +1,63 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ + +package org.hibernate.validator; + +import java.time.Duration; + +import javax.validation.ValidatorFactory; + +import org.hibernate.validator.constraints.ParameterScriptAssert; +import org.hibernate.validator.constraints.ScriptAssert; +import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; +import org.hibernate.validator.spi.scripting.ScriptEvaluator; +import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; + +/** + * Provides Hibernate Validator extensions to {@link ValidatorFactory} in the context of a predefined scope. + * + * @since 6.1 + */ +@Incubating +public interface PredefinedScopeHibernateValidatorFactory extends ValidatorFactory { + + /** + * Returns the factory responsible for creating {@link ScriptEvaluator}s used to + * evaluate script expressions of {@link ScriptAssert} and {@link ParameterScriptAssert} + * constraints. + * + * @return a {@link ScriptEvaluatorFactory} instance + */ + @Incubating + ScriptEvaluatorFactory getScriptEvaluatorFactory(); + + /** + * Returns the temporal validation tolerance i.e. the acceptable margin of error when comparing date/time in + * temporal constraints. + * + * @return the tolerance + */ + @Incubating + Duration getTemporalValidationTolerance(); + + /** + * Returns the getter property selection strategy defining the rules determining if a method is a getter or not. + * + * @return the getter property selection strategy of the current {@link ValidatorFactory} + */ + @Incubating + GetterPropertySelectionStrategy getGetterPropertySelectionStrategy(); + + /** + * Returns a context for validator configuration via options from the + * Bean Validation API as well as specific ones from Hibernate Validator. + * + * @return A context for validator configuration. + */ + @Override + HibernateValidatorContext usingContext(); +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java new file mode 100644 index 0000000000..dde4fa0e56 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java @@ -0,0 +1,43 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine; + +import java.util.Set; + +import javax.validation.spi.BootstrapState; +import javax.validation.spi.ConfigurationState; +import javax.validation.spi.ValidationProvider; + +import org.hibernate.validator.PredefinedScopeHibernateValidatorConfiguration; +import org.hibernate.validator.internal.util.CollectionHelper; + +/** + * @author Guillaume Smet + */ +public class PredefinedScopeConfigurationImpl extends AbstractConfigurationImpl + implements PredefinedScopeHibernateValidatorConfiguration, ConfigurationState { + + private Set> beanClassesToInitialize; + + public PredefinedScopeConfigurationImpl(BootstrapState state) { + super( state ); + } + + public PredefinedScopeConfigurationImpl(ValidationProvider validationProvider) { + super( validationProvider ); + } + + @Override + public PredefinedScopeHibernateValidatorConfiguration initializeBeanMetaData(Set> beanMetaDataToInitialize) { + beanClassesToInitialize = CollectionHelper.toImmutableSet( beanMetaDataToInitialize ); + return thisAsT(); + } + + public Set> getBeanClassesToInitialize() { + return beanClassesToInitialize; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorContextImpl.java new file mode 100644 index 0000000000..6f83cd90db --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorContextImpl.java @@ -0,0 +1,107 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine; + +import java.time.Duration; + +import javax.validation.ClockProvider; +import javax.validation.ConstraintValidatorFactory; +import javax.validation.MessageInterpolator; +import javax.validation.ParameterNameProvider; +import javax.validation.TraversableResolver; +import javax.validation.Validator; +import javax.validation.valueextraction.ValueExtractor; + +import org.hibernate.validator.HibernateValidatorContext; + +/** + * @author Guillaume Smet + */ +public class PredefinedScopeValidatorContextImpl implements HibernateValidatorContext { + + private final PredefinedScopeValidatorFactoryImpl validatorFactory; + + private final ValidatorFactoryScopedContext.Builder validatorFactoryScopedContextBuilder; + + public PredefinedScopeValidatorContextImpl(PredefinedScopeValidatorFactoryImpl validatorFactory) { + this.validatorFactoryScopedContextBuilder = new ValidatorFactoryScopedContext.Builder( validatorFactory.getValidatorFactoryScopedContext() ); + this.validatorFactory = validatorFactory; + } + + @Override + public HibernateValidatorContext messageInterpolator(MessageInterpolator messageInterpolator) { + throw new IllegalStateException( "Defining a Validator-specific message interpolator is not supported by the predefined scope ValidatorFactory." ); + } + + @Override + public HibernateValidatorContext traversableResolver(TraversableResolver traversableResolver) { + throw new IllegalStateException( "Defining a Validator-specific traversable resolver is not supported by the predefined scope ValidatorFactory." ); + } + + @Override + public HibernateValidatorContext constraintValidatorFactory(ConstraintValidatorFactory factory) { + throw new IllegalStateException( "Defining a Validator-specific constraint validator factory is not supported by the predefined scope ValidatorFactory." ); + } + + @Override + public HibernateValidatorContext parameterNameProvider(ParameterNameProvider parameterNameProvider) { + throw new IllegalStateException( "Defining a Validator-specific parameter name provider is not supported by the predefined scope ValidatorFactory." ); + } + + @Override + public HibernateValidatorContext clockProvider(ClockProvider clockProvider) { + throw new IllegalStateException( "Defining a Validator-specific clock provider is not supported by the predefined scope ValidatorFactory." ); + } + + @Override + public HibernateValidatorContext addValueExtractor(ValueExtractor extractor) { + throw new IllegalStateException( "Adding Validator-specific value extractors is not supported by the predefined scope ValidatorFactory." ); + } + + @Override + public HibernateValidatorContext failFast(boolean failFast) { + validatorFactoryScopedContextBuilder.setFailFast( failFast ); + return this; + } + + @Override + public HibernateValidatorContext allowOverridingMethodAlterParameterConstraint(boolean allow) { + throw new IllegalStateException( "Altering method validation configuration is not supported by the predefined scope ValidatorFactory." ); + } + + @Override + public HibernateValidatorContext allowMultipleCascadedValidationOnReturnValues(boolean allow) { + throw new IllegalStateException( "Altering method validation configuration is not supported by the predefined scope ValidatorFactory." ); + } + + @Override + public HibernateValidatorContext allowParallelMethodsDefineParameterConstraints(boolean allow) { + throw new IllegalStateException( "Altering method validation configuration is not supported by the predefined scope ValidatorFactory." ); + } + + @Override + public HibernateValidatorContext enableTraversableResolverResultCache(boolean enabled) { + validatorFactoryScopedContextBuilder.setTraversableResolverResultCacheEnabled( enabled ); + return this; + } + + @Override + public HibernateValidatorContext temporalValidationTolerance(Duration temporalValidationTolerance) { + throw new IllegalStateException( "Defining a Validator-specific temporal validation tolerance is not supported by the predefined scope ValidatorFactory." ); + } + + @Override + public HibernateValidatorContext constraintValidatorPayload(Object dynamicPayload) { + validatorFactoryScopedContextBuilder.setConstraintValidatorPayload( dynamicPayload ); + return this; + } + + @Override + public Validator getValidator() { + return validatorFactory.createValidator( validatorFactoryScopedContextBuilder.build() ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java new file mode 100644 index 0000000000..4f9bf634d5 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java @@ -0,0 +1,293 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine; + +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getAllowMultipleCascadedValidationOnReturnValues; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getAllowOverridingMethodAlterParameterConstraint; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getAllowParallelMethodsDefineParameterConstraints; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getConstraintMappings; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getConstraintValidatorPayload; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getExternalClassLoader; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getFailFast; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getTraversableResolverResultCacheEnabled; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.logValidatorFactoryScopedConfiguration; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.registerCustomConstraintValidators; +import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; + +import java.lang.invoke.MethodHandles; +import java.time.Duration; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.validation.ClockProvider; +import javax.validation.ConstraintValidatorFactory; +import javax.validation.MessageInterpolator; +import javax.validation.ParameterNameProvider; +import javax.validation.TraversableResolver; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import javax.validation.spi.ConfigurationState; + +import org.hibernate.validator.HibernateValidatorContext; +import org.hibernate.validator.HibernateValidatorFactory; +import org.hibernate.validator.PredefinedScopeHibernateValidatorFactory; +import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManagerImpl; +import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.PredefinedScopeBeanMetaDataManager; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; +import org.hibernate.validator.internal.metadata.provider.ProgrammaticMetaDataProvider; +import org.hibernate.validator.internal.metadata.provider.XmlMetaDataProvider; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; +import org.hibernate.validator.internal.util.ExecutableHelper; +import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; +import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; + +/** + * Factory returning initialized {@code Validator} instances. + *

+ * This factory is designed to support a predefined scope of bean classes to validate and constraint validators. + */ +public class PredefinedScopeValidatorFactoryImpl implements PredefinedScopeHibernateValidatorFactory { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + /** + * Context containing all {@link ValidatorFactory} level helpers and configuration properties. + */ + private final ValidatorFactoryScopedContext validatorFactoryScopedContext; + + /** + * The constraint validator manager for this factory. + */ + private final ConstraintValidatorManager constraintValidatorManager; + + /** + * Hibernate Validator specific flags to relax constraints on parameters. + */ + private final MethodValidationConfiguration methodValidationConfiguration; + + private final PredefinedScopeBeanMetaDataManager beanMetaDataManager; + + private final ValueExtractorManager valueExtractorManager; + + private final GetterPropertySelectionStrategy getterPropertySelectionStrategy; + + private final ValidationOrderGenerator validationOrderGenerator; + + public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState) { + ClassLoader externalClassLoader = getExternalClassLoader( configurationState ); + + this.valueExtractorManager = new ValueExtractorManager( configurationState.getValueExtractors() ); + + PredefinedScopeConfigurationImpl hibernateSpecificConfig = (PredefinedScopeConfigurationImpl) configurationState; + + Map properties = configurationState.getProperties(); + + this.methodValidationConfiguration = new MethodValidationConfiguration.Builder() + .allowOverridingMethodAlterParameterConstraint( + getAllowOverridingMethodAlterParameterConstraint( hibernateSpecificConfig, properties ) + ).allowMultipleCascadedValidationOnReturnValues( + getAllowMultipleCascadedValidationOnReturnValues( hibernateSpecificConfig, properties ) + ).allowParallelMethodsDefineParameterConstraints( + getAllowParallelMethodsDefineParameterConstraints( hibernateSpecificConfig, properties ) + ).build(); + + this.validatorFactoryScopedContext = new ValidatorFactoryScopedContext( + configurationState.getMessageInterpolator(), + configurationState.getTraversableResolver(), + new ExecutableParameterNameProvider( configurationState.getParameterNameProvider() ), + configurationState.getClockProvider(), + ValidatorFactoryConfigurationHelper.getTemporalValidationTolerance( configurationState, properties ), + ValidatorFactoryConfigurationHelper.getScriptEvaluatorFactory( configurationState, properties, externalClassLoader ), + getFailFast( hibernateSpecificConfig, properties ), + getTraversableResolverResultCacheEnabled( hibernateSpecificConfig, properties ), + getConstraintValidatorPayload( hibernateSpecificConfig ) + ); + + this.constraintValidatorManager = new ConstraintValidatorManagerImpl( + configurationState.getConstraintValidatorFactory(), + this.validatorFactoryScopedContext.getConstraintValidatorInitializationContext() + ); + + this.validationOrderGenerator = new ValidationOrderGenerator(); + + this.getterPropertySelectionStrategy = ValidatorFactoryConfigurationHelper.getGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ); + + ConstraintHelper constraintHelper = new ConstraintHelper(); + TypeResolutionHelper typeResolutionHelper = new TypeResolutionHelper(); + ExecutableHelper executableHelper = new ExecutableHelper( typeResolutionHelper ); + JavaBeanHelper javaBeanHelper = new JavaBeanHelper( ValidatorFactoryConfigurationHelper.getGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ) ); + + // HV-302; don't load XmlMappingParser if not necessary + XmlMetaDataProvider xmlMetaDataProvider; + if ( configurationState.getMappingStreams().isEmpty() ) { + xmlMetaDataProvider = null; + } + else { + xmlMetaDataProvider = new XmlMetaDataProvider( + constraintHelper, typeResolutionHelper, valueExtractorManager, javaBeanHelper, configurationState.getMappingStreams(), externalClassLoader + ); + } + + Set constraintMappings = Collections.unmodifiableSet( + getConstraintMappings( + typeResolutionHelper, + configurationState, + javaBeanHelper, + externalClassLoader + ) + ); + + registerCustomConstraintValidators( constraintMappings, constraintHelper ); + + this.beanMetaDataManager = new PredefinedScopeBeanMetaDataManager( + constraintHelper, + executableHelper, + typeResolutionHelper, + validatorFactoryScopedContext.getParameterNameProvider(), + valueExtractorManager, + javaBeanHelper, + validationOrderGenerator, + buildDataProviders( constraintHelper, typeResolutionHelper, valueExtractorManager, constraintValidatorManager, xmlMetaDataProvider, constraintMappings ), + methodValidationConfiguration, + hibernateSpecificConfig.getBeanClassesToInitialize() + ); + + if ( LOG.isDebugEnabled() ) { + logValidatorFactoryScopedConfiguration( validatorFactoryScopedContext ); + } + } + + @Override + public Validator getValidator() { + return createValidator( validatorFactoryScopedContext ); + } + + @Override + public MessageInterpolator getMessageInterpolator() { + return validatorFactoryScopedContext.getMessageInterpolator(); + } + + @Override + public TraversableResolver getTraversableResolver() { + return validatorFactoryScopedContext.getTraversableResolver(); + } + + @Override + public ConstraintValidatorFactory getConstraintValidatorFactory() { + return constraintValidatorManager.getDefaultConstraintValidatorFactory(); + } + + @Override + public ParameterNameProvider getParameterNameProvider() { + return validatorFactoryScopedContext.getParameterNameProvider().getDelegate(); + } + + public ExecutableParameterNameProvider getExecutableParameterNameProvider() { + return validatorFactoryScopedContext.getParameterNameProvider(); + } + + @Override + public ClockProvider getClockProvider() { + return validatorFactoryScopedContext.getClockProvider(); + } + + @Override + public ScriptEvaluatorFactory getScriptEvaluatorFactory() { + return validatorFactoryScopedContext.getScriptEvaluatorFactory(); + } + + @Override + public Duration getTemporalValidationTolerance() { + return validatorFactoryScopedContext.getTemporalValidationTolerance(); + } + + @Override + public GetterPropertySelectionStrategy getGetterPropertySelectionStrategy() { + return getterPropertySelectionStrategy; + } + + public boolean isFailFast() { + return validatorFactoryScopedContext.isFailFast(); + } + + public boolean isTraversableResolverResultCacheEnabled() { + return validatorFactoryScopedContext.isTraversableResolverResultCacheEnabled(); + } + + @Override + public T unwrap(Class type) { + //allow unwrapping into public super types + if ( type.isAssignableFrom( HibernateValidatorFactory.class ) ) { + return type.cast( this ); + } + throw LOG.getTypeNotSupportedForUnwrappingException( type ); + } + + @Override + public HibernateValidatorContext usingContext() { + return new PredefinedScopeValidatorContextImpl( this ); + } + + @Override + public void close() { + constraintValidatorManager.clear(); + beanMetaDataManager.clear(); + validatorFactoryScopedContext.getScriptEvaluatorFactory().clear(); + valueExtractorManager.clear(); + } + + public ValidatorFactoryScopedContext getValidatorFactoryScopedContext() { + return this.validatorFactoryScopedContext; + } + + Validator createValidator(ValidatorFactoryScopedContext validatorFactoryScopedContext) { + return new ValidatorImpl( + constraintValidatorManager.getDefaultConstraintValidatorFactory(), + beanMetaDataManager, + valueExtractorManager, + constraintValidatorManager, + validationOrderGenerator, + validatorFactoryScopedContext + ); + } + + private static List buildDataProviders( + ConstraintHelper constraintHelper, + TypeResolutionHelper typeResolutionHelper, + ValueExtractorManager valueExtractorManager, + ConstraintValidatorManager constraintValidatorManager, + XmlMetaDataProvider xmlMetaDataProvider, + Set constraintMappings) { + List metaDataProviders = newArrayList(); + if ( xmlMetaDataProvider != null ) { + metaDataProviders.add( xmlMetaDataProvider ); + } + + if ( !constraintMappings.isEmpty() ) { + metaDataProviders.add( + new ProgrammaticMetaDataProvider( + constraintHelper, + typeResolutionHelper, + valueExtractorManager, + constraintMappings + ) + ); + } + return metaDataProviders; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java new file mode 100644 index 0000000000..e88b81d183 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java @@ -0,0 +1,166 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.metadata; + +import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hibernate.validator.internal.engine.MethodValidationConfiguration; +import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataBuilder; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions; +import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider; +import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; +import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; +import org.hibernate.validator.internal.util.CollectionHelper; +import org.hibernate.validator.internal.util.ExecutableHelper; +import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; +import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper; + +public class PredefinedScopeBeanMetaDataManager implements BeanMetaDataManager { + + /** + * Used to cache the constraint meta data for validated entities + */ + private final Map> beanMetaDataMap; + + public PredefinedScopeBeanMetaDataManager(ConstraintHelper constraintHelper, + ExecutableHelper executableHelper, + TypeResolutionHelper typeResolutionHelper, + ExecutableParameterNameProvider parameterNameProvider, + ValueExtractorManager valueExtractorManager, + JavaBeanHelper javaBeanHelper, + ValidationOrderGenerator validationOrderGenerator, + List optionalMetaDataProviders, + MethodValidationConfiguration methodValidationConfiguration, + Set> beanClassesToInitialize) { + AnnotationProcessingOptions annotationProcessingOptions = getAnnotationProcessingOptionsFromNonDefaultProviders( optionalMetaDataProviders ); + AnnotationMetaDataProvider defaultProvider = new AnnotationMetaDataProvider( + constraintHelper, + typeResolutionHelper, + valueExtractorManager, + javaBeanHelper, + annotationProcessingOptions + ); + + List metaDataProviders = new ArrayList<>( optionalMetaDataProviders.size() + 1 ); + // We add the annotation based metadata provider at the first position so that the entire metadata model is assembled + // first. + // The other optional metadata providers will then contribute their additional metadata to the preexisting model. + // This helps to mitigate issues like HV-1450. + metaDataProviders.add( defaultProvider ); + metaDataProviders.addAll( optionalMetaDataProviders ); + + Map> tmpBeanMetadataMap = new HashMap<>(); + + for ( Class validatedClass : beanClassesToInitialize ) { + BeanMetaData beanMetaData = createBeanMetaData( constraintHelper, executableHelper, typeResolutionHelper, parameterNameProvider, valueExtractorManager, + javaBeanHelper, validationOrderGenerator, optionalMetaDataProviders, methodValidationConfiguration, + metaDataProviders, validatedClass ); + + tmpBeanMetadataMap.put( validatedClass.getName(), beanMetaData ); + + for ( Class parentClass : beanMetaData.getClassHierarchy() ) { + tmpBeanMetadataMap.put( parentClass.getName(), + createBeanMetaData( constraintHelper, executableHelper, typeResolutionHelper, parameterNameProvider, valueExtractorManager, + javaBeanHelper, validationOrderGenerator, optionalMetaDataProviders, methodValidationConfiguration, + metaDataProviders, parentClass ) ); + } + } + + this.beanMetaDataMap = CollectionHelper.toImmutableMap( tmpBeanMetadataMap ); + } + + @SuppressWarnings("unchecked") + @Override + public BeanMetaData getBeanMetaData(Class beanClass) { + return (BeanMetaData) beanMetaDataMap.get( beanClass.getName() ); + } + + @Override + public void clear() { + beanMetaDataMap.clear(); + } + + /** + * Creates a {@link org.hibernate.validator.internal.metadata.aggregated.BeanMetaData} containing the meta data from all meta + * data providers for the given type and its hierarchy. + * + * @param The type of interest. + * @param clazz The type's class. + * + * @return A bean meta data object for the given type. + */ + private static BeanMetaDataImpl createBeanMetaData(ConstraintHelper constraintHelper, + ExecutableHelper executableHelper, + TypeResolutionHelper typeResolutionHelper, + ExecutableParameterNameProvider parameterNameProvider, + ValueExtractorManager valueExtractorManager, + JavaBeanHelper javaBeanHelper, + ValidationOrderGenerator validationOrderGenerator, + List optionalMetaDataProviders, + MethodValidationConfiguration methodValidationConfiguration, + List metaDataProviders, + Class clazz) { + BeanMetaDataBuilder builder = BeanMetaDataBuilder.getInstance( + constraintHelper, executableHelper, typeResolutionHelper, valueExtractorManager, parameterNameProvider, validationOrderGenerator, clazz, methodValidationConfiguration ); + + for ( MetaDataProvider provider : metaDataProviders ) { + for ( BeanConfiguration beanConfiguration : getBeanConfigurationForHierarchy( provider, clazz ) ) { + builder.add( beanConfiguration ); + } + } + + return builder.build(); + } + + /** + * @return returns the annotation ignores from the non annotation based meta data providers + */ + private static AnnotationProcessingOptions getAnnotationProcessingOptionsFromNonDefaultProviders(List optionalMetaDataProviders) { + AnnotationProcessingOptions options = new AnnotationProcessingOptionsImpl(); + for ( MetaDataProvider metaDataProvider : optionalMetaDataProviders ) { + options.merge( metaDataProvider.getAnnotationProcessingOptions() ); + } + + return options; + } + + /** + * Returns a list with the configurations for all types contained in the given type's hierarchy (including + * implemented interfaces) starting at the specified type. + * + * @param beanClass The type of interest. + * @param The type of the class to get the configurations for. + * @return A set with the configurations for the complete hierarchy of the given type. May be empty, but never + * {@code null}. + */ + private static List> getBeanConfigurationForHierarchy(MetaDataProvider provider, Class beanClass) { + List> configurations = newArrayList(); + + for ( Class clazz : ClassHierarchyHelper.getHierarchy( beanClass ) ) { + BeanConfiguration configuration = provider.getBeanConfiguration( clazz ); + if ( configuration != null ) { + configurations.add( configuration ); + } + } + + return configurations; + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java new file mode 100644 index 0000000000..7866db996c --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java @@ -0,0 +1,74 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.predefinedscope; + +import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertNoViolations; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; + +import java.util.HashSet; +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.PredefinedScopeHibernateValidator; +import org.hibernate.validator.testutil.TestForIssue; +import org.testng.annotations.Test; + +@TestForIssue(jiraKey = "HV-1667") +public class PredefinedScopeValidatorFactoryTest { + + @Test + public void testValidation() { + Set> beanMetaDataToInitialize = new HashSet<>(); + beanMetaDataToInitialize.add( Bean.class ); + + ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) + .configure() + .initializeBeanMetaData( beanMetaDataToInitialize ) + .buildValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + + Set> violations = validator.validate( new Bean( "property", "test@example.com" ) ); + assertNoViolations( violations ); + + violations = validator.validate( new Bean( null, "invalid" ) ); + assertThat( violations ).containsOnlyViolations( + violationOf( NotNull.class ).withProperty( "property" ), + violationOf( Email.class ).withProperty( "email" ) ); + } + + private static class Bean { + + @NotNull + private String property; + + @Email + private String email; + + private Bean(String property, String email) { + this.property = property; + this.email = email; + } + + @SuppressWarnings("unused") + public String getProperty() { + return property; + } + + @SuppressWarnings("unused") + public String getEmail() { + return email; + } + } +} From 03f70890e9f4d487a39a559f14c749e9b4e07f42 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Sat, 8 Dec 2018 13:56:45 +0100 Subject: [PATCH 140/393] HV-1667 Throw an exception when the bean metadata are uninitialized --- .../ValidationContextBuilder.java | 36 ++++- .../validator/internal/util/logging/Log.java | 3 + .../PredefinedScopeValidatorFactoryTest.java | 142 ++++++++++++++++-- 3 files changed, 164 insertions(+), 17 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java index 8db1873385..ea3c00bf61 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java @@ -6,6 +6,7 @@ */ package org.hibernate.validator.internal.engine.validationcontext; +import java.lang.invoke.MethodHandles; import java.lang.reflect.Executable; import javax.validation.ConstraintValidatorFactory; @@ -16,6 +17,8 @@ import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; /** * Builder for creating {@link AbstractValidationContext}s suited for the different kinds of validation. @@ -25,6 +28,8 @@ */ public class ValidationContextBuilder { + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + private final BeanMetaDataManager beanMetaDataManager; private final ConstraintValidatorManager constraintValidatorManager; private final ConstraintValidatorFactory constraintValidatorFactory; @@ -50,6 +55,10 @@ public ValidationContextBuilder( public BaseBeanValidationContext forValidate(T rootBean) { @SuppressWarnings("unchecked") Class rootBeanClass = (Class) rootBean.getClass(); + BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); + + checkRootBeanMetaData( rootBeanClass, rootBeanMetaData ); + return new BeanValidationContext<>( constraintValidatorManager, constraintValidatorFactory, @@ -58,13 +67,17 @@ public BaseBeanValidationContext forValidate(T rootBean) { constraintValidatorInitializationContext, rootBean, rootBeanClass, - beanMetaDataManager.getBeanMetaData( rootBeanClass ) + rootBeanMetaData ); } public BaseBeanValidationContext forValidateProperty(T rootBean, PathImpl propertyPath) { @SuppressWarnings("unchecked") Class rootBeanClass = (Class) rootBean.getClass(); + BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); + + checkRootBeanMetaData( rootBeanClass, rootBeanMetaData ); + return new PropertyValidationContext<>( constraintValidatorManager, constraintValidatorFactory, @@ -73,12 +86,16 @@ public BaseBeanValidationContext forValidateProperty(T rootBean, PathImpl constraintValidatorInitializationContext, rootBean, rootBeanClass, - beanMetaDataManager.getBeanMetaData( rootBeanClass ), + rootBeanMetaData, propertyPath.getLeafNode().getName() ); } public BaseBeanValidationContext forValidateValue(Class rootBeanClass, PathImpl propertyPath) { + BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); + + checkRootBeanMetaData( rootBeanClass, rootBeanMetaData ); + return new PropertyValidationContext<>( constraintValidatorManager, constraintValidatorFactory, @@ -87,7 +104,7 @@ public BaseBeanValidationContext forValidateValue(Class rootBeanClass, constraintValidatorInitializationContext, null, //root bean rootBeanClass, - beanMetaDataManager.getBeanMetaData( rootBeanClass ), + rootBeanMetaData, propertyPath.getLeafNode().getName() ); } @@ -100,6 +117,8 @@ public ExecutableValidationContext forValidateParameters( Class rootBeanClass = rootBean != null ? (Class) rootBean.getClass() : (Class) executable.getDeclaringClass(); BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); + checkRootBeanMetaData( rootBeanClass, rootBeanMetaData ); + return new ParameterExecutableValidationContext<>( constraintValidatorManager, constraintValidatorFactory, @@ -122,6 +141,9 @@ public ExecutableValidationContext forValidateReturnValue( @SuppressWarnings("unchecked") Class rootBeanClass = rootBean != null ? (Class) rootBean.getClass() : (Class) executable.getDeclaringClass(); BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); + + checkRootBeanMetaData( rootBeanClass, rootBeanMetaData ); + return new ReturnValueExecutableValidationContext<>( constraintValidatorManager, constraintValidatorFactory, @@ -130,10 +152,16 @@ public ExecutableValidationContext forValidateReturnValue( constraintValidatorInitializationContext, rootBean, rootBeanClass, - beanMetaDataManager.getBeanMetaData( rootBeanClass ), + rootBeanMetaData, executable, rootBeanMetaData.getMetaDataFor( executable ), executableReturnValue ); } + + private void checkRootBeanMetaData(Class rootBeanClass, BeanMetaData rootBeanMetaData) { + if ( rootBeanMetaData == null ) { + throw LOG.uninitializedBeanMetaData( rootBeanClass ); + } + } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index c79e7ca4ef..928262bd27 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -875,4 +875,7 @@ ConstraintDefinitionException getConstraintValidatorDefinitionConstraintMismatch @Message(id = 248, value = "Unable to get an XML schema named %s.") ValidationException unableToGetXmlSchema(String schemaResourceName); + + @Message(id = 249, value = "Uninitialized bean metadata for class: %s. Please register your bean class as a class to initialize when initializing your ValidatorFactory.") + ValidationException uninitializedBeanMetaData(@FormatWith(ClassObjectFormatter.class) Class clazz); } diff --git a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java index 7866db996c..2093841994 100644 --- a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java @@ -8,13 +8,16 @@ import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertNoViolations; import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.pathWith; import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; import java.util.HashSet; import java.util.Set; import javax.validation.ConstraintViolation; +import javax.validation.Valid; import javax.validation.Validation; +import javax.validation.ValidationException; import javax.validation.Validator; import javax.validation.ValidatorFactory; import javax.validation.constraints.Email; @@ -28,16 +31,8 @@ public class PredefinedScopeValidatorFactoryTest { @Test - public void testValidation() { - Set> beanMetaDataToInitialize = new HashSet<>(); - beanMetaDataToInitialize.add( Bean.class ); - - ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) - .configure() - .initializeBeanMetaData( beanMetaDataToInitialize ) - .buildValidatorFactory(); - - Validator validator = validatorFactory.getValidator(); + public void testValidation() throws NoSuchMethodException, SecurityException { + Validator validator = getValidator(); Set> violations = validator.validate( new Bean( "property", "test@example.com" ) ); assertNoViolations( violations ); @@ -46,6 +41,100 @@ public void testValidation() { assertThat( violations ).containsOnlyViolations( violationOf( NotNull.class ).withProperty( "property" ), violationOf( Email.class ).withProperty( "email" ) ); + + violations = validator.forExecutables() + .validateParameters( new Bean(), Bean.class.getMethod( "setEmail", String.class ), + new Object[]{ "invalid" } ); + assertThat( violations ).containsOnlyViolations( + violationOf( Email.class ) + .withPropertyPath( pathWith().method( "setEmail" ).parameter( "email", 0 ) ) ); + + violations = validator.forExecutables() + .validateReturnValue( new Bean(), Bean.class.getMethod( "getEmail" ), "invalid" ); + assertThat( violations ).containsOnlyViolations( + violationOf( Email.class ) + .withPropertyPath( pathWith().method( "getEmail" ).returnValue() ) ); + + violations = validator.forExecutables() + .validateConstructorParameters( Bean.class.getConstructor( String.class, String.class ), + new Object[]{ null, "invalid" } ); + assertThat( violations ).containsOnlyViolations( + violationOf( NotNull.class ) + .withPropertyPath( pathWith().constructor( Bean.class ).parameter( "property", 0 ) ), + violationOf( Email.class ) + .withPropertyPath( pathWith().constructor( Bean.class ).parameter( "email", 1 ) ) ); + + violations = validator.forExecutables() + .validateConstructorReturnValue( Bean.class.getConstructor( String.class, String.class ), + new Bean( null, "invalid" ) ); + assertThat( violations ).containsOnlyViolations( + violationOf( NotNull.class ) + .withPropertyPath( pathWith().constructor( Bean.class ).returnValue() + .property( "property" ) ), + violationOf( Email.class ) + .withPropertyPath( pathWith().constructor( Bean.class ).returnValue() + .property( "email" ) ) ); + } + + @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000249:.*") + public void testValidationOnUnknownBean() throws NoSuchMethodException, SecurityException { + Validator validator = getValidator(); + + Set> violations = validator.validate( new UnknownBean() ); + assertNoViolations( violations ); + } + + @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000249:.*") + public void testValidationOnUnknownBeanMethodParameter() throws NoSuchMethodException, SecurityException { + Validator validator = getValidator(); + + Set> violations = validator.validate( new UnknownBean() ); + assertNoViolations( violations ); + + violations = validator.forExecutables() + .validateParameters( new UnknownBean(), UnknownBean.class.getMethod( "setMethod", String.class ), + new Object[]{ "" } ); + assertNoViolations( violations ); + } + + @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000249:.*") + public void testValidationOnUnknownBeanMethodReturnValue() throws NoSuchMethodException, SecurityException { + Validator validator = getValidator(); + + Set> violations = validator.forExecutables() + .validateReturnValue( new UnknownBean(), UnknownBean.class.getMethod( "getMethod" ), "" ); + assertNoViolations( violations ); + } + + @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000249:.*") + public void testValidationOnUnknownBeanConstructorParameters() throws NoSuchMethodException, SecurityException { + Validator validator = getValidator(); + + Set> violations = validator.forExecutables() + .validateConstructorParameters( UnknownBean.class.getConstructor( String.class ), + new Object[]{ "" } ); + assertNoViolations( violations ); + } + + @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000249:.*") + public void testValidationOnUnknownBeanConstructorReturnValue() throws NoSuchMethodException, SecurityException { + Validator validator = getValidator(); + + Set> violations = validator.forExecutables() + .validateConstructorReturnValue( UnknownBean.class.getConstructor( String.class ), new UnknownBean() ); + assertNoViolations( violations ); + } + + private static Validator getValidator() { + Set> beanMetaDataToInitialize = new HashSet<>(); + beanMetaDataToInitialize.add( Bean.class ); + + ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) + .configure() + .initializeBeanMetaData( beanMetaDataToInitialize ) + .buildValidatorFactory(); + + return validatorFactory.getValidator(); } private static class Bean { @@ -56,7 +145,11 @@ private static class Bean { @Email private String email; - private Bean(String property, String email) { + public Bean() { + } + + @Valid + public Bean(@NotNull String property, @Email String email) { this.property = property; this.email = email; } @@ -66,9 +159,32 @@ public String getProperty() { return property; } - @SuppressWarnings("unused") - public String getEmail() { + public @Email String getEmail() { return email; } + + @SuppressWarnings("unused") + public void setEmail(@Email String email) { + this.email = email; + } + } + + private static class UnknownBean { + + public UnknownBean() { + } + + @SuppressWarnings("unused") + public UnknownBean(String parameter) { + } + + @SuppressWarnings("unused") + public String getMethod() { + return null; + } + + @SuppressWarnings("unused") + public void setMethod(String parameter) { + } } } From 95d966e44592a016fcb9fb1e5f4311540ca37b16 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Sat, 8 Dec 2018 13:57:33 +0100 Subject: [PATCH 141/393] HV-1667 Introduce ConstraintCreationContext --- ...tPropertyConstraintMappingContextImpl.java | 6 +- ...dableConstraintMappingContextImplBase.java | 8 +- .../ConstraintMappingContextImplBase.java | 18 ++- ...erElementConstraintMappingContextImpl.java | 19 ++- .../cfg/context/DefaultConstraintMapping.java | 14 +-- ...xecutableConstraintMappingContextImpl.java | 20 ++- .../FieldConstraintMappingContextImpl.java | 11 +- .../GetterConstraintMappingContextImpl.java | 11 +- ...ParameterConstraintMappingContextImpl.java | 11 +- .../TypeConstraintMappingContextImpl.java | 18 ++- .../engine/ConstraintCreationContext.java | 49 ++++++++ .../PredefinedScopeValidatorFactoryImpl.java | 31 ++--- .../internal/engine/ValidatorContextImpl.java | 13 +- .../internal/engine/ValidatorFactoryImpl.java | 114 ++++++++---------- .../metadata/BeanMetaDataManagerImpl.java | 37 ++---- .../PredefinedScopeBeanMetaDataManager.java | 23 ++-- .../aggregated/BeanMetaDataBuilder.java | 60 +++------ .../metadata/aggregated/ClassMetaData.java | 9 +- .../aggregated/ExecutableMetaData.java | 16 +-- .../metadata/aggregated/MetaDataBuilder.java | 20 ++- .../aggregated/ParameterMetaData.java | 12 +- .../metadata/aggregated/PropertyMetaData.java | 21 ++-- .../metadata/core/MetaConstraint.java | 4 +- .../metadata/core/MetaConstraints.java | 4 +- .../provider/AnnotationMetaDataProvider.java | 56 +++++---- .../ProgrammaticMetaDataProvider.java | 17 +-- .../provider/XmlMetaDataProvider.java | 10 +- ...AbstractConstrainedElementStaxBuilder.java | 21 ++-- ...nstrainedExecutableElementStaxBuilder.java | 24 ++-- .../internal/xml/mapping/BeanStaxBuilder.java | 29 ++--- .../ClassConstraintTypeStaxBuilder.java | 18 +-- .../ConstrainedConstructorStaxBuilder.java | 11 +- .../mapping/ConstrainedFieldStaxBuilder.java | 11 +- .../mapping/ConstrainedGetterStaxBuilder.java | 13 +- .../mapping/ConstrainedMethodStaxBuilder.java | 11 +- .../ConstrainedParameterStaxBuilder.java | 11 +- .../ConstraintMappingsStaxBuilder.java | 19 ++- .../mapping/ConstraintTypeStaxBuilder.java | 20 ++- .../ContainerElementTypeStaxBuilder.java | 22 ++-- .../mapping/CrossParameterStaxBuilder.java | 17 +-- .../xml/mapping/MappingXmlParser.java | 18 +-- .../xml/mapping/ReturnValueStaxBuilder.java | 9 +- .../test/cfg/ConstraintMappingTest.java | 10 +- .../internal/engine/path/PathImplTest.java | 7 +- .../metadata/BeanMetaDataManagerTest.java | 7 +- .../aggregated/ExecutableMetaDataTest.java | 7 +- .../aggregated/ParameterMetaDataTest.java | 11 +- .../aggregated/PropertyMetaDataTest.java | 7 +- .../metadata/core/MetaConstraintTest.java | 12 +- .../descriptor/BeanDescriptorTest.java | 2 +- .../AnnotationMetaDataProviderTest.java | 10 +- .../TypeAnnotationMetaDataRetrievalTest.java | 8 +- .../internal/xml/MappingXmlParserTest.java | 17 ++- ...nstraintValidatorInitializationHelper.java | 13 ++ .../integrationtest/OsgiIntegrationTest.java | 2 +- 55 files changed, 424 insertions(+), 575 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/ConstraintCreationContext.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/AbstractPropertyConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/AbstractPropertyConstraintMappingContextImpl.java index b0f987b5cd..056470024c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/AbstractPropertyConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/AbstractPropertyConstraintMappingContextImpl.java @@ -12,13 +12,11 @@ import org.hibernate.validator.cfg.context.ContainerElementConstraintMappingContext; import org.hibernate.validator.cfg.context.MethodConstraintMappingContext; import org.hibernate.validator.cfg.context.PropertyConstraintMappingContext; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.properties.Property; -import org.hibernate.validator.internal.util.TypeResolutionHelper; /** * Constraint mapping creational context which allows to configure the constraints for one bean property. @@ -98,7 +96,7 @@ public ContainerElementConstraintMappingContext containerElementType(int index, return super.containerElement( this, typeContext, location, index, nestedIndexes ); } - abstract ConstrainedElement build(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager); + abstract ConstrainedElement build(ConstraintCreationContext constraintCreationContext); @Override protected ConstraintType getConstraintType() { diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/CascadableConstraintMappingContextImplBase.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/CascadableConstraintMappingContextImplBase.java index a8f40b8944..b77845420a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/CascadableConstraintMappingContextImplBase.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/CascadableConstraintMappingContextImplBase.java @@ -23,14 +23,12 @@ import org.hibernate.validator.cfg.context.ContainerElementConstraintMappingContext; import org.hibernate.validator.cfg.context.ContainerElementTarget; import org.hibernate.validator.cfg.context.GroupConversionTargetContext; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.TypeHelper; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -151,10 +149,10 @@ public boolean isCascading() { return isCascading; } - protected Set> getTypeArgumentConstraints(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { + protected Set> getTypeArgumentConstraints(ConstraintCreationContext constraintCreationContext) { return containerElementContexts.values() .stream() - .map( t -> t.build( constraintHelper, typeResolutionHelper, valueExtractorManager ) ) + .map( t -> t.build( constraintCreationContext ) ) .flatMap( Set::stream ) .collect( Collectors.toSet() ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintMappingContextImplBase.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintMappingContextImplBase.java index 3598e1d70f..8207726486 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintMappingContextImplBase.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ConstraintMappingContextImplBase.java @@ -12,13 +12,11 @@ import java.util.Collections; import java.util.Set; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.core.MetaConstraints; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; -import org.hibernate.validator.internal.util.TypeResolutionHelper; /** * Base class for implementations of constraint mapping creational context types. @@ -54,8 +52,7 @@ protected void addConstraint(ConfiguredConstraint constraint) { constraints.add( constraint ); } - protected Set> getConstraints(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager) { + protected Set> getConstraints(ConstraintCreationContext constraintCreationContext) { if ( constraints == null ) { return Collections.emptySet(); } @@ -63,22 +60,23 @@ protected Set> getConstraints(ConstraintHelper constraintHelpe Set> metaConstraints = newHashSet(); for ( ConfiguredConstraint configuredConstraint : constraints ) { - metaConstraints.add( asMetaConstraint( configuredConstraint, constraintHelper, typeResolutionHelper, valueExtractorManager ) ); + metaConstraints.add( asMetaConstraint( configuredConstraint, constraintCreationContext ) ); } return metaConstraints; } - private MetaConstraint asMetaConstraint(ConfiguredConstraint config, ConstraintHelper constraintHelper, - TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { + private MetaConstraint asMetaConstraint(ConfiguredConstraint config, ConstraintCreationContext constraintCreationContext ) { ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl( - constraintHelper, + constraintCreationContext.getConstraintHelper(), config.getLocation().getConstrainable(), config.createAnnotationDescriptor(), config.getLocation().getKind(), getConstraintType() ); - return MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor, config.getLocation() ); + return MetaConstraints.create( constraintCreationContext.getTypeResolutionHelper(), + constraintCreationContext.getValueExtractorManager(), + constraintCreationContext.getConstraintValidatorManager(), constraintDescriptor, config.getLocation() ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java index 7a00c66cd4..9502eeb08b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ContainerElementConstraintMappingContextImpl.java @@ -31,10 +31,9 @@ import org.hibernate.validator.cfg.context.PropertyConstraintMappingContext; import org.hibernate.validator.cfg.context.ReturnValueConstraintMappingContext; import org.hibernate.validator.cfg.context.ReturnValueTarget; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.engine.valueextraction.ArrayElement; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.core.MetaConstraints; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; @@ -43,7 +42,6 @@ import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.StringHelper; import org.hibernate.validator.internal.util.TypeHelper; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -231,30 +229,29 @@ CascadingMetaDataBuilder getContainerElementCascadingMetaDataBuilder() { ); } - Set> build(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager) { + Set> build(ConstraintCreationContext constraintCreationContext) { return Stream.concat( constraints.stream() - .map( c -> asMetaConstraint( c, constraintHelper, typeResolutionHelper, valueExtractorManager ) ), + .map( c -> asMetaConstraint( c, constraintCreationContext ) ), nestedContainerElementContexts.values() .stream() - .map( c -> c.build( constraintHelper, typeResolutionHelper, valueExtractorManager ) ) + .map( c -> c.build( constraintCreationContext ) ) .flatMap( Set::stream ) ) .collect( Collectors.toSet() ); } - private MetaConstraint asMetaConstraint(ConfiguredConstraint config, ConstraintHelper constraintHelper, - TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { + private MetaConstraint asMetaConstraint(ConfiguredConstraint config, ConstraintCreationContext constraintCreationContext) { ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl<>( - constraintHelper, + constraintCreationContext.getConstraintHelper(), config.getLocation().getConstrainable(), config.createAnnotationDescriptor(), config.getLocation().getKind(), getConstraintType() ); - return MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor, config.getLocation() ); + return MetaConstraints.create( constraintCreationContext.getTypeResolutionHelper(), constraintCreationContext.getValueExtractorManager(), + constraintCreationContext.getConstraintValidatorManager(), constraintDescriptor, config.getLocation() ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/DefaultConstraintMapping.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/DefaultConstraintMapping.java index 5aa56c623d..9b48ab7138 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/DefaultConstraintMapping.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/DefaultConstraintMapping.java @@ -14,19 +14,16 @@ import java.util.Set; import javax.validation.Constraint; -import javax.validation.valueextraction.ValueExtractor; import org.hibernate.validator.cfg.ConstraintMapping; import org.hibernate.validator.cfg.context.ConstraintDefinitionContext; import org.hibernate.validator.cfg.context.TypeConstraintMappingContext; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.engine.constraintdefinition.ConstraintDefinitionContribution; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.Contracts; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -83,18 +80,15 @@ public Set> getConfiguredTypes() { /** * Returns all bean configurations configured through this constraint mapping. * - * @param constraintHelper constraint helper required for building constraint descriptors - * @param typeResolutionHelper type resolution helper - * @param valueExtractorManager the {@link ValueExtractor} manager + * @param constraintCreationContext the constraint creation context * * @return a set of {@link BeanConfiguration}s with an element for each type configured through this mapping */ - public Set> getBeanConfigurations(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager) { + public Set> getBeanConfigurations(ConstraintCreationContext constraintCreationContext) { Set> configurations = newHashSet(); for ( TypeConstraintMappingContextImpl typeContext : typeContexts ) { - configurations.add( typeContext.build( constraintHelper, typeResolutionHelper, valueExtractorManager ) ); + configurations.add( typeContext.build( constraintCreationContext ) ); } return configurations; diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ExecutableConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ExecutableConstraintMappingContextImpl.java index 503c284637..260a741654 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ExecutableConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ExecutableConstraintMappingContextImpl.java @@ -15,16 +15,14 @@ import org.hibernate.validator.cfg.context.CrossParameterConstraintMappingContext; import org.hibernate.validator.cfg.context.ParameterConstraintMappingContext; import org.hibernate.validator.cfg.context.ReturnValueConstraintMappingContext; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; import org.hibernate.validator.internal.properties.Callable; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -103,27 +101,25 @@ public TypeConstraintMappingContextImpl getTypeContext() { return typeContext; } - public ConstrainedElement build(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager) { + public ConstrainedElement build(ConstraintCreationContext constraintCreationContext) { return new ConstrainedExecutable( ConfigurationSource.API, callable, - getParameters( constraintHelper, typeResolutionHelper, valueExtractorManager ), - crossParameterContext != null ? crossParameterContext.getConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ) : Collections.>emptySet(), - returnValueContext != null ? returnValueContext.getConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ) : Collections.>emptySet(), - returnValueContext != null ? returnValueContext.getTypeArgumentConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ) : Collections.>emptySet(), + getParameters( constraintCreationContext ), + crossParameterContext != null ? crossParameterContext.getConstraints( constraintCreationContext ) : Collections.>emptySet(), + returnValueContext != null ? returnValueContext.getConstraints( constraintCreationContext ) : Collections.>emptySet(), + returnValueContext != null ? returnValueContext.getTypeArgumentConstraints( constraintCreationContext ) : Collections.>emptySet(), returnValueContext != null ? returnValueContext.getCascadingMetaDataBuilder() : CascadingMetaDataBuilder.nonCascading() ); } - private List getParameters(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager) { + private List getParameters(ConstraintCreationContext constraintCreationContext) { List constrainedParameters = newArrayList(); for ( int i = 0; i < parameterContexts.length; i++ ) { ParameterConstraintMappingContextImpl parameter = parameterContexts[i]; if ( parameter != null ) { - constrainedParameters.add( parameter.build( constraintHelper, typeResolutionHelper, valueExtractorManager ) ); + constrainedParameters.add( parameter.build( constraintCreationContext ) ); } else { constrainedParameters.add( diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldConstraintMappingContextImpl.java index bc77618fb6..984b920ac8 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/FieldConstraintMappingContextImpl.java @@ -8,15 +8,13 @@ import org.hibernate.validator.cfg.ConstraintDef; import org.hibernate.validator.cfg.context.PropertyConstraintMappingContext; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; -import org.hibernate.validator.internal.util.TypeResolutionHelper; /** * An implementation of {@link AbstractPropertyConstraintMappingContextImpl} for a field property. @@ -41,12 +39,13 @@ definition, getProperty() return this; } - ConstrainedElement build(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { + @Override + ConstrainedElement build(ConstraintCreationContext constraintCreationContext) { return new ConstrainedField( ConfigurationSource.API, getProperty(), - getConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), - getTypeArgumentConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), + getConstraints( constraintCreationContext ), + getTypeArgumentConstraints( constraintCreationContext ), getCascadingMetaDataBuilder() ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterConstraintMappingContextImpl.java index e78c2534cc..16b72d9b32 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/GetterConstraintMappingContextImpl.java @@ -8,14 +8,12 @@ import org.hibernate.validator.cfg.ConstraintDef; import org.hibernate.validator.cfg.context.PropertyConstraintMappingContext; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; -import org.hibernate.validator.internal.util.TypeResolutionHelper; /** * An implementation of {@link AbstractPropertyConstraintMappingContextImpl} for a getter property. @@ -40,12 +38,13 @@ definition, getProperty() return this; } - ConstrainedElement build(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { + @Override + ConstrainedElement build(ConstraintCreationContext constraintCreationContext) { return new ConstrainedExecutable( ConfigurationSource.API, getProperty(), - getConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), - getTypeArgumentConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), + getConstraints( constraintCreationContext ), + getTypeArgumentConstraints( constraintCreationContext ), getCascadingMetaDataBuilder() ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ParameterConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ParameterConstraintMappingContextImpl.java index 314b23f1c7..1fb43860d4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ParameterConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/ParameterConstraintMappingContextImpl.java @@ -15,13 +15,11 @@ import org.hibernate.validator.cfg.context.MethodConstraintMappingContext; import org.hibernate.validator.cfg.context.ParameterConstraintMappingContext; import org.hibernate.validator.cfg.context.ReturnValueConstraintMappingContext; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; -import org.hibernate.validator.internal.util.TypeResolutionHelper; /** * Constraint mapping creational context which allows to configure the constraints for one method parameter. @@ -119,8 +117,7 @@ public ContainerElementConstraintMappingContext containerElementType(int index, ); } - public ConstrainedParameter build(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager) { + public ConstrainedParameter build(ConstraintCreationContext constraintCreationContext) { Type parameterType = executableContext.getCallable().getParameterGenericType( parameterIndex ); return new ConstrainedParameter( @@ -128,8 +125,8 @@ public ConstrainedParameter build(ConstraintHelper constraintHelper, TypeResolut executableContext.getCallable(), parameterType, parameterIndex, - getConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), - getTypeArgumentConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ), + getConstraints( constraintCreationContext ), + getTypeArgumentConstraints( constraintCreationContext ), getCascadingMetaDataBuilder() ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java index fcf2d401dc..20c012e4e8 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/cfg/context/TypeConstraintMappingContextImpl.java @@ -23,8 +23,7 @@ import org.hibernate.validator.cfg.context.MethodConstraintMappingContext; import org.hibernate.validator.cfg.context.PropertyConstraintMappingContext; import org.hibernate.validator.cfg.context.TypeConstraintMappingContext; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; @@ -38,7 +37,6 @@ import org.hibernate.validator.internal.properties.javabean.JavaBeanMethod; import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.ExecutableHelper; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.util.privilegedactions.NewInstance; @@ -230,19 +228,17 @@ public ConstructorConstraintMappingContext constructor(Class... parameterType return context; } - BeanConfiguration build(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager) { + BeanConfiguration build(ConstraintCreationContext constraintCreationContext) { return new BeanConfiguration<>( ConfigurationSource.API, beanClass, - buildConstraintElements( constraintHelper, typeResolutionHelper, valueExtractorManager ), + buildConstraintElements( constraintCreationContext ), defaultGroupSequence, getDefaultGroupSequenceProvider() ); } - private Set buildConstraintElements(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager) { + private Set buildConstraintElements(ConstraintCreationContext constraintCreationContext) { Set elements = newHashSet(); //class-level configuration @@ -250,18 +246,18 @@ private Set buildConstraintElements(ConstraintHelper constra new ConstrainedType( ConfigurationSource.API, beanClass, - getConstraints( constraintHelper, typeResolutionHelper, valueExtractorManager ) + getConstraints( constraintCreationContext ) ) ); //constructors/methods for ( ExecutableConstraintMappingContextImpl executableContext : executableContexts ) { - elements.add( executableContext.build( constraintHelper, typeResolutionHelper, valueExtractorManager ) ); + elements.add( executableContext.build( constraintCreationContext ) ); } //properties for ( AbstractPropertyConstraintMappingContextImpl propertyContext : propertyContexts ) { - elements.add( propertyContext.build( constraintHelper, typeResolutionHelper, valueExtractorManager ) ); + elements.add( propertyContext.build( constraintCreationContext ) ); } return elements; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ConstraintCreationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ConstraintCreationContext.java new file mode 100644 index 0000000000..8a8ce2c573 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ConstraintCreationContext.java @@ -0,0 +1,49 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine; + +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.util.TypeResolutionHelper; + +public class ConstraintCreationContext { + + private final ConstraintHelper constraintHelper; + + private final ConstraintValidatorManager constraintValidatorManager; + + private final TypeResolutionHelper typeResolutionHelper; + + private final ValueExtractorManager valueExtractorManager; + + public ConstraintCreationContext(ConstraintHelper constraintHelper, + ConstraintValidatorManager constraintValidatorManager, + TypeResolutionHelper typeResolutionHelper, + ValueExtractorManager valueExtractorManager) { + this.constraintHelper = constraintHelper; + this.constraintValidatorManager = constraintValidatorManager; + this.typeResolutionHelper = typeResolutionHelper; + this.valueExtractorManager = valueExtractorManager; + } + + public ConstraintHelper getConstraintHelper() { + return constraintHelper; + } + + public ConstraintValidatorManager getConstraintValidatorManager() { + return constraintValidatorManager; + } + + public TypeResolutionHelper getTypeResolutionHelper() { + return typeResolutionHelper; + } + + public ValueExtractorManager getValueExtractorManager() { + return valueExtractorManager; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java index 4f9bf634d5..b738a6dc9b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java @@ -91,8 +91,6 @@ public class PredefinedScopeValidatorFactoryImpl implements PredefinedScopeHiber public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState) { ClassLoader externalClassLoader = getExternalClassLoader( configurationState ); - this.valueExtractorManager = new ValueExtractorManager( configurationState.getValueExtractors() ); - PredefinedScopeConfigurationImpl hibernateSpecificConfig = (PredefinedScopeConfigurationImpl) configurationState; Map properties = configurationState.getProperties(); @@ -127,8 +125,13 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState this.getterPropertySelectionStrategy = ValidatorFactoryConfigurationHelper.getGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ); + this.valueExtractorManager = new ValueExtractorManager( configurationState.getValueExtractors() ); ConstraintHelper constraintHelper = new ConstraintHelper(); TypeResolutionHelper typeResolutionHelper = new TypeResolutionHelper(); + + ConstraintCreationContext constraintCreationContext = new ConstraintCreationContext( constraintHelper, + constraintValidatorManager, typeResolutionHelper, valueExtractorManager ); + ExecutableHelper executableHelper = new ExecutableHelper( typeResolutionHelper ); JavaBeanHelper javaBeanHelper = new JavaBeanHelper( ValidatorFactoryConfigurationHelper.getGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ) ); @@ -139,7 +142,7 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState } else { xmlMetaDataProvider = new XmlMetaDataProvider( - constraintHelper, typeResolutionHelper, valueExtractorManager, javaBeanHelper, configurationState.getMappingStreams(), externalClassLoader + constraintCreationContext, javaBeanHelper, configurationState.getMappingStreams(), externalClassLoader ); } @@ -155,14 +158,12 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState registerCustomConstraintValidators( constraintMappings, constraintHelper ); this.beanMetaDataManager = new PredefinedScopeBeanMetaDataManager( - constraintHelper, + constraintCreationContext, executableHelper, - typeResolutionHelper, validatorFactoryScopedContext.getParameterNameProvider(), - valueExtractorManager, javaBeanHelper, validationOrderGenerator, - buildDataProviders( constraintHelper, typeResolutionHelper, valueExtractorManager, constraintValidatorManager, xmlMetaDataProvider, constraintMappings ), + buildMetaDataProviders( constraintCreationContext, xmlMetaDataProvider, constraintMappings ), methodValidationConfiguration, hibernateSpecificConfig.getBeanClassesToInitialize() ); @@ -266,11 +267,8 @@ Validator createValidator(ValidatorFactoryScopedContext validatorFactoryScopedCo ); } - private static List buildDataProviders( - ConstraintHelper constraintHelper, - TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager, - ConstraintValidatorManager constraintValidatorManager, + private static List buildMetaDataProviders( + ConstraintCreationContext constraintCreationContext, XmlMetaDataProvider xmlMetaDataProvider, Set constraintMappings) { List metaDataProviders = newArrayList(); @@ -279,14 +277,7 @@ private static List buildDataProviders( } if ( !constraintMappings.isEmpty() ) { - metaDataProviders.add( - new ProgrammaticMetaDataProvider( - constraintHelper, - typeResolutionHelper, - valueExtractorManager, - constraintMappings - ) - ); + metaDataProviders.add( new ProgrammaticMetaDataProvider( constraintCreationContext, constraintMappings ) ); } return metaDataProviders; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorContextImpl.java index 5ee8cba70f..cee1fd75f4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorContextImpl.java @@ -40,7 +40,7 @@ public class ValidatorContextImpl implements HibernateValidatorContext { private ConstraintValidatorFactory constraintValidatorFactory; private final ValidatorFactoryScopedContext.Builder validatorFactoryScopedContextBuilder; - private final ValueExtractorManager valueExtractorManager; + private final ConstraintCreationContext constraintCreationContext; private final MethodValidationConfiguration.Builder methodValidationConfigurationBuilder; private final Map valueExtractorDescriptors; @@ -48,8 +48,8 @@ public ValidatorContextImpl(ValidatorFactoryImpl validatorFactory) { this.validatorFactoryScopedContextBuilder = new ValidatorFactoryScopedContext.Builder( validatorFactory.getValidatorFactoryScopedContext() ); this.validatorFactory = validatorFactory; this.constraintValidatorFactory = validatorFactory.getConstraintValidatorFactory(); + this.constraintCreationContext = validatorFactory.getConstraintCreationContext(); this.methodValidationConfigurationBuilder = new MethodValidationConfiguration.Builder( validatorFactory.getMethodValidationConfiguration() ); - this.valueExtractorManager = validatorFactory.getValueExtractorManager(); this.valueExtractorDescriptors = new HashMap<>(); } @@ -146,9 +146,12 @@ public HibernateValidatorContext constraintValidatorPayload(Object dynamicPayloa public Validator getValidator() { return validatorFactory.createValidator( constraintValidatorFactory, - valueExtractorDescriptors.isEmpty() ? valueExtractorManager : new ValueExtractorManager( valueExtractorManager, valueExtractorDescriptors ), + valueExtractorDescriptors.isEmpty() + ? constraintCreationContext + : new ConstraintCreationContext( constraintCreationContext.getConstraintHelper(), + constraintCreationContext.getConstraintValidatorManager(), constraintCreationContext.getTypeResolutionHelper(), + new ValueExtractorManager( constraintCreationContext.getValueExtractorManager(), valueExtractorDescriptors ) ), validatorFactoryScopedContextBuilder.build(), - methodValidationConfigurationBuilder.build() - ); + methodValidationConfigurationBuilder.build() ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java index 3b06c4ce33..0cddf32457 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java @@ -81,11 +81,6 @@ public class ValidatorFactoryImpl implements HibernateValidatorFactory { */ private final ValidatorFactoryScopedContext validatorFactoryScopedContext; - /** - * The constraint validator manager for this factory. - */ - private final ConstraintValidatorManager constraintValidatorManager; - /** * Programmatic constraints passed via the Hibernate Validator specific API. Empty if there are * no programmatic constraints @@ -94,14 +89,9 @@ public class ValidatorFactoryImpl implements HibernateValidatorFactory { private final Set constraintMappings; /** - * Helper for dealing with built-in validators and determining custom constraint annotations. + * The constraint creation context containing all the helpers necessary to the constraint creation. */ - private final ConstraintHelper constraintHelper; - - /** - * Used for resolving type parameters. Thread-safe. - */ - private final TypeResolutionHelper typeResolutionHelper; + private final ConstraintCreationContext constraintCreationContext; /** * Used for discovering overridden methods. Thread-safe. @@ -126,9 +116,7 @@ public class ValidatorFactoryImpl implements HibernateValidatorFactory { * provider. See also HV-659. */ @ThreadSafe - private final ConcurrentMap beanMetaDataManagers; - - private final ValueExtractorManager valueExtractorManager; + private final ConcurrentMap beanMetaDataManagers = new ConcurrentHashMap<>(); private final JavaBeanHelper javaBeanHelper; @@ -137,12 +125,6 @@ public class ValidatorFactoryImpl implements HibernateValidatorFactory { public ValidatorFactoryImpl(ConfigurationState configurationState) { ClassLoader externalClassLoader = getExternalClassLoader( configurationState ); - this.valueExtractorManager = new ValueExtractorManager( configurationState.getValueExtractors() ); - this.beanMetaDataManagers = new ConcurrentHashMap<>(); - this.constraintHelper = new ConstraintHelper(); - this.typeResolutionHelper = new TypeResolutionHelper(); - this.executableHelper = new ExecutableHelper( typeResolutionHelper ); - ConfigurationImpl hibernateSpecificConfig = null; if ( configurationState instanceof ConfigurationImpl ) { hibernateSpecificConfig = (ConfigurationImpl) configurationState; @@ -150,29 +132,6 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { Map properties = configurationState.getProperties(); - this.javaBeanHelper = new JavaBeanHelper( ValidatorFactoryConfigurationHelper.getGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ) ); - - // HV-302; don't load XmlMappingParser if not necessary - if ( configurationState.getMappingStreams().isEmpty() ) { - this.xmlMetaDataProvider = null; - } - else { - this.xmlMetaDataProvider = new XmlMetaDataProvider( - constraintHelper, typeResolutionHelper, valueExtractorManager, javaBeanHelper, configurationState.getMappingStreams(), externalClassLoader - ); - } - - this.constraintMappings = Collections.unmodifiableSet( - getConstraintMappings( - typeResolutionHelper, - configurationState, - javaBeanHelper, - externalClassLoader - ) - ); - - registerCustomConstraintValidators( constraintMappings, constraintHelper ); - this.methodValidationConfiguration = new MethodValidationConfiguration.Builder() .allowOverridingMethodAlterParameterConstraint( getAllowOverridingMethodAlterParameterConstraint( hibernateSpecificConfig, properties ) @@ -194,13 +153,41 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { getConstraintValidatorPayload( hibernateSpecificConfig ) ); - this.constraintValidatorManager = new ConstraintValidatorManagerImpl( + ConstraintValidatorManager constraintValidatorManager = new ConstraintValidatorManagerImpl( configurationState.getConstraintValidatorFactory(), this.validatorFactoryScopedContext.getConstraintValidatorInitializationContext() ); this.validationOrderGenerator = new ValidationOrderGenerator(); + ValueExtractorManager valueExtractorManager = new ValueExtractorManager( configurationState.getValueExtractors() ); + ConstraintHelper constraintHelper = new ConstraintHelper(); + TypeResolutionHelper typeResolutionHelper = new TypeResolutionHelper(); + + this.constraintCreationContext = new ConstraintCreationContext( constraintHelper, constraintValidatorManager, typeResolutionHelper, valueExtractorManager ); + + this.executableHelper = new ExecutableHelper( typeResolutionHelper ); + this.javaBeanHelper = new JavaBeanHelper( ValidatorFactoryConfigurationHelper.getGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ) ); + + // HV-302; don't load XmlMappingParser if not necessary + if ( configurationState.getMappingStreams().isEmpty() ) { + this.xmlMetaDataProvider = null; + } + else { + this.xmlMetaDataProvider = new XmlMetaDataProvider( constraintCreationContext, javaBeanHelper, configurationState.getMappingStreams(), externalClassLoader ); + } + + this.constraintMappings = Collections.unmodifiableSet( + getConstraintMappings( + typeResolutionHelper, + configurationState, + javaBeanHelper, + externalClassLoader + ) + ); + + registerCustomConstraintValidators( constraintMappings, constraintHelper ); + if ( LOG.isDebugEnabled() ) { logValidatorFactoryScopedConfiguration( validatorFactoryScopedContext ); } @@ -209,8 +196,8 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { @Override public Validator getValidator() { return createValidator( - constraintValidatorManager.getDefaultConstraintValidatorFactory(), - valueExtractorManager, + constraintCreationContext.getConstraintValidatorManager().getDefaultConstraintValidatorFactory(), + constraintCreationContext, validatorFactoryScopedContext, methodValidationConfiguration ); @@ -228,7 +215,7 @@ public TraversableResolver getTraversableResolver() { @Override public ConstraintValidatorFactory getConstraintValidatorFactory() { - return constraintValidatorManager.getDefaultConstraintValidatorFactory(); + return constraintCreationContext.getConstraintValidatorManager().getDefaultConstraintValidatorFactory(); } @Override @@ -272,8 +259,8 @@ public boolean isTraversableResolverResultCacheEnabled() { return validatorFactoryScopedContext.isTraversableResolverResultCacheEnabled(); } - ValueExtractorManager getValueExtractorManager() { - return valueExtractorManager; + ConstraintCreationContext getConstraintCreationContext() { + return constraintCreationContext; } @Override @@ -292,13 +279,13 @@ public HibernateValidatorContext usingContext() { @Override public void close() { - constraintValidatorManager.clear(); - constraintHelper.clear(); + constraintCreationContext.getConstraintValidatorManager().clear(); + constraintCreationContext.getConstraintHelper().clear(); for ( BeanMetaDataManager beanMetaDataManager : beanMetaDataManagers.values() ) { beanMetaDataManager.clear(); } validatorFactoryScopedContext.getScriptEvaluatorFactory().clear(); - valueExtractorManager.clear(); + constraintCreationContext.getValueExtractorManager().clear(); } public ValidatorFactoryScopedContext getValidatorFactoryScopedContext() { @@ -306,21 +293,18 @@ public ValidatorFactoryScopedContext getValidatorFactoryScopedContext() { } Validator createValidator(ConstraintValidatorFactory constraintValidatorFactory, - ValueExtractorManager valueExtractorManager, + ConstraintCreationContext constraintCreationContext, ValidatorFactoryScopedContext validatorFactoryScopedContext, MethodValidationConfiguration methodValidationConfiguration) { - BeanMetaDataManager beanMetaDataManager = beanMetaDataManagers.computeIfAbsent( - new BeanMetaDataManagerKey( validatorFactoryScopedContext.getParameterNameProvider(), valueExtractorManager, methodValidationConfiguration ), + new BeanMetaDataManagerKey( validatorFactoryScopedContext.getParameterNameProvider(), constraintCreationContext.getValueExtractorManager(), methodValidationConfiguration ), key -> new BeanMetaDataManagerImpl( - constraintHelper, + constraintCreationContext, executableHelper, - typeResolutionHelper, validatorFactoryScopedContext.getParameterNameProvider(), - valueExtractorManager, javaBeanHelper, validationOrderGenerator, - buildDataProviders(), + buildMetaDataProviders(), methodValidationConfiguration ) ); @@ -328,14 +312,14 @@ Validator createValidator(ConstraintValidatorFactory constraintValidatorFactory, return new ValidatorImpl( constraintValidatorFactory, beanMetaDataManager, - valueExtractorManager, - constraintValidatorManager, + constraintCreationContext.getValueExtractorManager(), + constraintCreationContext.getConstraintValidatorManager(), validationOrderGenerator, validatorFactoryScopedContext ); } - private List buildDataProviders() { + private List buildMetaDataProviders() { List metaDataProviders = newArrayList(); if ( xmlMetaDataProvider != null ) { metaDataProviders.add( xmlMetaDataProvider ); @@ -344,9 +328,7 @@ private List buildDataProviders() { if ( !constraintMappings.isEmpty() ) { metaDataProviders.add( new ProgrammaticMetaDataProvider( - constraintHelper, - typeResolutionHelper, - valueExtractorManager, + constraintCreationContext, constraintMappings ) ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java index 260c1ba6e0..1b6876ee02 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java @@ -15,17 +15,14 @@ import java.util.EnumSet; import java.util.List; -import javax.validation.valueextraction.ValueExtractor; - +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.engine.MethodValidationConfiguration; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; -import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataBuilder; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; @@ -35,7 +32,6 @@ import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper; import org.hibernate.validator.internal.util.stereotypes.Immutable; @@ -80,19 +76,9 @@ public class BeanMetaDataManagerImpl implements BeanMetaDataManager { private final List metaDataProviders; /** - * Helper for builtin constraints and their validator implementations - */ - private final ConstraintHelper constraintHelper; - - /** - * Used for resolving generic type information. - */ - private final TypeResolutionHelper typeResolutionHelper; - - /** - * The {@link ValueExtractor} manager. + * The constraint creation context containing all the helpers necessary to the constraint creation. */ - private final ValueExtractorManager valueExtractorManager; + private final ConstraintCreationContext constraintCreationContext; private final ExecutableParameterNameProvider parameterNameProvider; @@ -115,19 +101,15 @@ public class BeanMetaDataManagerImpl implements BeanMetaDataManager { */ private final MethodValidationConfiguration methodValidationConfiguration; - public BeanMetaDataManagerImpl(ConstraintHelper constraintHelper, + public BeanMetaDataManagerImpl(ConstraintCreationContext constraintCreationContext, ExecutableHelper executableHelper, - TypeResolutionHelper typeResolutionHelper, ExecutableParameterNameProvider parameterNameProvider, - ValueExtractorManager valueExtractorManager, JavaBeanHelper javaBeanHelper, ValidationOrderGenerator validationOrderGenerator, List optionalMetaDataProviders, MethodValidationConfiguration methodValidationConfiguration) { - this.constraintHelper = constraintHelper; + this.constraintCreationContext = constraintCreationContext; this.executableHelper = executableHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; this.parameterNameProvider = parameterNameProvider; this.validationOrderGenerator = validationOrderGenerator; @@ -144,9 +126,7 @@ public BeanMetaDataManagerImpl(ConstraintHelper constraintHelper, AnnotationProcessingOptions annotationProcessingOptions = getAnnotationProcessingOptionsFromNonDefaultProviders( optionalMetaDataProviders ); AnnotationMetaDataProvider defaultProvider = new AnnotationMetaDataProvider( - constraintHelper, - typeResolutionHelper, - valueExtractorManager, + constraintCreationContext, javaBeanHelper, annotationProcessingOptions ); @@ -192,7 +172,8 @@ public int numberOfCachedBeanMetaDataInstances() { */ private BeanMetaDataImpl createBeanMetaData(Class clazz) { BeanMetaDataBuilder builder = BeanMetaDataBuilder.getInstance( - constraintHelper, executableHelper, typeResolutionHelper, valueExtractorManager, parameterNameProvider, validationOrderGenerator, clazz, methodValidationConfiguration ); + constraintCreationContext, executableHelper, parameterNameProvider, + validationOrderGenerator, clazz, methodValidationConfiguration ); for ( MetaDataProvider provider : metaDataProviders ) { for ( BeanConfiguration beanConfiguration : getBeanConfigurationForHierarchy( provider, clazz ) ) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java index e88b81d183..319951ff28 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java @@ -14,15 +14,14 @@ import java.util.Map; import java.util.Set; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.engine.MethodValidationConfiguration; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataBuilder; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; @@ -30,7 +29,6 @@ import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper; public class PredefinedScopeBeanMetaDataManager implements BeanMetaDataManager { @@ -40,11 +38,9 @@ public class PredefinedScopeBeanMetaDataManager implements BeanMetaDataManager { */ private final Map> beanMetaDataMap; - public PredefinedScopeBeanMetaDataManager(ConstraintHelper constraintHelper, + public PredefinedScopeBeanMetaDataManager(ConstraintCreationContext constraintCreationContext, ExecutableHelper executableHelper, - TypeResolutionHelper typeResolutionHelper, ExecutableParameterNameProvider parameterNameProvider, - ValueExtractorManager valueExtractorManager, JavaBeanHelper javaBeanHelper, ValidationOrderGenerator validationOrderGenerator, List optionalMetaDataProviders, @@ -52,9 +48,7 @@ public PredefinedScopeBeanMetaDataManager(ConstraintHelper constraintHelper, Set> beanClassesToInitialize) { AnnotationProcessingOptions annotationProcessingOptions = getAnnotationProcessingOptionsFromNonDefaultProviders( optionalMetaDataProviders ); AnnotationMetaDataProvider defaultProvider = new AnnotationMetaDataProvider( - constraintHelper, - typeResolutionHelper, - valueExtractorManager, + constraintCreationContext, javaBeanHelper, annotationProcessingOptions ); @@ -70,7 +64,7 @@ public PredefinedScopeBeanMetaDataManager(ConstraintHelper constraintHelper, Map> tmpBeanMetadataMap = new HashMap<>(); for ( Class validatedClass : beanClassesToInitialize ) { - BeanMetaData beanMetaData = createBeanMetaData( constraintHelper, executableHelper, typeResolutionHelper, parameterNameProvider, valueExtractorManager, + BeanMetaData beanMetaData = createBeanMetaData( constraintCreationContext, executableHelper, parameterNameProvider, javaBeanHelper, validationOrderGenerator, optionalMetaDataProviders, methodValidationConfiguration, metaDataProviders, validatedClass ); @@ -78,7 +72,7 @@ public PredefinedScopeBeanMetaDataManager(ConstraintHelper constraintHelper, for ( Class parentClass : beanMetaData.getClassHierarchy() ) { tmpBeanMetadataMap.put( parentClass.getName(), - createBeanMetaData( constraintHelper, executableHelper, typeResolutionHelper, parameterNameProvider, valueExtractorManager, + createBeanMetaData( constraintCreationContext, executableHelper, parameterNameProvider, javaBeanHelper, validationOrderGenerator, optionalMetaDataProviders, methodValidationConfiguration, metaDataProviders, parentClass ) ); } @@ -107,11 +101,9 @@ public void clear() { * * @return A bean meta data object for the given type. */ - private static BeanMetaDataImpl createBeanMetaData(ConstraintHelper constraintHelper, + private static BeanMetaDataImpl createBeanMetaData(ConstraintCreationContext constraintCreationContext, ExecutableHelper executableHelper, - TypeResolutionHelper typeResolutionHelper, ExecutableParameterNameProvider parameterNameProvider, - ValueExtractorManager valueExtractorManager, JavaBeanHelper javaBeanHelper, ValidationOrderGenerator validationOrderGenerator, List optionalMetaDataProviders, @@ -119,7 +111,8 @@ private static BeanMetaDataImpl createBeanMetaData(ConstraintHelper const List metaDataProviders, Class clazz) { BeanMetaDataBuilder builder = BeanMetaDataBuilder.getInstance( - constraintHelper, executableHelper, typeResolutionHelper, valueExtractorManager, parameterNameProvider, validationOrderGenerator, clazz, methodValidationConfiguration ); + constraintCreationContext, executableHelper, parameterNameProvider, + validationOrderGenerator, clazz, methodValidationConfiguration ); for ( MetaDataProvider provider : metaDataProviders ) { for ( BeanConfiguration beanConfiguration : getBeanConfigurationForHierarchy( provider, clazz ) ) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataBuilder.java index 765fdfe681..4f266dfa27 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/BeanMetaDataBuilder.java @@ -11,10 +11,9 @@ import java.util.List; import java.util.Set; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.engine.MethodValidationConfiguration; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; @@ -25,7 +24,6 @@ import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.StringHelper; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.spi.group.DefaultGroupSequenceProvider; /** @@ -38,13 +36,11 @@ */ public class BeanMetaDataBuilder { - private final ConstraintHelper constraintHelper; + private final ConstraintCreationContext constraintCreationContext; private final ValidationOrderGenerator validationOrderGenerator; private final Class beanClass; private final Set builders = newHashSet(); private final ExecutableHelper executableHelper; - private final TypeResolutionHelper typeResolutionHelper; - private final ValueExtractorManager valueExtractorManager; private final ExecutableParameterNameProvider parameterNameProvider; private final MethodValidationConfiguration methodValidationConfiguration; @@ -55,38 +51,30 @@ public class BeanMetaDataBuilder { private BeanMetaDataBuilder( - ConstraintHelper constraintHelper, + ConstraintCreationContext constraintCreationContext, ExecutableHelper executableHelper, - TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager, ExecutableParameterNameProvider parameterNameProvider, ValidationOrderGenerator validationOrderGenerator, Class beanClass, MethodValidationConfiguration methodValidationConfiguration) { this.beanClass = beanClass; - this.constraintHelper = constraintHelper; + this.constraintCreationContext = constraintCreationContext; this.validationOrderGenerator = validationOrderGenerator; this.executableHelper = executableHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; this.parameterNameProvider = parameterNameProvider; this.methodValidationConfiguration = methodValidationConfiguration; } public static BeanMetaDataBuilder getInstance( - ConstraintHelper constraintHelper, + ConstraintCreationContext constraintCreationContext, ExecutableHelper executableHelper, - TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager, ExecutableParameterNameProvider parameterNameProvider, ValidationOrderGenerator validationOrderGenerator, Class beanClass, MethodValidationConfiguration methodValidationConfiguration) { return new BeanMetaDataBuilder<>( - constraintHelper, + constraintCreationContext, executableHelper, - typeResolutionHelper, - valueExtractorManager, parameterNameProvider, validationOrderGenerator, beanClass, @@ -130,10 +118,8 @@ private void addMetaDataToBuilder(ConstrainedElement constrainableElement, Set build() { private static class BuilderDelegate { private final Class beanClass; private final ConstrainedElement constrainedElement; - private final ConstraintHelper constraintHelper; + private final ConstraintCreationContext constraintCreationContext; private final ExecutableHelper executableHelper; - private final TypeResolutionHelper typeResolutionHelper; - private final ValueExtractorManager valueExtractorManager; private final ExecutableParameterNameProvider parameterNameProvider; private MetaDataBuilder metaDataBuilder; private ExecutableMetaData.Builder methodBuilder; @@ -172,19 +156,15 @@ private static class BuilderDelegate { public BuilderDelegate( Class beanClass, ConstrainedElement constrainedElement, - ConstraintHelper constraintHelper, + ConstraintCreationContext constraintCreationContext, ExecutableHelper executableHelper, - TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager, ExecutableParameterNameProvider parameterNameProvider, MethodValidationConfiguration methodValidationConfiguration ) { this.beanClass = beanClass; this.constrainedElement = constrainedElement; - this.constraintHelper = constraintHelper; + this.constraintCreationContext = constraintCreationContext; this.executableHelper = executableHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; this.parameterNameProvider = parameterNameProvider; this.methodValidationConfiguration = methodValidationConfiguration; @@ -194,9 +174,7 @@ public BuilderDelegate( metaDataBuilder = new PropertyMetaData.Builder( beanClass, constrainedField, - constraintHelper, - typeResolutionHelper, - valueExtractorManager + constraintCreationContext ); break; case CONSTRUCTOR: @@ -211,10 +189,8 @@ public BuilderDelegate( methodBuilder = new ExecutableMetaData.Builder( beanClass, constrainedExecutable, - constraintHelper, + constraintCreationContext, executableHelper, - typeResolutionHelper, - valueExtractorManager, parameterNameProvider, methodValidationConfiguration ); @@ -224,9 +200,7 @@ public BuilderDelegate( metaDataBuilder = new PropertyMetaData.Builder( beanClass, constrainedExecutable, - constraintHelper, - typeResolutionHelper, - valueExtractorManager + constraintCreationContext ); } break; @@ -235,9 +209,7 @@ public BuilderDelegate( metaDataBuilder = new ClassMetaData.Builder( beanClass, constrainedType, - constraintHelper, - typeResolutionHelper, - valueExtractorManager + constraintCreationContext ); break; default: @@ -264,10 +236,8 @@ public boolean add(ConstrainedElement constrainedElement) { methodBuilder = new ExecutableMetaData.Builder( beanClass, constrainedMethod, - constraintHelper, + constraintCreationContext, executableHelper, - typeResolutionHelper, - valueExtractorManager, parameterNameProvider, methodValidationConfiguration ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ClassMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ClassMetaData.java index 1c69196f2c..a9174ad4f1 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ClassMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ClassMetaData.java @@ -11,13 +11,11 @@ import javax.validation.ElementKind; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.descriptor.ClassDescriptorImpl; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedType; -import org.hibernate.validator.internal.util.TypeResolutionHelper; /** * Represents the constraint related meta data for a type i.e. class-level @@ -86,9 +84,8 @@ public boolean equals(Object obj) { } public static class Builder extends MetaDataBuilder { - public Builder(Class beanClass, ConstrainedType constrainedType, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager) { - super( beanClass, constraintHelper, typeResolutionHelper, valueExtractorManager ); + public Builder(Class beanClass, ConstrainedType constrainedType, ConstraintCreationContext constraintCreationContext) { + super( beanClass, constraintCreationContext ); add( constrainedType ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java index 6c8ab7705f..be8979bc73 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ExecutableMetaData.java @@ -21,10 +21,9 @@ import javax.validation.ElementKind; import javax.validation.metadata.ParameterDescriptor; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.engine.MethodValidationConfiguration; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.aggregated.rule.MethodConfigurationRule; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.descriptor.ExecutableDescriptorImpl; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; @@ -35,7 +34,6 @@ import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.stereotypes.Immutable; /** @@ -279,13 +277,11 @@ public static class Builder extends MetaDataBuilder { public Builder( Class beanClass, ConstrainedExecutable constrainedExecutable, - ConstraintHelper constraintHelper, + ConstraintCreationContext constraintCreationContext, ExecutableHelper executableHelper, - TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager, ExecutableParameterNameProvider parameterNameProvider, MethodValidationConfiguration methodValidationConfiguration) { - super( beanClass, constraintHelper, typeResolutionHelper, valueExtractorManager ); + super( beanClass, constraintCreationContext ); this.executableHelper = executableHelper; this.parameterNameProvider = parameterNameProvider; @@ -393,7 +389,7 @@ public ExecutableMetaData build() { adaptOriginsAndImplicitGroups( getContainerElementConstraints() ), findParameterMetaData(), adaptOriginsAndImplicitGroups( crossParameterConstraints ), - cascadingMetaDataBuilder.build( valueExtractorManager, callable ), + cascadingMetaDataBuilder.build( constraintCreationContext.getValueExtractorManager(), callable ), isConstrained, kind == ConstrainedElementKind.GETTER ); @@ -418,9 +414,7 @@ private List findParameterMetaData() { new ParameterMetaData.Builder( callable.getDeclaringClass(), oneParameter, - constraintHelper, - typeResolutionHelper, - valueExtractorManager, + constraintCreationContext, parameterNameProvider ) ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/MetaDataBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/MetaDataBuilder.java index cecf054f94..3a094ca28b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/MetaDataBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/MetaDataBuilder.java @@ -11,14 +11,12 @@ import java.lang.annotation.Annotation; import java.util.Set; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.core.ConstraintOrigin; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.core.MetaConstraints; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; -import org.hibernate.validator.internal.util.TypeResolutionHelper; /** * Builds {@link ConstraintMetaData} instances for the @@ -29,20 +27,16 @@ */ public abstract class MetaDataBuilder { - protected final ConstraintHelper constraintHelper; - protected final TypeResolutionHelper typeResolutionHelper; - protected final ValueExtractorManager valueExtractorManager; + protected final ConstraintCreationContext constraintCreationContext; private final Class beanClass; private final Set> directConstraints = newHashSet(); private final Set> containerElementsConstraints = newHashSet(); private boolean isCascading = false; - protected MetaDataBuilder(Class beanClass, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { + protected MetaDataBuilder(Class beanClass, ConstraintCreationContext constraintCreationContext) { this.beanClass = beanClass; - this.constraintHelper = constraintHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; + this.constraintCreationContext = constraintCreationContext; } /** @@ -128,7 +122,7 @@ private MetaConstraint adaptOriginAndImplicitGroup(Met Class constraintClass = constraint.getLocation().getDeclaringClass(); ConstraintDescriptorImpl descriptor = new ConstraintDescriptorImpl<>( - constraintHelper, + constraintCreationContext.getConstraintHelper(), constraint.getLocation().getConstrainable(), constraint.getDescriptor().getAnnotationDescriptor(), constraint.getConstraintLocationKind(), @@ -137,7 +131,9 @@ private MetaConstraint adaptOriginAndImplicitGroup(Met constraint.getDescriptor().getConstraintType() ); - return MetaConstraints.create( typeResolutionHelper, valueExtractorManager, descriptor, constraint.getLocation() ); + return MetaConstraints.create( constraintCreationContext.getTypeResolutionHelper(), + constraintCreationContext.getValueExtractorManager(), + constraintCreationContext.getConstraintValidatorManager(), descriptor, constraint.getLocation() ); } /** diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ParameterMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ParameterMetaData.java index 839d12f812..fadcceb751 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ParameterMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/ParameterMetaData.java @@ -13,9 +13,8 @@ import javax.validation.ElementKind; import javax.validation.metadata.ParameterDescriptor; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.engine.path.PathImpl; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.descriptor.ParameterDescriptorImpl; import org.hibernate.validator.internal.metadata.facets.Cascadable; @@ -25,7 +24,6 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; -import org.hibernate.validator.internal.util.TypeResolutionHelper; /** * An aggregated view of the constraint related meta data for a single method @@ -117,11 +115,9 @@ public static class Builder extends MetaDataBuilder { public Builder(Class beanClass, ConstrainedParameter constrainedParameter, - ConstraintHelper constraintHelper, - TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager, + ConstraintCreationContext constraintCreationContext, ExecutableParameterNameProvider parameterNameProvider) { - super( beanClass, constraintHelper, typeResolutionHelper, valueExtractorManager ); + super( beanClass, constraintCreationContext ); this.parameterNameProvider = parameterNameProvider; this.parameterType = constrainedParameter.getType(); @@ -170,7 +166,7 @@ public ParameterMetaData build() { parameterType, adaptOriginsAndImplicitGroups( getDirectConstraints() ), adaptOriginsAndImplicitGroups( getContainerElementConstraints() ), - cascadingMetaDataBuilder.build( valueExtractorManager, callableForNameRetrieval ) + cascadingMetaDataBuilder.build( constraintCreationContext.getValueExtractorManager(), callableForNameRetrieval ) ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java index fffa02635a..c5cb0683f2 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java @@ -21,8 +21,7 @@ import javax.validation.ElementKind; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.core.MetaConstraints; import org.hibernate.validator.internal.metadata.descriptor.PropertyDescriptorImpl; @@ -38,7 +37,6 @@ import org.hibernate.validator.internal.properties.Property; import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; import org.hibernate.validator.internal.util.CollectionHelper; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.util.stereotypes.Immutable; @@ -157,18 +155,16 @@ public static class Builder extends MetaDataBuilder { private final Map cascadableBuilders = new HashMap<>(); private final Type propertyType; - public Builder(Class beanClass, ConstrainedField constrainedProperty, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager) { - super( beanClass, constraintHelper, typeResolutionHelper, valueExtractorManager ); + public Builder(Class beanClass, ConstrainedField constrainedProperty, ConstraintCreationContext constraintCreationContext) { + super( beanClass, constraintCreationContext ); this.propertyName = constrainedProperty.getField().getName(); this.propertyType = constrainedProperty.getField().getType(); add( constrainedProperty ); } - public Builder(Class beanClass, ConstrainedExecutable constrainedMethod, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager) { - super( beanClass, constraintHelper, typeResolutionHelper, valueExtractorManager ); + public Builder(Class beanClass, ConstrainedExecutable constrainedMethod, ConstraintCreationContext constraintCreationContext) { + super( beanClass, constraintCreationContext ); this.propertyName = constrainedMethod.getCallable().as( Property.class ).getPropertyName(); this.propertyType = constrainedMethod.getCallable().getType(); @@ -195,7 +191,8 @@ public final void add(ConstrainedElement constrainedElement) { Cascadable.Builder builder = cascadableBuilders.get( property ); if ( builder == null ) { - builder = AbstractPropertyCascadable.AbstractBuilder.builder( valueExtractorManager, property, + builder = AbstractPropertyCascadable.AbstractBuilder.builder( + constraintCreationContext.getValueExtractorManager(), property, constrainedElement.getCascadingMetaDataBuilder() ); cascadableBuilders.put( property, builder ); } @@ -291,7 +288,9 @@ private MetaConstraint withGetterLocation(ConstraintLocation getterConstraint } } - return MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraint.getDescriptor(), converted ); + return MetaConstraints.create( constraintCreationContext.getTypeResolutionHelper(), + constraintCreationContext.getValueExtractorManager(), + constraintCreationContext.getConstraintValidatorManager(), constraint.getDescriptor(), converted ); } private String getPropertyName(ConstrainedElement constrainedElement) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java index de3a33005a..7d5e23e560 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java @@ -17,6 +17,7 @@ import org.hibernate.validator.internal.engine.ValueContext; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; import org.hibernate.validator.internal.engine.validationcontext.ValidationContext; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorDescriptor; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorHelper; @@ -67,7 +68,8 @@ public class MetaConstraint { * @param valueExtractorDescriptors the potential {@link ValueExtractor}s used to extract the value to validate * @param validatedValueType the type of the validated element */ - MetaConstraint(ConstraintDescriptorImpl constraintDescriptor, ConstraintLocation location, List valueExtractionPath, + MetaConstraint(ConstraintValidatorManager constraintValidatorManager, ConstraintDescriptorImpl constraintDescriptor, + ConstraintLocation location, List valueExtractionPath, Type validatedValueType) { this.constraintTree = ConstraintTree.of( constraintDescriptor, validatedValueType ); this.location = location; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraints.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraints.java index ced135aa74..50a9893d11 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraints.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraints.java @@ -20,6 +20,7 @@ import javax.validation.metadata.ValidateUnwrappedValue; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorDescriptor; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorHelper; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; @@ -49,6 +50,7 @@ private MetaConstraints() { } public static MetaConstraint create(TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + ConstraintValidatorManager constraintValidatorManager, ConstraintDescriptorImpl constraintDescriptor, ConstraintLocation location) { List valueExtractionPath = new ArrayList<>(); @@ -69,7 +71,7 @@ public static MetaConstraint create(TypeResolutionHelp Collections.reverse( valueExtractionPath ); - return new MetaConstraint<>( constraintDescriptor, location, valueExtractionPath, typeOfValidatedElement ); + return new MetaConstraint<>( constraintValidatorManager, constraintDescriptor, location, valueExtractionPath, typeOfValidatedElement ); } private static Type addValueExtractorDescriptorForWrappedValue(TypeResolutionHelper typeResolutionHelper, diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java index 0f68ebf22c..7d5c3b4ffb 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java @@ -39,12 +39,11 @@ import javax.validation.groups.ConvertGroup; import org.hibernate.validator.group.GroupSequenceProvider; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.engine.valueextraction.ArrayElement; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.core.MetaConstraints; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; @@ -69,7 +68,6 @@ import org.hibernate.validator.internal.properties.javabean.JavaBeanParameter; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.ReflectionHelper; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -91,22 +89,16 @@ public class AnnotationMetaDataProvider implements MetaDataProvider { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - private final ConstraintHelper constraintHelper; - private final TypeResolutionHelper typeResolutionHelper; + private final ConstraintCreationContext constraintCreationContext; private final AnnotationProcessingOptions annotationProcessingOptions; - private final ValueExtractorManager valueExtractorManager; private final JavaBeanHelper javaBeanHelper; private final BeanConfiguration objectBeanConfiguration; - public AnnotationMetaDataProvider(ConstraintHelper constraintHelper, - TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager, + public AnnotationMetaDataProvider(ConstraintCreationContext constraintCreationContext, JavaBeanHelper javaBeanHelper, AnnotationProcessingOptions annotationProcessingOptions) { - this.constraintHelper = constraintHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; + this.constraintCreationContext = constraintCreationContext; this.javaBeanHelper = javaBeanHelper; this.annotationProcessingOptions = annotationProcessingOptions; @@ -209,7 +201,11 @@ private Set> getClassLevelConstraints(Class clazz) { ConstraintLocation location = ConstraintLocation.forClass( clazz ); for ( ConstraintDescriptorImpl constraintDescriptor : classLevelConstraintDescriptors ) { - classLevelConstraints.add( MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor, location ) ); + classLevelConstraints.add( MetaConstraints.create( constraintCreationContext.getTypeResolutionHelper(), + constraintCreationContext.getValueExtractorManager(), + constraintCreationContext.getConstraintValidatorManager(), + constraintDescriptor, + location ) ); } return classLevelConstraints; @@ -263,7 +259,10 @@ private Set> convertToMetaConstraints(List constraintDescription : constraintDescriptors ) { - constraints.add( MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescription, location ) ); + constraints.add( MetaConstraints.create( constraintCreationContext.getTypeResolutionHelper(), + constraintCreationContext.getValueExtractorManager(), + constraintCreationContext.getConstraintValidatorManager(), + constraintDescription, location ) ); } return constraints; } @@ -364,8 +363,12 @@ private Set> convertToMetaConstraints(List constraintDescriptor : constraintDescriptors ) { - ConstraintLocation location = constraintDescriptor.getConstraintType() == ConstraintType.GENERIC ? returnValueLocation : crossParameterLocation; - constraints.add( MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor, location ) ); + ConstraintLocation location = constraintDescriptor.getConstraintType() == ConstraintType.GENERIC + ? returnValueLocation + : crossParameterLocation; + constraints.add( MetaConstraints.create( constraintCreationContext.getTypeResolutionHelper(), + constraintCreationContext.getValueExtractorManager(), + constraintCreationContext.getConstraintValidatorManager(), constraintDescriptor, location ) ); } return constraints; @@ -415,8 +418,10 @@ private List getParameterMetaData(JavaBeanExecutable ja for ( ConstraintDescriptorImpl constraintDescriptorImpl : constraintDescriptors ) { parameterConstraints.add( - MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptorImpl, location ) - ); + MetaConstraints.create( constraintCreationContext.getTypeResolutionHelper(), + constraintCreationContext.getValueExtractorManager(), + constraintCreationContext.getConstraintValidatorManager(), constraintDescriptorImpl, + location ) ); } } else { @@ -520,17 +525,17 @@ protected List> findConstrain // HV-1049 and HV-1311 - Ignore annotations from the JDK (jdk.internal.* and java.*); They cannot be constraint // annotations so skip them right here, as for the proper check we'd need package access permission for // "jdk.internal" and "java". - if ( constraintHelper.isJdkAnnotation( annotation.annotationType() ) ) { + if ( constraintCreationContext.getConstraintHelper().isJdkAnnotation( annotation.annotationType() ) ) { return Collections.emptyList(); } List constraints = newArrayList(); Class annotationType = annotation.annotationType(); - if ( constraintHelper.isConstraintAnnotation( annotationType ) ) { + if ( constraintCreationContext.getConstraintHelper().isConstraintAnnotation( annotationType ) ) { constraints.add( annotation ); } - else if ( constraintHelper.isMultiValueConstraint( annotationType ) ) { - constraints.addAll( constraintHelper.getConstraintsFromMultiValueConstraint( annotation ) ); + else if ( constraintCreationContext.getConstraintHelper().isMultiValueConstraint( annotationType ) ) { + constraints.addAll( constraintCreationContext.getConstraintHelper().getConstraintsFromMultiValueConstraint( annotation ) ); } return constraints.stream() @@ -575,7 +580,7 @@ private ConstraintDescriptorImpl buildConstraintDescri A annotation, ConstraintLocationKind type) { return new ConstraintDescriptorImpl<>( - constraintHelper, + constraintCreationContext.getConstraintHelper(), constrainable, new ConstraintAnnotationDescriptor<>( annotation ), type @@ -793,7 +798,10 @@ private Set> findTypeUseConstraints(Constrainable constrainabl ConstraintLocation constraintLocation = ConstraintLocation.forTypeArgument( location.toConstraintLocation(), typeVariable, type ); for ( ConstraintDescriptorImpl constraintDescriptor : constraintDescriptors ) { - constraints.add( MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor, constraintLocation ) ); + constraints.add( MetaConstraints.create( constraintCreationContext.getTypeResolutionHelper(), + constraintCreationContext.getValueExtractorManager(), + constraintCreationContext.getConstraintValidatorManager(), constraintDescriptor, + constraintLocation ) ); } return constraints; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/ProgrammaticMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/ProgrammaticMetaDataProvider.java index f9f293de31..6a98e446ea 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/ProgrammaticMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/ProgrammaticMetaDataProvider.java @@ -14,14 +14,12 @@ import java.util.Set; import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.Contracts; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.util.stereotypes.Immutable; @@ -40,14 +38,12 @@ public class ProgrammaticMetaDataProvider implements MetaDataProvider { private final Map> configuredBeans; private final AnnotationProcessingOptions annotationProcessingOptions; - public ProgrammaticMetaDataProvider(ConstraintHelper constraintHelper, - TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager, + public ProgrammaticMetaDataProvider(ConstraintCreationContext constraintCreationContext, Set constraintMappings) { Contracts.assertNotNull( constraintMappings ); configuredBeans = CollectionHelper.toImmutableMap( - createBeanConfigurations( constraintMappings, constraintHelper, typeResolutionHelper, valueExtractorManager ) + createBeanConfigurations( constraintMappings, constraintCreationContext ) ); assertUniquenessOfConfiguredTypes( constraintMappings ); @@ -68,12 +64,11 @@ private static void assertUniquenessOfConfiguredTypes(Set> createBeanConfigurations(Set mappings, ConstraintHelper constraintHelper, - TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager) { + private static Map> createBeanConfigurations(Set mappings, + ConstraintCreationContext constraintCreationContext) { final Map> configuredBeans = new HashMap<>(); for ( DefaultConstraintMapping mapping : mappings ) { - Set> beanConfigurations = mapping.getBeanConfigurations( constraintHelper, typeResolutionHelper, - valueExtractorManager ); + Set> beanConfigurations = mapping.getBeanConfigurations( constraintCreationContext ); for ( BeanConfiguration beanConfiguration : beanConfigurations ) { configuredBeans.put( beanConfiguration.getBeanClass().getName(), beanConfiguration ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlMetaDataProvider.java index 12f51ddb4e..51320ed3b5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlMetaDataProvider.java @@ -11,15 +11,13 @@ import java.util.Map; import java.util.Set; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.CollectionHelper; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.stereotypes.Immutable; import org.hibernate.validator.internal.xml.mapping.MappingXmlParser; @@ -38,14 +36,12 @@ public class XmlMetaDataProvider implements MetaDataProvider { private final AnnotationProcessingOptions annotationProcessingOptions; - public XmlMetaDataProvider(ConstraintHelper constraintHelper, - TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager, + public XmlMetaDataProvider(ConstraintCreationContext constraintCreationContext, JavaBeanHelper javaBeanHelper, Set mappingStreams, ClassLoader externalClassLoader) { - MappingXmlParser mappingParser = new MappingXmlParser( constraintHelper, typeResolutionHelper, valueExtractorManager, + MappingXmlParser mappingParser = new MappingXmlParser( constraintCreationContext, javaBeanHelper, externalClassLoader ); mappingParser.parse( mappingStreams ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractConstrainedElementStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractConstrainedElementStaxBuilder.java index 4791436852..c1b33da4f7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractConstrainedElementStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractConstrainedElementStaxBuilder.java @@ -18,12 +18,10 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.XMLEvent; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.xml.AbstractStaxBuilder; import org.hibernate.validator.internal.xml.mapping.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; @@ -37,9 +35,7 @@ abstract class AbstractConstrainedElementStaxBuilder extends AbstractStaxBuilder private static final QName IGNORE_ANNOTATIONS_QNAME = new QName( "ignore-annotations" ); protected final ClassLoadingHelper classLoadingHelper; - protected final ConstraintHelper constraintHelper; - protected final TypeResolutionHelper typeResolutionHelper; - protected final ValueExtractorManager valueExtractorManager; + protected final ConstraintCreationContext constraintCreationContext; protected final DefaultPackageStaxBuilder defaultPackageStaxBuilder; protected final AnnotationProcessingOptionsImpl annotationProcessingOptions; @@ -50,14 +46,11 @@ abstract class AbstractConstrainedElementStaxBuilder extends AbstractStaxBuilder protected final List constraintTypeStaxBuilders; protected final ContainerElementTypeConfigurationBuilder containerElementTypeConfigurationBuilder; - AbstractConstrainedElementStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, - TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + AbstractConstrainedElementStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintCreationContext constraintCreationContext, DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions) { this.classLoadingHelper = classLoadingHelper; this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; - this.constraintHelper = constraintHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; + this.constraintCreationContext = constraintCreationContext; this.groupConversionBuilder = new GroupConversionStaxBuilder( classLoadingHelper, defaultPackageStaxBuilder ); this.validStaxBuilder = new ValidStaxBuilder(); @@ -94,11 +87,13 @@ protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLS } private ConstraintTypeStaxBuilder getNewConstraintTypeStaxBuilder() { - return new ConstraintTypeStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder ); + return new ConstraintTypeStaxBuilder( classLoadingHelper, constraintCreationContext, + defaultPackageStaxBuilder ); } private ContainerElementTypeStaxBuilder getNewContainerElementTypeStaxBuilder() { - return new ContainerElementTypeStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder ); + return new ContainerElementTypeStaxBuilder( classLoadingHelper, constraintCreationContext, + defaultPackageStaxBuilder ); } protected ContainerElementTypeConfiguration getContainerElementTypeConfiguration(Type type, ConstraintLocation constraintLocation) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractConstrainedExecutableElementStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractConstrainedExecutableElementStaxBuilder.java index c466e28fec..91c87f4d6c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractConstrainedExecutableElementStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/AbstractConstrainedExecutableElementStaxBuilder.java @@ -15,10 +15,8 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.XMLEvent; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.xml.AbstractStaxBuilder; /** @@ -31,9 +29,7 @@ abstract class AbstractConstrainedExecutableElementStaxBuilder extends AbstractS private static final QName IGNORE_ANNOTATIONS_QNAME = new QName( "ignore-annotations" ); protected final ClassLoadingHelper classLoadingHelper; - protected final ConstraintHelper constraintHelper; - protected final TypeResolutionHelper typeResolutionHelper; - protected final ValueExtractorManager valueExtractorManager; + protected final ConstraintCreationContext constraintCreationContext; protected final DefaultPackageStaxBuilder defaultPackageStaxBuilder; protected final AnnotationProcessingOptionsImpl annotationProcessingOptions; @@ -44,14 +40,11 @@ abstract class AbstractConstrainedExecutableElementStaxBuilder extends AbstractS private ReturnValueStaxBuilder returnValueStaxBuilder; AbstractConstrainedExecutableElementStaxBuilder( - ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, - TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + ClassLoadingHelper classLoadingHelper, ConstraintCreationContext constraintCreationContext, DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions) { this.classLoadingHelper = classLoadingHelper; this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; - this.constraintHelper = constraintHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; + this.constraintCreationContext = constraintCreationContext; this.annotationProcessingOptions = annotationProcessingOptions; @@ -86,15 +79,18 @@ else if ( localCrossParameterStaxBuilder.process( xmlEventReader, xmlEvent ) ) { } private ConstrainedParameterStaxBuilder getNewConstrainedParameterStaxBuilder() { - return new ConstrainedParameterStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + return new ConstrainedParameterStaxBuilder( classLoadingHelper, constraintCreationContext, + defaultPackageStaxBuilder, annotationProcessingOptions ); } private CrossParameterStaxBuilder getNewCrossParameterStaxBuilder() { - return new CrossParameterStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + return new CrossParameterStaxBuilder( classLoadingHelper, constraintCreationContext, + defaultPackageStaxBuilder, annotationProcessingOptions ); } private ReturnValueStaxBuilder getNewReturnValueStaxBuilder() { - return new ReturnValueStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + return new ReturnValueStaxBuilder( classLoadingHelper, constraintCreationContext, + defaultPackageStaxBuilder, annotationProcessingOptions ); } public Optional getReturnValueStaxBuilder() { diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/BeanStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/BeanStaxBuilder.java index 475148542f..35b8cd20c8 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/BeanStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/BeanStaxBuilder.java @@ -23,14 +23,12 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.XMLEvent; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.properties.javabean.JavaBeanConstructor; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.properties.javabean.JavaBeanMethod; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.xml.AbstractStaxBuilder; @@ -49,9 +47,7 @@ class BeanStaxBuilder extends AbstractStaxBuilder { private static final String BEAN_QNAME_LOCAL_PART = "bean"; private final ClassLoadingHelper classLoadingHelper; - private final ConstraintHelper constraintHelper; - private final TypeResolutionHelper typeResolutionHelper; - private final ValueExtractorManager valueExtractorManager; + private final ConstraintCreationContext constraintCreationContext; private final DefaultPackageStaxBuilder defaultPackageStaxBuilder; private final AnnotationProcessingOptionsImpl annotationProcessingOptions; private final Map, List>> defaultSequences; @@ -64,15 +60,12 @@ class BeanStaxBuilder extends AbstractStaxBuilder { private final List constrainedMethodStaxBuilders; private final List constrainedConstructorStaxBuilders; - BeanStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, - TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + BeanStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintCreationContext constraintCreationContext, DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions, Map, List>> defaultSequences) { this.classLoadingHelper = classLoadingHelper; this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; - this.constraintHelper = constraintHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; + this.constraintCreationContext = constraintCreationContext; this.annotationProcessingOptions = annotationProcessingOptions; this.defaultSequences = defaultSequences; @@ -98,7 +91,7 @@ protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLS ConstrainedConstructorStaxBuilder constructorStaxBuilder = getNewConstrainedConstructorStaxBuilder(); ClassConstraintTypeStaxBuilder localClassConstraintTypeStaxBuilder = new ClassConstraintTypeStaxBuilder( - classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, + classLoadingHelper, constraintCreationContext, defaultPackageStaxBuilder, annotationProcessingOptions, defaultSequences ); while ( !( xmlEvent.isEndElement() && xmlEvent.asEndElement().getName().getLocalPart().equals( getAcceptableQName() ) ) ) { @@ -126,19 +119,23 @@ else if ( localClassConstraintTypeStaxBuilder.process( xmlEventReader, xmlEvent } private ConstrainedFieldStaxBuilder getNewConstrainedFieldStaxBuilder() { - return new ConstrainedFieldStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + return new ConstrainedFieldStaxBuilder( classLoadingHelper, constraintCreationContext, + defaultPackageStaxBuilder, annotationProcessingOptions ); } private ConstrainedGetterStaxBuilder getNewConstrainedGetterStaxBuilder() { - return new ConstrainedGetterStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + return new ConstrainedGetterStaxBuilder( classLoadingHelper, constraintCreationContext, + defaultPackageStaxBuilder, annotationProcessingOptions ); } private ConstrainedMethodStaxBuilder getNewConstrainedMethodStaxBuilder() { - return new ConstrainedMethodStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + return new ConstrainedMethodStaxBuilder( classLoadingHelper, constraintCreationContext, + defaultPackageStaxBuilder, annotationProcessingOptions ); } private ConstrainedConstructorStaxBuilder getNewConstrainedConstructorStaxBuilder() { - return new ConstrainedConstructorStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + return new ConstrainedConstructorStaxBuilder( classLoadingHelper, constraintCreationContext, + defaultPackageStaxBuilder, annotationProcessingOptions ); } void build(JavaBeanHelper javaBeanHelper, Set> processedClasses, Map, Set> constrainedElementsByType) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassConstraintTypeStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassConstraintTypeStaxBuilder.java index 1d059154eb..0a6907f039 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassConstraintTypeStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ClassConstraintTypeStaxBuilder.java @@ -19,15 +19,13 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.XMLEvent; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedType; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.xml.AbstractStaxBuilder; /** @@ -41,9 +39,7 @@ class ClassConstraintTypeStaxBuilder extends AbstractStaxBuilder { private static final QName IGNORE_ANNOTATIONS_QNAME = new QName( "ignore-annotations" ); private final ClassLoadingHelper classLoadingHelper; - private final ConstraintHelper constraintHelper; - private final TypeResolutionHelper typeResolutionHelper; - private final ValueExtractorManager valueExtractorManager; + private final ConstraintCreationContext constraintCreationContext; private final DefaultPackageStaxBuilder defaultPackageStaxBuilder; private final AnnotationProcessingOptionsImpl annotationProcessingOptions; private final Map, List>> defaultSequences; @@ -52,15 +48,12 @@ class ClassConstraintTypeStaxBuilder extends AbstractStaxBuilder { private final List constraintTypeStaxBuilders; private final GroupSequenceStaxBuilder groupSequenceStaxBuilder; - ClassConstraintTypeStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, - TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + ClassConstraintTypeStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintCreationContext constraintCreationContext, DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions, Map, List>> defaultSequences) { this.classLoadingHelper = classLoadingHelper; this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; - this.constraintHelper = constraintHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; + this.constraintCreationContext = constraintCreationContext; this.annotationProcessingOptions = annotationProcessingOptions; this.defaultSequences = defaultSequences; @@ -90,7 +83,8 @@ protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLS } private ConstraintTypeStaxBuilder getNewConstraintTypeStaxBuilder() { - return new ConstraintTypeStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder ); + return new ConstraintTypeStaxBuilder( classLoadingHelper, constraintCreationContext, + defaultPackageStaxBuilder ); } ConstrainedType build(Class beanClass) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java index d7f56ab36f..a65a246a3d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedConstructorStaxBuilder.java @@ -15,10 +15,9 @@ import javax.xml.namespace.QName; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; @@ -26,7 +25,6 @@ import org.hibernate.validator.internal.properties.javabean.JavaBeanConstructor; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.CollectionHelper; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -44,10 +42,9 @@ class ConstrainedConstructorStaxBuilder extends AbstractConstrainedExecutableEle private static final String METHOD_QNAME_LOCAL_PART = "constructor"; ConstrainedConstructorStaxBuilder( - ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager, DefaultPackageStaxBuilder defaultPackageStaxBuilder, - AnnotationProcessingOptionsImpl annotationProcessingOptions) { - super( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + ClassLoadingHelper classLoadingHelper, ConstraintCreationContext constraintCreationContext, + DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions) { + super( classLoadingHelper, constraintCreationContext, defaultPackageStaxBuilder, annotationProcessingOptions ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java index ded9e7b06d..0277d0d37d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedFieldStaxBuilder.java @@ -14,17 +14,15 @@ import javax.xml.namespace.QName; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; -import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.properties.javabean.JavaBeanField; -import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.xml.mapping.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; @@ -43,10 +41,9 @@ class ConstrainedFieldStaxBuilder extends AbstractConstrainedElementStaxBuilder private static final String FIELD_QNAME_LOCAL_PART = "field"; private static final QName NAME_QNAME = new QName( "name" ); - ConstrainedFieldStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, - TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + ConstrainedFieldStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintCreationContext constraintCreationContext, DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions) { - super( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + super( classLoadingHelper, constraintCreationContext, defaultPackageStaxBuilder, annotationProcessingOptions ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java index 617a1be254..df8dabaf6f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedGetterStaxBuilder.java @@ -15,18 +15,16 @@ import javax.xml.namespace.QName; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; -import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.properties.javabean.JavaBeanGetter; -import org.hibernate.validator.internal.util.TypeResolutionHelper; +import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.xml.mapping.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; @@ -45,10 +43,9 @@ class ConstrainedGetterStaxBuilder extends AbstractConstrainedElementStaxBuilder private static final String GETTER_QNAME_LOCAL_PART = "getter"; - ConstrainedGetterStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager, DefaultPackageStaxBuilder defaultPackageStaxBuilder, - AnnotationProcessingOptionsImpl annotationProcessingOptions) { - super( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + ConstrainedGetterStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintCreationContext constraintCreationContext, + DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions) { + super( classLoadingHelper, constraintCreationContext, defaultPackageStaxBuilder, annotationProcessingOptions ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java index 658ea6d07b..c6cafd1ebf 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedMethodStaxBuilder.java @@ -15,10 +15,9 @@ import javax.xml.namespace.QName; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; @@ -26,7 +25,6 @@ import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; import org.hibernate.validator.internal.properties.javabean.JavaBeanMethod; import org.hibernate.validator.internal.util.CollectionHelper; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -45,10 +43,9 @@ class ConstrainedMethodStaxBuilder extends AbstractConstrainedExecutableElementS private static final QName NAME_QNAME = new QName( "name" ); ConstrainedMethodStaxBuilder( - ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager, DefaultPackageStaxBuilder defaultPackageStaxBuilder, - AnnotationProcessingOptionsImpl annotationProcessingOptions) { - super( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + ClassLoadingHelper classLoadingHelper, ConstraintCreationContext constraintCreationContext, + DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions) { + super( classLoadingHelper, constraintCreationContext, defaultPackageStaxBuilder, annotationProcessingOptions ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java index 5cc0cb2f65..549ba144db 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstrainedParameterStaxBuilder.java @@ -15,16 +15,14 @@ import javax.validation.ValidationException; import javax.xml.namespace.QName; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.metadata.raw.ConfigurationSource; import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; import org.hibernate.validator.internal.properties.Callable; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.xml.mapping.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; @@ -43,10 +41,9 @@ class ConstrainedParameterStaxBuilder extends AbstractConstrainedElementStaxBuil private static final String PARAMETER_QNAME_LOCAL_PART = "parameter"; private static final QName TYPE_QNAME = new QName( "type" ); - ConstrainedParameterStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, - ValueExtractorManager valueExtractorManager, DefaultPackageStaxBuilder defaultPackageStaxBuilder, - AnnotationProcessingOptionsImpl annotationProcessingOptions) { - super( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + ConstrainedParameterStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintCreationContext constraintCreationContext, + DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions) { + super( classLoadingHelper, constraintCreationContext, defaultPackageStaxBuilder, annotationProcessingOptions ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintMappingsStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintMappingsStaxBuilder.java index f97862513c..5717243a0c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintMappingsStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintMappingsStaxBuilder.java @@ -15,12 +15,10 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.XMLEvent; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.xml.AbstractStaxBuilder; /** @@ -34,9 +32,7 @@ class ConstraintMappingsStaxBuilder extends AbstractStaxBuilder { private static final String CONSTRAINT_MAPPINGS_QNAME = "constraint-mappings"; private final ClassLoadingHelper classLoadingHelper; - private final ConstraintHelper constraintHelper; - private final TypeResolutionHelper typeResolutionHelper; - private final ValueExtractorManager valueExtractorManager; + private final ConstraintCreationContext constraintCreationContext; private final AnnotationProcessingOptionsImpl annotationProcessingOptions; private final JavaBeanHelper javaBeanHelper; private final Map, List>> defaultSequences; @@ -45,12 +41,10 @@ class ConstraintMappingsStaxBuilder extends AbstractStaxBuilder { private final List beanStaxBuilders; private final List constraintDefinitionStaxBuilders; - public ConstraintMappingsStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + public ConstraintMappingsStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintCreationContext constraintCreationContext, AnnotationProcessingOptionsImpl annotationProcessingOptions, JavaBeanHelper javaBeanHelper, Map, List>> defaultSequences) { this.classLoadingHelper = classLoadingHelper; - this.constraintHelper = constraintHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; + this.constraintCreationContext = constraintCreationContext; this.annotationProcessingOptions = annotationProcessingOptions; this.javaBeanHelper = javaBeanHelper; this.defaultSequences = defaultSequences; @@ -85,11 +79,12 @@ else if ( constraintDefinitionStaxBuilder.process( xmlEventReader, xmlEvent ) ) } private BeanStaxBuilder getNewBeanStaxBuilder() { - return new BeanStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions, defaultSequences ); + return new BeanStaxBuilder( classLoadingHelper, constraintCreationContext, + defaultPackageStaxBuilder, annotationProcessingOptions, defaultSequences ); } private ConstraintDefinitionStaxBuilder getNewConstraintDefinitionStaxBuilder() { - return new ConstraintDefinitionStaxBuilder( classLoadingHelper, constraintHelper, defaultPackageStaxBuilder ); + return new ConstraintDefinitionStaxBuilder( classLoadingHelper, constraintCreationContext.getConstraintHelper(), defaultPackageStaxBuilder ); } public void build(Set> processedClasses, Map, Set> constrainedElementsByType, Set alreadyProcessedConstraintDefinitions) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintTypeStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintTypeStaxBuilder.java index 10557668cb..183645419b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintTypeStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ConstraintTypeStaxBuilder.java @@ -29,14 +29,13 @@ import javax.xml.stream.events.StartElement; import javax.xml.stream.events.XMLEvent; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.core.MetaConstraints; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.annotation.AnnotationDescriptor; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.internal.util.logging.Log; @@ -61,9 +60,7 @@ class ConstraintTypeStaxBuilder extends AbstractStaxBuilder { private static final QName CONSTRAINT_ANNOTATION_QNAME = new QName( "annotation" ); private final ClassLoadingHelper classLoadingHelper; - private final ConstraintHelper constraintHelper; - private final TypeResolutionHelper typeResolutionHelper; - private final ValueExtractorManager valueExtractorManager; + private final ConstraintCreationContext constraintCreationContext; private final DefaultPackageStaxBuilder defaultPackageStaxBuilder; // Builders: @@ -77,14 +74,11 @@ class ConstraintTypeStaxBuilder extends AbstractStaxBuilder { private String constraintAnnotation; ConstraintTypeStaxBuilder( - ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, - TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + ClassLoadingHelper classLoadingHelper, ConstraintCreationContext constraintCreationContext, DefaultPackageStaxBuilder defaultPackageStaxBuilder) { this.classLoadingHelper = classLoadingHelper; this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; - this.constraintHelper = constraintHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; + this.constraintCreationContext = constraintCreationContext; this.groupsStaxBuilder = new GroupsStaxBuilder( classLoadingHelper, defaultPackageStaxBuilder ); this.payloadStaxBuilder = new PayloadStaxBuilder( classLoadingHelper, defaultPackageStaxBuilder ); @@ -150,10 +144,12 @@ MetaConstraint build(ConstraintLocation constraintLoca // we set initially ConstraintOrigin.DEFINED_LOCALLY for all xml configured constraints // later we will make copies of this constraint descriptor when needed and adjust the ConstraintOrigin ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl<>( - constraintHelper, constraintLocation.getConstrainable(), annotationDescriptor, kind, constraintType + constraintCreationContext.getConstraintHelper(), constraintLocation.getConstrainable(), annotationDescriptor, kind, constraintType ); - return MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor, constraintLocation ); + return MetaConstraints.create( constraintCreationContext.getTypeResolutionHelper(), + constraintCreationContext.getValueExtractorManager(), + constraintCreationContext.getConstraintValidatorManager(), constraintDescriptor, constraintLocation ); } private static class MessageStaxBuilder extends AbstractOneLineStringStaxBuilder { diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypeStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypeStaxBuilder.java index eeb2d16a6d..456dacc83b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypeStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ContainerElementTypeStaxBuilder.java @@ -23,15 +23,13 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.XMLEvent; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.engine.valueextraction.ArrayElement; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.TypeHelper; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.xml.AbstractStaxBuilder; @@ -51,9 +49,7 @@ class ContainerElementTypeStaxBuilder extends AbstractStaxBuilder { private static final QName TYPE_ARGUMENT_INDEX_QNAME = new QName( "type-argument-index" ); private final ClassLoadingHelper classLoadingHelper; - private final ConstraintHelper constraintHelper; - private final TypeResolutionHelper typeResolutionHelper; - private final ValueExtractorManager valueExtractorManager; + private final ConstraintCreationContext constraintCreationContext; private final DefaultPackageStaxBuilder defaultPackageStaxBuilder; private Integer typeArgumentIndex; @@ -62,13 +58,11 @@ class ContainerElementTypeStaxBuilder extends AbstractStaxBuilder { private final GroupConversionStaxBuilder groupConversionBuilder; private final List containerElementTypeConfigurationStaxBuilders; - ContainerElementTypeStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, - TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, DefaultPackageStaxBuilder defaultPackageStaxBuilder) { + ContainerElementTypeStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintCreationContext constraintCreationContext, + DefaultPackageStaxBuilder defaultPackageStaxBuilder) { this.classLoadingHelper = classLoadingHelper; this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; - this.constraintHelper = constraintHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; + this.constraintCreationContext = constraintCreationContext; this.groupConversionBuilder = new GroupConversionStaxBuilder( classLoadingHelper, defaultPackageStaxBuilder ); this.validStaxBuilder = new ValidStaxBuilder(); @@ -106,11 +100,13 @@ protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLS } private ConstraintTypeStaxBuilder getNewConstraintTypeStaxBuilder() { - return new ConstraintTypeStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder ); + return new ConstraintTypeStaxBuilder( classLoadingHelper, constraintCreationContext, + defaultPackageStaxBuilder ); } private ContainerElementTypeStaxBuilder getNewContainerElementTypeConfigurationStaxBuilder() { - return new ContainerElementTypeStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder ); + return new ContainerElementTypeStaxBuilder( classLoadingHelper, constraintCreationContext, + defaultPackageStaxBuilder ); } public ContainerElementTypeConfiguration build(Set configuredPaths, diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java index 84119ecbd3..5719dedbac 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/CrossParameterStaxBuilder.java @@ -17,15 +17,13 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.XMLEvent; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl.ConstraintType; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.properties.Callable; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.xml.AbstractStaxBuilder; /** @@ -39,23 +37,18 @@ class CrossParameterStaxBuilder extends AbstractStaxBuilder { private static final QName IGNORE_ANNOTATIONS_QNAME = new QName( "ignore-annotations" ); protected final ClassLoadingHelper classLoadingHelper; - protected final ConstraintHelper constraintHelper; - protected final TypeResolutionHelper typeResolutionHelper; - protected final ValueExtractorManager valueExtractorManager; + protected final ConstraintCreationContext constraintCreationContext; protected final DefaultPackageStaxBuilder defaultPackageStaxBuilder; protected final AnnotationProcessingOptionsImpl annotationProcessingOptions; protected Optional ignoreAnnotations; protected final List constraintTypeStaxBuilders; - CrossParameterStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, - TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + CrossParameterStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintCreationContext constraintCreationContext, DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions) { this.classLoadingHelper = classLoadingHelper; this.defaultPackageStaxBuilder = defaultPackageStaxBuilder; - this.constraintHelper = constraintHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; + this.constraintCreationContext = constraintCreationContext; this.annotationProcessingOptions = annotationProcessingOptions; @@ -81,7 +74,7 @@ protected void add(XMLEventReader xmlEventReader, XMLEvent xmlEvent) throws XMLS } private ConstraintTypeStaxBuilder getNewConstraintTypeStaxBuilder() { - return new ConstraintTypeStaxBuilder( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder ); + return new ConstraintTypeStaxBuilder( classLoadingHelper, constraintCreationContext, defaultPackageStaxBuilder ); } Set> build(Callable callable) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java index 51f5e103e4..22a1b1b864 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/MappingXmlParser.java @@ -26,20 +26,17 @@ import javax.xml.validation.Schema; import javax.xml.validation.Validator; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader; import org.hibernate.validator.internal.util.privilegedactions.SetContextClassLoader; import org.hibernate.validator.internal.xml.CloseIgnoringInputStream; import org.hibernate.validator.internal.xml.XmlParserHelper; - import org.xml.sax.SAXException; /** @@ -53,9 +50,7 @@ public class MappingXmlParser { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); private final Set> processedClasses = newHashSet(); - private final ConstraintHelper constraintHelper; - private final TypeResolutionHelper typeResolutionHelper; - private final ValueExtractorManager valueExtractorManager; + private final ConstraintCreationContext constraintCreationContext; private final AnnotationProcessingOptionsImpl annotationProcessingOptions; private final JavaBeanHelper javaBeanHelper; private final Map, List>> defaultSequences; @@ -77,11 +72,8 @@ private static Map getSchemasByVersion() { return schemasByVersion; } - public MappingXmlParser(ConstraintHelper constraintHelper, TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, - JavaBeanHelper javaBeanHelper, ClassLoader externalClassLoader) { - this.constraintHelper = constraintHelper; - this.typeResolutionHelper = typeResolutionHelper; - this.valueExtractorManager = valueExtractorManager; + public MappingXmlParser(ConstraintCreationContext constraintCreationContext, JavaBeanHelper javaBeanHelper, ClassLoader externalClassLoader) { + this.constraintCreationContext = constraintCreationContext; this.annotationProcessingOptions = new AnnotationProcessingOptionsImpl(); this.javaBeanHelper = javaBeanHelper; this.defaultSequences = newHashMap(); @@ -127,7 +119,7 @@ public final void parse(Set mappingStreams) { in.reset(); ConstraintMappingsStaxBuilder constraintMappingsStaxBuilder = new ConstraintMappingsStaxBuilder( - classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, + classLoadingHelper, constraintCreationContext, annotationProcessingOptions, javaBeanHelper, defaultSequences ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java index 8157a2ba6d..71520c4f5a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/mapping/ReturnValueStaxBuilder.java @@ -12,16 +12,14 @@ import javax.xml.namespace.QName; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.metadata.aggregated.CascadingMetaDataBuilder; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.properties.Callable; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.xml.mapping.ContainerElementTypeConfigurationBuilder.ContainerElementTypeConfiguration; /** @@ -33,10 +31,9 @@ class ReturnValueStaxBuilder extends AbstractConstrainedElementStaxBuilder { private static final String RETURN_VALUE_QNAME_LOCAL_PART = "return-value"; - ReturnValueStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintHelper constraintHelper, - TypeResolutionHelper typeResolutionHelper, ValueExtractorManager valueExtractorManager, + ReturnValueStaxBuilder(ClassLoadingHelper classLoadingHelper, ConstraintCreationContext constraintCreationContext, DefaultPackageStaxBuilder defaultPackageStaxBuilder, AnnotationProcessingOptionsImpl annotationProcessingOptions) { - super( classLoadingHelper, constraintHelper, typeResolutionHelper, valueExtractorManager, defaultPackageStaxBuilder, annotationProcessingOptions ); + super( classLoadingHelper, constraintCreationContext, defaultPackageStaxBuilder, annotationProcessingOptions ); } @Override diff --git a/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java b/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java index 9fe5899cd4..e1c5ca96fc 100644 --- a/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java @@ -9,13 +9,13 @@ import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertNoViolations; import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; +import static org.hibernate.validator.testutils.ConstraintValidatorInitializationHelper.getDummyConstraintCreationContext; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import java.lang.annotation.ElementType; import java.util.Arrays; import java.util.Calendar; -import java.util.Collections; import java.util.GregorianCalendar; import java.util.List; import java.util.Set; @@ -48,17 +48,13 @@ import org.hibernate.validator.constraints.Range; import org.hibernate.validator.group.GroupSequenceProvider; import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.metadata.raw.ConstrainedExecutable; import org.hibernate.validator.internal.metadata.raw.ConstrainedField; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.spi.group.DefaultGroupSequenceProvider; import org.hibernate.validator.testutils.ValidatorUtil; - import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -555,9 +551,7 @@ public void testDeprecatedPropertyMethodForFieldAndGetterProgrammaticConstraintD private BeanConfiguration getBeanConfiguration(Class type) { Set> beanConfigurations = mapping.getBeanConfigurations( - new ConstraintHelper(), - new TypeResolutionHelper(), - new ValueExtractorManager( Collections.emptySet() ) + getDummyConstraintCreationContext() ); for ( BeanConfiguration beanConfiguration : beanConfigurations ) { diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java index ae86af9aa6..09a67ac8f4 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java @@ -9,6 +9,7 @@ import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; import static org.hibernate.validator.testutil.ConstraintViolationAssert.pathWith; import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; +import static org.hibernate.validator.testutils.ConstraintValidatorInitializationHelper.getDummyConstraintCreationContext; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; @@ -31,11 +32,9 @@ import org.hibernate.validator.internal.engine.MethodValidationConfiguration; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.engine.path.PathImpl; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl; import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; @@ -194,11 +193,9 @@ public void testCreationOfExecutablePath() throws Exception { Method executable = Container.class.getMethod( "addItem", Key.class, Item.class ); BeanMetaDataManager beanMetaDataManager = new BeanMetaDataManagerImpl( - new ConstraintHelper(), + getDummyConstraintCreationContext(), new ExecutableHelper( new TypeResolutionHelper() ), - new TypeResolutionHelper(), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), - new ValueExtractorManager( Collections.emptySet() ), new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), new ValidationOrderGenerator(), Collections.emptyList(), diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java index 67ed249488..306006d7d0 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java @@ -6,6 +6,7 @@ */ package org.hibernate.validator.test.internal.metadata; +import static org.hibernate.validator.testutils.ConstraintValidatorInitializationHelper.getDummyConstraintCreationContext; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotSame; import static org.testng.Assert.assertTrue; @@ -23,11 +24,9 @@ import org.hibernate.validator.internal.engine.DefaultParameterNameProvider; import org.hibernate.validator.internal.engine.MethodValidationConfiguration; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; @@ -53,11 +52,9 @@ public class BeanMetaDataManagerTest { @BeforeMethod public void setUpBeanMetaDataManager() { metaDataManager = new BeanMetaDataManagerImpl( - new ConstraintHelper(), + getDummyConstraintCreationContext(), new ExecutableHelper( new TypeResolutionHelper() ), - new TypeResolutionHelper(), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), - new ValueExtractorManager( Collections.emptySet() ), new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), new ValidationOrderGenerator(), Collections.emptyList(), diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java index ab4b283fb3..172df763ed 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java @@ -7,6 +7,7 @@ package org.hibernate.validator.test.internal.metadata.aggregated; import static org.assertj.core.api.Assertions.assertThat; +import static org.hibernate.validator.testutils.ConstraintValidatorInitializationHelper.getDummyConstraintCreationContext; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; @@ -25,12 +26,10 @@ import org.hibernate.validator.internal.engine.DefaultParameterNameProvider; import org.hibernate.validator.internal.engine.MethodValidationConfiguration; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; @@ -59,11 +58,9 @@ public class ExecutableMetaDataTest { @BeforeMethod public void setupBeanMetaData() { beanMetaDataManager = new BeanMetaDataManagerImpl( - new ConstraintHelper(), + getDummyConstraintCreationContext(), new ExecutableHelper( new TypeResolutionHelper() ), - new TypeResolutionHelper(), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), - new ValueExtractorManager( Collections.emptySet() ), new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), new ValidationOrderGenerator(), Collections.emptyList(), diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java index 5748cc5048..189b3a75d0 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java @@ -7,6 +7,7 @@ package org.hibernate.validator.test.internal.metadata.aggregated; import static org.assertj.core.api.Assertions.assertThat; +import static org.hibernate.validator.testutils.ConstraintValidatorInitializationHelper.getDummyConstraintCreationContext; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; @@ -26,13 +27,11 @@ import org.hibernate.validator.internal.engine.DefaultParameterNameProvider; import org.hibernate.validator.internal.engine.MethodValidationConfiguration; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; import org.hibernate.validator.internal.metadata.aggregated.ParameterMetaData; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; @@ -59,11 +58,9 @@ public class ParameterMetaDataTest { @BeforeMethod public void setupBeanMetaData() { BeanMetaDataManager beanMetaDataManager = new BeanMetaDataManagerImpl( - new ConstraintHelper(), + getDummyConstraintCreationContext(), new ExecutableHelper( new TypeResolutionHelper() ), - new TypeResolutionHelper(), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), - new ValueExtractorManager( Collections.emptySet() ), new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), new ValidationOrderGenerator(), Collections.emptyList(), @@ -130,11 +127,9 @@ public void parameterNameInInheritanceHierarchy() throws Exception { // The failure rate on my current VM before fixing the bug is 50%. // Running it in a loop does not improve the odds of failure: all tests will pass or fail for all loop run. BeanMetaDataManager beanMetaDataManager = new BeanMetaDataManagerImpl( - new ConstraintHelper(), + getDummyConstraintCreationContext(), new ExecutableHelper( new TypeResolutionHelper() ), - new TypeResolutionHelper(), new ExecutableParameterNameProvider( new SkewedParameterNameProvider() ), - new ValueExtractorManager( Collections.emptySet() ), new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), new ValidationOrderGenerator(), Collections.emptyList(), diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java index fe7a328cc4..e7a723fd00 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java @@ -7,6 +7,7 @@ package org.hibernate.validator.test.internal.metadata.aggregated; import static org.assertj.core.api.Assertions.assertThat; +import static org.hibernate.validator.testutils.ConstraintValidatorInitializationHelper.getDummyConstraintCreationContext; import java.util.Collections; import java.util.Set; @@ -19,11 +20,9 @@ import org.hibernate.validator.internal.engine.DefaultParameterNameProvider; import org.hibernate.validator.internal.engine.MethodValidationConfiguration; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl; import org.hibernate.validator.internal.metadata.aggregated.PropertyMetaData; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; @@ -43,11 +42,9 @@ public class PropertyMetaDataTest { @BeforeMethod public void setupBeanMetaDataManager() { beanMetaDataManager = new BeanMetaDataManagerImpl( - new ConstraintHelper(), + getDummyConstraintCreationContext(), new ExecutableHelper( new TypeResolutionHelper() ), - new TypeResolutionHelper(), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), - new ValueExtractorManager( Collections.emptySet() ), new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), new ValidationOrderGenerator(), Collections.emptyList(), diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java index ce5e9f0708..e4965e5ce0 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java @@ -6,6 +6,7 @@ */ package org.hibernate.validator.test.internal.metadata.core; +import static org.hibernate.validator.testutils.ConstraintValidatorInitializationHelper.getDummyConstraintValidatorInitializationContext; import static org.testng.Assert.assertEquals; import java.lang.reflect.Method; @@ -13,6 +14,9 @@ import javax.validation.constraints.NotNull; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorFactoryImpl; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManagerImpl; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; @@ -35,6 +39,7 @@ public class MetaConstraintTest { private ConstraintHelper constraintHelper; private TypeResolutionHelper typeResolutionHelper; private ValueExtractorManager valueExtractorManager; + private ConstraintValidatorManager constraintValidatorManager; private Method barMethod; private ConstraintAnnotationDescriptor constraintAnnotationDescriptor; @@ -43,6 +48,7 @@ public void setUp() throws Exception { constraintHelper = new ConstraintHelper(); typeResolutionHelper = new TypeResolutionHelper(); valueExtractorManager = new ValueExtractorManager( Collections.emptySet() ); + constraintValidatorManager = new ConstraintValidatorManagerImpl( new ConstraintValidatorFactoryImpl(), getDummyConstraintValidatorInitializationContext() ); barMethod = Foo.class.getMethod( "getBar" ); constraintAnnotationDescriptor = new ConstraintAnnotationDescriptor.Builder<>( barMethod.getAnnotation( NotNull.class ) ).build(); } @@ -55,13 +61,15 @@ public void two_meta_constraints_for_the_same_constraint_should_be_equal() throw constraintHelper, javaBeanGetter, constraintAnnotationDescriptor, ConstraintLocationKind.METHOD ); ConstraintLocation location1 = ConstraintLocation.forClass( Foo.class ); - MetaConstraint metaConstraint1 = MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor1, location1 ); + MetaConstraint metaConstraint1 = MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintValidatorManager, + constraintDescriptor1, location1 ); ConstraintDescriptorImpl constraintDescriptor2 = new ConstraintDescriptorImpl<>( constraintHelper, javaBeanGetter, constraintAnnotationDescriptor, ConstraintLocationKind.METHOD ); ConstraintLocation location2 = ConstraintLocation.forClass( Foo.class ); - MetaConstraint metaConstraint2 = MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintDescriptor2, location2 ); + MetaConstraint metaConstraint2 = MetaConstraints.create( typeResolutionHelper, valueExtractorManager, constraintValidatorManager, + constraintDescriptor2, location2 ); assertEquals( metaConstraint1, metaConstraint2, "Two MetaConstraint instances for the same constraint should be equal" diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/descriptor/BeanDescriptorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/descriptor/BeanDescriptorTest.java index c5e0fbf00e..30e44cc64e 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/descriptor/BeanDescriptorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/descriptor/BeanDescriptorTest.java @@ -463,7 +463,7 @@ public void foo(String foo) { } } - @ScriptAssert(lang = "some lang", script = "some script") + @ScriptAssert(lang = "groovy", script = "true") private static class ClassLevelConstrainedType { } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java index cd7fce3d4e..21ab1a450c 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java @@ -10,13 +10,13 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; import static org.assertj.core.api.Assertions.assertThat; import static org.hibernate.validator.internal.util.CollectionHelper.newHashMap; +import static org.hibernate.validator.testutils.ConstraintValidatorInitializationHelper.getDummyConstraintCreationContext; import java.lang.annotation.Documented; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.time.LocalDate; -import java.util.Collections; import java.util.Map; import javax.validation.Constraint; @@ -29,9 +29,7 @@ import javax.validation.metadata.ConstraintDescriptor; import org.hibernate.validator.constraints.ScriptAssert; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider; @@ -43,9 +41,7 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedType; import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.testutil.TestForIssue; - import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -61,9 +57,7 @@ public class AnnotationMetaDataProviderTest extends AnnotationMetaDataProviderTe @BeforeMethod public void setUpProvider() { provider = new AnnotationMetaDataProvider( - new ConstraintHelper(), - new TypeResolutionHelper(), - new ValueExtractorManager( Collections.emptySet() ), + getDummyConstraintCreationContext(), new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), new AnnotationProcessingOptionsImpl() ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/TypeAnnotationMetaDataRetrievalTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/TypeAnnotationMetaDataRetrievalTest.java index 5dc4c74d87..ee70424dab 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/TypeAnnotationMetaDataRetrievalTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/TypeAnnotationMetaDataRetrievalTest.java @@ -7,6 +7,7 @@ package org.hibernate.validator.test.internal.metadata.provider; import static org.assertj.core.api.Assertions.assertThat; +import static org.hibernate.validator.testutils.ConstraintValidatorInitializationHelper.getDummyConstraintCreationContext; import java.lang.annotation.Annotation; import java.util.Collection; @@ -18,9 +19,7 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider; import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; @@ -29,7 +28,6 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedParameter; import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -45,9 +43,7 @@ public class TypeAnnotationMetaDataRetrievalTest extends AnnotationMetaDataProvi @BeforeClass public void setup() { provider = new AnnotationMetaDataProvider( - new ConstraintHelper(), - new TypeResolutionHelper(), - new ValueExtractorManager( Collections.emptySet() ), + getDummyConstraintCreationContext(), new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), new AnnotationProcessingOptionsImpl() ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/xml/MappingXmlParserTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/xml/MappingXmlParserTest.java index 56d1d341c1..b264cd1d17 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/xml/MappingXmlParserTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/xml/MappingXmlParserTest.java @@ -7,13 +7,13 @@ package org.hibernate.validator.test.internal.xml; import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; +import static org.hibernate.validator.testutils.ConstraintValidatorInitializationHelper.getDummyConstraintCreationContext; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import java.io.InputStream; -import java.util.Collections; import java.util.List; import java.util.Set; @@ -22,12 +22,10 @@ import javax.validation.ValidationException; import javax.validation.constraints.DecimalMin; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorDescriptor; -import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; -import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; -import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.xml.mapping.MappingXmlParser; import org.hibernate.validator.testutil.TestForIssue; import org.testng.annotations.BeforeMethod; @@ -39,20 +37,21 @@ public class MappingXmlParserTest { private MappingXmlParser xmlMappingParser; - private ConstraintHelper constraintHelper; + private ConstraintCreationContext constraintCreationContext; @BeforeMethod public void setupParserHelper() { - constraintHelper = new ConstraintHelper(); + constraintCreationContext = getDummyConstraintCreationContext(); xmlMappingParser = new MappingXmlParser( - constraintHelper, new TypeResolutionHelper(), new ValueExtractorManager( Collections.emptySet() ), new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), null + constraintCreationContext, + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), null ); } @Test @TestForIssue(jiraKey = "HV-782") public void testAdditionalConstraintValidatorsGetAddedAndAreLastInList() { - List> validatorDescriptors = constraintHelper.getAllValidatorDescriptors( + List> validatorDescriptors = constraintCreationContext.getConstraintHelper().getAllValidatorDescriptors( DecimalMin.class ); @@ -64,7 +63,7 @@ public void testAdditionalConstraintValidatorsGetAddedAndAreLastInList() { xmlMappingParser.parse( mappingStreams ); - validatorDescriptors = constraintHelper.getAllValidatorDescriptors( DecimalMin.class ); + validatorDescriptors = constraintCreationContext.getConstraintHelper().getAllValidatorDescriptors( DecimalMin.class ); assertFalse( validatorDescriptors.isEmpty(), "Wrong number of default validators" ); assertEquals( getIndex( validatorDescriptors, DecimalMinValidatorForFoo.class ), validatorDescriptors.size() - 1, "The custom validator must be last" ); diff --git a/engine/src/test/java/org/hibernate/validator/testutils/ConstraintValidatorInitializationHelper.java b/engine/src/test/java/org/hibernate/validator/testutils/ConstraintValidatorInitializationHelper.java index 30dbe909d4..1978dc0c6b 100644 --- a/engine/src/test/java/org/hibernate/validator/testutils/ConstraintValidatorInitializationHelper.java +++ b/engine/src/test/java/org/hibernate/validator/testutils/ConstraintValidatorInitializationHelper.java @@ -8,17 +8,23 @@ import java.lang.annotation.Annotation; import java.time.Duration; +import java.util.Collections; import javax.validation.ClockProvider; import javax.validation.metadata.ConstraintDescriptor; import org.hibernate.validator.constraintvalidation.HibernateConstraintValidator; import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; +import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.engine.DefaultClockProvider; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorFactoryImpl; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManagerImpl; import org.hibernate.validator.internal.engine.scripting.DefaultScriptEvaluatorFactory; +import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; +import org.hibernate.validator.internal.util.TypeResolutionHelper; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.spi.scripting.ScriptEvaluator; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; @@ -66,6 +72,13 @@ public static HibernateConstraintValidatorInitializationContext getDummyConstrai return DUMMY_CONSTRAINT_VALIDATOR_INITIALIZATION_CONTEXT; } + public static ConstraintCreationContext getDummyConstraintCreationContext() { + return new ConstraintCreationContext( new ConstraintHelper(), + new ConstraintValidatorManagerImpl( new ConstraintValidatorFactoryImpl(), getDummyConstraintValidatorInitializationContext() ), + new TypeResolutionHelper(), + new ValueExtractorManager( Collections.emptySet() ) ); + } + public static HibernateConstraintValidatorInitializationContext getConstraintValidatorInitializationContext( ScriptEvaluatorFactory scriptEvaluatorFactory, ClockProvider clockProvider, Duration duration ) { diff --git a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java index e156542893..90ccc79411 100644 --- a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java +++ b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java @@ -195,7 +195,7 @@ public void canConfigureCustomConstraintValidatorFactoryViaValidationXml() { .getValidator() .validate( new Customer() ); - assertEquals( 1, ExampleConstraintValidatorFactory.invocationCounter.get() ); + assertEquals( 2, ExampleConstraintValidatorFactory.invocationCounter.get() ); } @Test From e96de7f8b90c9e4c537929778852f52df6332141 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Sat, 8 Dec 2018 13:24:33 +0100 Subject: [PATCH 142/393] HV-1667 Initialize the default constraint validators eagerly --- .../ComposingConstraintTree.java | 12 ++--- .../constraintvalidation/ConstraintTree.java | 47 +++++++++---------- .../SimpleConstraintTree.java | 4 +- .../metadata/core/MetaConstraint.java | 2 +- 4 files changed, 30 insertions(+), 35 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java index 3b01a1cf88..6e1a021c71 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java @@ -47,19 +47,19 @@ class ComposingConstraintTree extends ConstraintTree { @Immutable private final List> children; - public ComposingConstraintTree(ConstraintDescriptorImpl descriptor, Type validatedValueType) { - super( descriptor, validatedValueType ); + public ComposingConstraintTree(ConstraintValidatorManager constraintValidatorManager, ConstraintDescriptorImpl descriptor, Type validatedValueType) { + super( constraintValidatorManager, descriptor, validatedValueType ); this.children = descriptor.getComposingConstraintImpls().stream() - .map( desc -> createConstraintTree( desc ) ) + .map( desc -> createConstraintTree( constraintValidatorManager, desc ) ) .collect( Collectors.collectingAndThen( Collectors.toList(), CollectionHelper::toImmutableList ) ); } - private ConstraintTree createConstraintTree(ConstraintDescriptorImpl composingDescriptor) { + private ConstraintTree createConstraintTree(ConstraintValidatorManager constraintValidatorManager, ConstraintDescriptorImpl composingDescriptor) { if ( composingDescriptor.getComposingConstraintImpls().isEmpty() ) { - return new SimpleConstraintTree<>( composingDescriptor, getValidatedValueType() ); + return new SimpleConstraintTree<>( constraintValidatorManager, composingDescriptor, getValidatedValueType() ); } else { - return new ComposingConstraintTree<>( composingDescriptor, getValidatedValueType() ); + return new ComposingConstraintTree<>( constraintValidatorManager, composingDescriptor, getValidatedValueType() ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java index 3cafdf1b28..22c7970548 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java @@ -18,8 +18,10 @@ import javax.validation.ConstraintDeclarationException; import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorFactory; import javax.validation.ValidationException; +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; import org.hibernate.validator.internal.engine.ValueContext; import org.hibernate.validator.internal.engine.validationcontext.ValidationContext; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; @@ -48,23 +50,24 @@ public abstract class ConstraintTree { private final Type validatedValueType; - /** - * Either the initialized constraint validator for the default constraint validator factory or - * {@link ConstraintValidatorManager#DUMMY_CONSTRAINT_VALIDATOR}. - */ - private volatile ConstraintValidator constraintValidatorForDefaultConstraintValidatorFactoryAndInitializationContext; + private final ConstraintValidator defaultInitializedConstraintValidator; - protected ConstraintTree(ConstraintDescriptorImpl descriptor, Type validatedValueType) { + protected ConstraintTree(ConstraintValidatorManager constraintValidatorManager, ConstraintDescriptorImpl descriptor, Type validatedValueType) { this.descriptor = descriptor; this.validatedValueType = validatedValueType; + + this.defaultInitializedConstraintValidator = getInitializedConstraintValidator( constraintValidatorManager, + constraintValidatorManager.getDefaultConstraintValidatorFactory(), + constraintValidatorManager.getDefaultConstraintValidatorInitializationContext() ); } - public static ConstraintTree of(ConstraintDescriptorImpl composingDescriptor, Type validatedValueType) { + public static ConstraintTree of(ConstraintValidatorManager constraintValidatorManager, + ConstraintDescriptorImpl composingDescriptor, Type validatedValueType) { if ( composingDescriptor.getComposingConstraintImpls().isEmpty() ) { - return new SimpleConstraintTree<>( composingDescriptor, validatedValueType ); + return new SimpleConstraintTree<>( constraintValidatorManager, composingDescriptor, validatedValueType ); } else { - return new ComposingConstraintTree<>( composingDescriptor, validatedValueType ); + return new ComposingConstraintTree<>( constraintValidatorManager, composingDescriptor, validatedValueType ); } } @@ -121,25 +124,15 @@ private ValidationException getExceptionForNullValidator(Type validatedValueType if ( validationContext.getConstraintValidatorFactory() == validationContext.getConstraintValidatorManager().getDefaultConstraintValidatorFactory() && validationContext.getConstraintValidatorInitializationContext() == validationContext.getConstraintValidatorManager() .getDefaultConstraintValidatorInitializationContext() ) { - validator = constraintValidatorForDefaultConstraintValidatorFactoryAndInitializationContext; - - if ( validator == null ) { - synchronized ( this ) { - validator = constraintValidatorForDefaultConstraintValidatorFactoryAndInitializationContext; - if ( validator == null ) { - validator = getInitializedConstraintValidator( validationContext ); - - constraintValidatorForDefaultConstraintValidatorFactoryAndInitializationContext = validator; - } - } - } + validator = defaultInitializedConstraintValidator; } else { // For now, we don't cache the result in the ConstraintTree if we don't use the default constraint validator // factory. Creating a lot of CHM for that cache might not be a good idea and we prefer being conservative // for now. Note that we have the ConstraintValidatorManager cache that mitigates the situation. // If you come up with a use case where it makes sense, please reach out to us. - validator = getInitializedConstraintValidator( validationContext ); + validator = getInitializedConstraintValidator( validationContext.getConstraintValidatorManager(), validationContext.getConstraintValidatorFactory(), + validationContext.getConstraintValidatorInitializationContext() ); } if ( validator == DUMMY_CONSTRAINT_VALIDATOR ) { @@ -150,12 +143,14 @@ private ValidationException getExceptionForNullValidator(Type validatedValueType } @SuppressWarnings("unchecked") - private ConstraintValidator getInitializedConstraintValidator(ValidationContext validationContext) { - ConstraintValidator validator = validationContext.getConstraintValidatorManager().getInitializedValidator( + private ConstraintValidator getInitializedConstraintValidator(ConstraintValidatorManager constraintValidatorManager, + ConstraintValidatorFactory constraintValidatorFactory, + HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext) { + ConstraintValidator validator = constraintValidatorManager.getInitializedValidator( validatedValueType, descriptor, - validationContext.getConstraintValidatorFactory(), - validationContext.getConstraintValidatorInitializationContext() + constraintValidatorFactory, + constraintValidatorInitializationContext ); if ( validator != null ) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java index cfbbeb0657..882786cf34 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java @@ -33,8 +33,8 @@ class SimpleConstraintTree extends ConstraintTree { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - public SimpleConstraintTree(ConstraintDescriptorImpl descriptor, Type validatedValueType) { - super( descriptor, validatedValueType ); + public SimpleConstraintTree(ConstraintValidatorManager constraintValidatorManager, ConstraintDescriptorImpl descriptor, Type validatedValueType) { + super( constraintValidatorManager, descriptor, validatedValueType ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java index 7d5e23e560..44e9577167 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java @@ -71,7 +71,7 @@ public class MetaConstraint { MetaConstraint(ConstraintValidatorManager constraintValidatorManager, ConstraintDescriptorImpl constraintDescriptor, ConstraintLocation location, List valueExtractionPath, Type validatedValueType) { - this.constraintTree = ConstraintTree.of( constraintDescriptor, validatedValueType ); + this.constraintTree = ConstraintTree.of( constraintValidatorManager, constraintDescriptor, validatedValueType ); this.location = location; this.valueExtractionPath = getValueExtractionPath( valueExtractionPath ); this.hashCode = buildHashCode( constraintDescriptor, location ); From 289fd3f12268a87132bc41a80601521d4f3d80c0 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 28 Nov 2018 13:14:28 +0100 Subject: [PATCH 143/393] HV-1667 Introduce a simplified ConstraintValidatorManager for predefined scope --- .../PredefinedScopeValidatorFactoryImpl.java | 4 +- ...bstractConstraintValidatorManagerImpl.java | 178 ++++++++++++++++++ .../ConstraintValidatorManagerImpl.java | 153 +-------------- ...edScopeConstraintValidatorManagerImpl.java | 66 +++++++ 4 files changed, 253 insertions(+), 148 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/AbstractConstraintValidatorManagerImpl.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/PredefinedScopeConstraintValidatorManagerImpl.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java index b738a6dc9b..7c8fb063af 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java @@ -39,7 +39,7 @@ import org.hibernate.validator.PredefinedScopeHibernateValidatorFactory; import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; -import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManagerImpl; +import org.hibernate.validator.internal.engine.constraintvalidation.PredefinedScopeConstraintValidatorManagerImpl; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.metadata.PredefinedScopeBeanMetaDataManager; @@ -116,7 +116,7 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState getConstraintValidatorPayload( hibernateSpecificConfig ) ); - this.constraintValidatorManager = new ConstraintValidatorManagerImpl( + this.constraintValidatorManager = new PredefinedScopeConstraintValidatorManagerImpl( configurationState.getConstraintValidatorFactory(), this.validatorFactoryScopedContext.getConstraintValidatorInitializationContext() ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/AbstractConstraintValidatorManagerImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/AbstractConstraintValidatorManagerImpl.java new file mode 100644 index 0000000000..a8c14621ec --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/AbstractConstraintValidatorManagerImpl.java @@ -0,0 +1,178 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.constraintvalidation; + +import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; + +import java.lang.annotation.Annotation; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.validation.ConstraintDeclarationException; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorFactory; +import javax.validation.metadata.ConstraintDescriptor; + +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidator; +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; +import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; +import org.hibernate.validator.internal.util.TypeHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; + +/** + * @author Guillaume Smet + */ +public abstract class AbstractConstraintValidatorManagerImpl implements ConstraintValidatorManager { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + /** + * The explicit or implicit default constraint validator factory. We always cache {@code ConstraintValidator} + * instances if they are created via the default instance and with the default initialization context. Constraint + * validator instances created via other factory instances (specified eg via {@code ValidatorFactory#usingContext()} + * or initialization context are only cached for the most recently used factory and context. + */ + private final ConstraintValidatorFactory defaultConstraintValidatorFactory; + + /** + * The explicit or implicit default constraint validator initialization context. We always cache + * {@code ConstraintValidator} instances if they are created via the default instance and with the default context. + * Constraint validator instances created via other factory instances (specified eg via + * {@code ValidatorFactory#usingContext()} or initialization context are only cached for the most recently used + * factory and context. + */ + private final HibernateConstraintValidatorInitializationContext defaultConstraintValidatorInitializationContext; + + /** + * Creates a new {@code ConstraintValidatorManager}. + * + * @param defaultConstraintValidatorFactory the default validator factory + * @param defaultConstraintValidatorInitializationContext the default initialization context + */ + public AbstractConstraintValidatorManagerImpl(ConstraintValidatorFactory defaultConstraintValidatorFactory, + HibernateConstraintValidatorInitializationContext defaultConstraintValidatorInitializationContext) { + this.defaultConstraintValidatorFactory = defaultConstraintValidatorFactory; + this.defaultConstraintValidatorInitializationContext = defaultConstraintValidatorInitializationContext; + } + + @Override + public ConstraintValidatorFactory getDefaultConstraintValidatorFactory() { + return defaultConstraintValidatorFactory; + } + + @Override + public HibernateConstraintValidatorInitializationContext getDefaultConstraintValidatorInitializationContext() { + return defaultConstraintValidatorInitializationContext; + } + + protected ConstraintValidator createAndInitializeValidator( + Type validatedValueType, + ConstraintDescriptorImpl descriptor, + ConstraintValidatorFactory constraintValidatorFactory, + HibernateConstraintValidatorInitializationContext initializationContext) { + + ConstraintValidatorDescriptor validatorDescriptor = findMatchingValidatorDescriptor( descriptor, validatedValueType ); + ConstraintValidator constraintValidator; + + if ( validatorDescriptor == null ) { + return null; + } + + constraintValidator = validatorDescriptor.newInstance( constraintValidatorFactory ); + initializeValidator( descriptor, constraintValidator, initializationContext ); + + return constraintValidator; + } + + /** + * Runs the validator resolution algorithm. + * + * @param validatedValueType The type of the value to be validated (the type of the member/class the constraint was placed on). + * + * @return The class of a matching validator. + */ + private ConstraintValidatorDescriptor findMatchingValidatorDescriptor(ConstraintDescriptorImpl descriptor, Type validatedValueType) { + Map> availableValidatorDescriptors = TypeHelper.getValidatorTypes( + descriptor.getAnnotationType(), + descriptor.getMatchingConstraintValidatorDescriptors() + ); + + List discoveredSuitableTypes = findSuitableValidatorTypes( validatedValueType, availableValidatorDescriptors.keySet() ); + resolveAssignableTypes( discoveredSuitableTypes ); + + if ( discoveredSuitableTypes.size() == 0 ) { + return null; + } + + if ( discoveredSuitableTypes.size() > 1 ) { + throw LOG.getMoreThanOneValidatorFoundForTypeException( validatedValueType, discoveredSuitableTypes ); + } + + Type suitableType = discoveredSuitableTypes.get( 0 ); + return availableValidatorDescriptors.get( suitableType ); + } + + private List findSuitableValidatorTypes(Type type, Iterable availableValidatorTypes) { + List determinedSuitableTypes = newArrayList(); + for ( Type validatorType : availableValidatorTypes ) { + if ( TypeHelper.isAssignable( validatorType, type ) + && !determinedSuitableTypes.contains( validatorType ) ) { + determinedSuitableTypes.add( validatorType ); + } + } + return determinedSuitableTypes; + } + + private void initializeValidator( + ConstraintDescriptor descriptor, + ConstraintValidator constraintValidator, + HibernateConstraintValidatorInitializationContext initializationContext) { + try { + if ( constraintValidator instanceof HibernateConstraintValidator ) { + ( (HibernateConstraintValidator) constraintValidator ).initialize( descriptor, initializationContext ); + } + constraintValidator.initialize( descriptor.getAnnotation() ); + } + catch (RuntimeException e) { + if ( e instanceof ConstraintDeclarationException ) { + throw e; + } + throw LOG.getUnableToInitializeConstraintValidatorException( constraintValidator.getClass(), e ); + } + } + + /** + * Tries to reduce all assignable classes down to a single class. + * + * @param assignableTypes The set of all classes which are assignable to the class of the value to be validated and + * which are handled by at least one of the validators for the specified constraint. + */ + private void resolveAssignableTypes(List assignableTypes) { + if ( assignableTypes.size() == 0 || assignableTypes.size() == 1 ) { + return; + } + + List typesToRemove = new ArrayList<>(); + do { + typesToRemove.clear(); + Type type = assignableTypes.get( 0 ); + for ( int i = 1; i < assignableTypes.size(); i++ ) { + if ( TypeHelper.isAssignable( type, assignableTypes.get( i ) ) ) { + typesToRemove.add( type ); + } + else if ( TypeHelper.isAssignable( assignableTypes.get( i ), type ) ) { + typesToRemove.add( assignableTypes.get( i ) ); + } + } + assignableTypes.removeAll( typesToRemove ); + } while ( typesToRemove.size() > 0 ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManagerImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManagerImpl.java index e39d09d051..4cd5425dc2 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManagerImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManagerImpl.java @@ -6,28 +6,20 @@ */ package org.hibernate.validator.internal.engine.constraintvalidation; -import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; - import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandles; import java.lang.reflect.Type; -import java.util.ArrayList; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; -import javax.validation.ConstraintDeclarationException; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorFactory; -import javax.validation.metadata.ConstraintDescriptor; -import org.hibernate.validator.constraintvalidation.HibernateConstraintValidator; import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.util.Contracts; -import org.hibernate.validator.internal.util.TypeHelper; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -36,28 +28,12 @@ * Default implementation of the {@link ConstraintValidatorManager}. * * @author Hardy Ferentschik + * @author Guillaume Smet */ -public class ConstraintValidatorManagerImpl implements ConstraintValidatorManager { +public class ConstraintValidatorManagerImpl extends AbstractConstraintValidatorManagerImpl { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - /** - * The explicit or implicit default constraint validator factory. We always cache {@code ConstraintValidator} - * instances if they are created via the default instance and with the default initialization context. Constraint - * validator instances created via other factory instances (specified eg via {@code ValidatorFactory#usingContext()} - * or initialization context are only cached for the most recently used factory and context. - */ - private final ConstraintValidatorFactory defaultConstraintValidatorFactory; - - /** - * The explicit or implicit default constraint validator initialization context. We always cache - * {@code ConstraintValidator} instances if they are created via the default instance and with the default context. - * Constraint validator instances created via other factory instances (specified eg via - * {@code ValidatorFactory#usingContext()} or initialization context are only cached for the most recently used - * factory and context. - */ - private final HibernateConstraintValidatorInitializationContext defaultConstraintValidatorInitializationContext; - /** * The most recently used non default constraint validator factory. */ @@ -88,8 +64,7 @@ public class ConstraintValidatorManagerImpl implements ConstraintValidatorManage */ public ConstraintValidatorManagerImpl(ConstraintValidatorFactory defaultConstraintValidatorFactory, HibernateConstraintValidatorInitializationContext defaultConstraintValidatorInitializationContext) { - this.defaultConstraintValidatorFactory = defaultConstraintValidatorFactory; - this.defaultConstraintValidatorInitializationContext = defaultConstraintValidatorInitializationContext; + super( defaultConstraintValidatorFactory, defaultConstraintValidatorInitializationContext ); this.constraintValidatorCache = new ConcurrentHashMap<>(); } @@ -133,9 +108,9 @@ public ConstraintValidatorManagerImpl(ConstraintValidatorFactory defaultConstrai private ConstraintValidator cacheValidator(CacheKey key, ConstraintValidator constraintValidator) { // we only cache constraint validator instances for the default and most recently used factory - if ( ( key.getConstraintValidatorFactory() != defaultConstraintValidatorFactory + if ( ( key.getConstraintValidatorFactory() != getDefaultConstraintValidatorFactory() && key.getConstraintValidatorFactory() != mostRecentlyUsedNonDefaultConstraintValidatorFactory ) || - ( key.getConstraintValidatorInitializationContext() != defaultConstraintValidatorInitializationContext + ( key.getConstraintValidatorInitializationContext() != getDefaultConstraintValidatorInitializationContext() && key.getConstraintValidatorInitializationContext() != mostRecentlyUsedNonDefaultConstraintValidatorInitializationContext ) ) { synchronized ( mostRecentlyUsedNonDefaultConstraintValidatorFactoryAndInitializationContextMutex ) { @@ -149,32 +124,12 @@ public ConstraintValidatorManagerImpl(ConstraintValidatorFactory defaultConstrai } @SuppressWarnings("unchecked") - ConstraintValidator cached = (ConstraintValidator) constraintValidatorCache.putIfAbsent( key, constraintValidator ); + ConstraintValidator cached = (ConstraintValidator) constraintValidatorCache.putIfAbsent( key, + constraintValidator != null ? constraintValidator : DUMMY_CONSTRAINT_VALIDATOR ); return cached != null ? cached : constraintValidator; } - @SuppressWarnings("unchecked") - private ConstraintValidator createAndInitializeValidator( - Type validatedValueType, - ConstraintDescriptorImpl descriptor, - ConstraintValidatorFactory constraintValidatorFactory, - HibernateConstraintValidatorInitializationContext initializationContext) { - - ConstraintValidatorDescriptor validatorDescriptor = findMatchingValidatorDescriptor( descriptor, validatedValueType ); - ConstraintValidator constraintValidator; - - if ( validatorDescriptor == null ) { - constraintValidator = (ConstraintValidator) DUMMY_CONSTRAINT_VALIDATOR; - } - else { - constraintValidator = validatorDescriptor.newInstance( constraintValidatorFactory ); - initializeValidator( descriptor, constraintValidator, initializationContext ); - } - - return constraintValidator; - } - private void clearEntries(ConstraintValidatorFactory constraintValidatorFactory, HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext) { Iterator>> cacheEntries = constraintValidatorCache.entrySet().iterator(); @@ -196,104 +151,10 @@ public void clear() { constraintValidatorCache.clear(); } - @Override - public ConstraintValidatorFactory getDefaultConstraintValidatorFactory() { - return defaultConstraintValidatorFactory; - } - - @Override - public HibernateConstraintValidatorInitializationContext getDefaultConstraintValidatorInitializationContext() { - return defaultConstraintValidatorInitializationContext; - } - public int numberOfCachedConstraintValidatorInstances() { return constraintValidatorCache.size(); } - /** - * Runs the validator resolution algorithm. - * - * @param validatedValueType The type of the value to be validated (the type of the member/class the constraint was placed on). - * - * @return The class of a matching validator. - */ - private ConstraintValidatorDescriptor findMatchingValidatorDescriptor(ConstraintDescriptorImpl descriptor, Type validatedValueType) { - Map> availableValidatorDescriptors = TypeHelper.getValidatorTypes( - descriptor.getAnnotationType(), - descriptor.getMatchingConstraintValidatorDescriptors() - ); - - List discoveredSuitableTypes = findSuitableValidatorTypes( validatedValueType, availableValidatorDescriptors.keySet() ); - resolveAssignableTypes( discoveredSuitableTypes ); - - if ( discoveredSuitableTypes.size() == 0 ) { - return null; - } - - if ( discoveredSuitableTypes.size() > 1 ) { - throw LOG.getMoreThanOneValidatorFoundForTypeException( validatedValueType, discoveredSuitableTypes ); - } - - Type suitableType = discoveredSuitableTypes.get( 0 ); - return availableValidatorDescriptors.get( suitableType ); - } - - private List findSuitableValidatorTypes(Type type, Iterable availableValidatorTypes) { - List determinedSuitableTypes = newArrayList(); - for ( Type validatorType : availableValidatorTypes ) { - if ( TypeHelper.isAssignable( validatorType, type ) - && !determinedSuitableTypes.contains( validatorType ) ) { - determinedSuitableTypes.add( validatorType ); - } - } - return determinedSuitableTypes; - } - - private void initializeValidator( - ConstraintDescriptor descriptor, - ConstraintValidator constraintValidator, - HibernateConstraintValidatorInitializationContext initializationContext) { - try { - if ( constraintValidator instanceof HibernateConstraintValidator ) { - ( (HibernateConstraintValidator) constraintValidator ).initialize( descriptor, initializationContext ); - } - constraintValidator.initialize( descriptor.getAnnotation() ); - } - catch (RuntimeException e) { - if ( e instanceof ConstraintDeclarationException ) { - throw e; - } - throw LOG.getUnableToInitializeConstraintValidatorException( constraintValidator.getClass(), e ); - } - } - - /** - * Tries to reduce all assignable classes down to a single class. - * - * @param assignableTypes The set of all classes which are assignable to the class of the value to be validated and - * which are handled by at least one of the validators for the specified constraint. - */ - private void resolveAssignableTypes(List assignableTypes) { - if ( assignableTypes.size() == 0 || assignableTypes.size() == 1 ) { - return; - } - - List typesToRemove = new ArrayList<>(); - do { - typesToRemove.clear(); - Type type = assignableTypes.get( 0 ); - for ( int i = 1; i < assignableTypes.size(); i++ ) { - if ( TypeHelper.isAssignable( type, assignableTypes.get( i ) ) ) { - typesToRemove.add( type ); - } - else if ( TypeHelper.isAssignable( assignableTypes.get( i ), type ) ) { - typesToRemove.add( assignableTypes.get( i ) ); - } - } - assignableTypes.removeAll( typesToRemove ); - } while ( typesToRemove.size() > 0 ); - } - private static final class CacheKey { // These members are not final for optimization purposes private ConstraintAnnotationDescriptor annotationDescriptor; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/PredefinedScopeConstraintValidatorManagerImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/PredefinedScopeConstraintValidatorManagerImpl.java new file mode 100644 index 0000000000..473ba98da0 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/PredefinedScopeConstraintValidatorManagerImpl.java @@ -0,0 +1,66 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.constraintvalidation; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorFactory; + +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; +import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; +import org.hibernate.validator.internal.util.Contracts; + +/** + * Implementation of the {@link ConstraintValidatorManager} for the predefined scope ValidatorFactory. + * + * @author Guillaume Smet + */ +public class PredefinedScopeConstraintValidatorManagerImpl extends AbstractConstraintValidatorManagerImpl { + + /** + * Creates a new {@code ConstraintValidatorManager}. + * + * @param defaultConstraintValidatorFactory the default validator factory + * @param defaultConstraintValidatorInitializationContext the default initialization context + */ + public PredefinedScopeConstraintValidatorManagerImpl( + ConstraintValidatorFactory defaultConstraintValidatorFactory, + HibernateConstraintValidatorInitializationContext defaultConstraintValidatorInitializationContext + ) { + super( defaultConstraintValidatorFactory, defaultConstraintValidatorInitializationContext ); + } + + /** + * @param validatedValueType the type of the value to be validated. Cannot be {@code null}. + * @param descriptor the constraint descriptor for which to get an initialized constraint validator. Cannot be {@code null} + * @param constraintValidatorFactory constraint factory used to instantiate the constraint validator. Cannot be {@code null}. + * @param initializationContext context used on constraint validator initialization + * @param the annotation type + * + * @return an initialized constraint validator for the given type and annotation of the value to be validated. + * {@code null} is returned if no matching constraint validator could be found. + */ + @Override + public ConstraintValidator getInitializedValidator( + Type validatedValueType, + ConstraintDescriptorImpl descriptor, + ConstraintValidatorFactory constraintValidatorFactory, + HibernateConstraintValidatorInitializationContext initializationContext) { + Contracts.assertNotNull( validatedValueType ); + Contracts.assertNotNull( descriptor ); + Contracts.assertNotNull( constraintValidatorFactory ); + Contracts.assertNotNull( initializationContext ); + + return createAndInitializeValidator( validatedValueType, descriptor, constraintValidatorFactory, initializationContext ); + } + + @Override + public void clear() { + } +} From ea278f8b5ae6e39d8bbe73420733e6f2bf3b20bc Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 10 Dec 2018 14:26:53 +0100 Subject: [PATCH 144/393] HV-1667 Clean up ValidatorFactoryConfigurationHelper --- .../PredefinedScopeValidatorFactoryImpl.java | 42 ++++++++++--------- .../ValidatorFactoryConfigurationHelper.java | 28 ++++++------- .../internal/engine/ValidatorFactoryImpl.java | 40 +++++++++--------- 3 files changed, 56 insertions(+), 54 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java index 7c8fb063af..9282f3952d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java @@ -6,14 +6,16 @@ */ package org.hibernate.validator.internal.engine; -import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getAllowMultipleCascadedValidationOnReturnValues; -import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getAllowOverridingMethodAlterParameterConstraint; -import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getAllowParallelMethodsDefineParameterConstraints; -import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getConstraintMappings; -import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getConstraintValidatorPayload; -import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getExternalClassLoader; -import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getFailFast; -import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getTraversableResolverResultCacheEnabled; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowMultipleCascadedValidationOnReturnValues; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowOverridingMethodAlterParameterConstraint; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowParallelMethodsDefineParameterConstraints; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineConstraintMappings; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineConstraintValidatorPayload; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineExternalClassLoader; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineFailFast; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineScriptEvaluatorFactory; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineTemporalValidationTolerance; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineTraversableResolverResultCacheEnabled; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.logValidatorFactoryScopedConfiguration; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.registerCustomConstraintValidators; import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; @@ -89,7 +91,7 @@ public class PredefinedScopeValidatorFactoryImpl implements PredefinedScopeHiber private final ValidationOrderGenerator validationOrderGenerator; public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState) { - ClassLoader externalClassLoader = getExternalClassLoader( configurationState ); + ClassLoader externalClassLoader = determineExternalClassLoader( configurationState ); PredefinedScopeConfigurationImpl hibernateSpecificConfig = (PredefinedScopeConfigurationImpl) configurationState; @@ -97,11 +99,11 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState this.methodValidationConfiguration = new MethodValidationConfiguration.Builder() .allowOverridingMethodAlterParameterConstraint( - getAllowOverridingMethodAlterParameterConstraint( hibernateSpecificConfig, properties ) + determineAllowOverridingMethodAlterParameterConstraint( hibernateSpecificConfig, properties ) ).allowMultipleCascadedValidationOnReturnValues( - getAllowMultipleCascadedValidationOnReturnValues( hibernateSpecificConfig, properties ) + determineAllowMultipleCascadedValidationOnReturnValues( hibernateSpecificConfig, properties ) ).allowParallelMethodsDefineParameterConstraints( - getAllowParallelMethodsDefineParameterConstraints( hibernateSpecificConfig, properties ) + determineAllowParallelMethodsDefineParameterConstraints( hibernateSpecificConfig, properties ) ).build(); this.validatorFactoryScopedContext = new ValidatorFactoryScopedContext( @@ -109,11 +111,11 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState configurationState.getTraversableResolver(), new ExecutableParameterNameProvider( configurationState.getParameterNameProvider() ), configurationState.getClockProvider(), - ValidatorFactoryConfigurationHelper.getTemporalValidationTolerance( configurationState, properties ), - ValidatorFactoryConfigurationHelper.getScriptEvaluatorFactory( configurationState, properties, externalClassLoader ), - getFailFast( hibernateSpecificConfig, properties ), - getTraversableResolverResultCacheEnabled( hibernateSpecificConfig, properties ), - getConstraintValidatorPayload( hibernateSpecificConfig ) + determineTemporalValidationTolerance( configurationState, properties ), + determineScriptEvaluatorFactory( configurationState, properties, externalClassLoader ), + determineFailFast( hibernateSpecificConfig, properties ), + determineTraversableResolverResultCacheEnabled( hibernateSpecificConfig, properties ), + determineConstraintValidatorPayload( hibernateSpecificConfig ) ); this.constraintValidatorManager = new PredefinedScopeConstraintValidatorManagerImpl( @@ -123,7 +125,7 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState this.validationOrderGenerator = new ValidationOrderGenerator(); - this.getterPropertySelectionStrategy = ValidatorFactoryConfigurationHelper.getGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ); + this.getterPropertySelectionStrategy = ValidatorFactoryConfigurationHelper.determineGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ); this.valueExtractorManager = new ValueExtractorManager( configurationState.getValueExtractors() ); ConstraintHelper constraintHelper = new ConstraintHelper(); @@ -133,7 +135,7 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState constraintValidatorManager, typeResolutionHelper, valueExtractorManager ); ExecutableHelper executableHelper = new ExecutableHelper( typeResolutionHelper ); - JavaBeanHelper javaBeanHelper = new JavaBeanHelper( ValidatorFactoryConfigurationHelper.getGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ) ); + JavaBeanHelper javaBeanHelper = new JavaBeanHelper( ValidatorFactoryConfigurationHelper.determineGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ) ); // HV-302; don't load XmlMappingParser if not necessary XmlMetaDataProvider xmlMetaDataProvider; @@ -147,7 +149,7 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState } Set constraintMappings = Collections.unmodifiableSet( - getConstraintMappings( + determineConstraintMappings( typeResolutionHelper, configurationState, javaBeanHelper, diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java index 1e4d63ff24..a5dffbdf6b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java @@ -47,11 +47,11 @@ final class ValidatorFactoryConfigurationHelper { private ValidatorFactoryConfigurationHelper() { } - static ClassLoader getExternalClassLoader(ConfigurationState configurationState) { + static ClassLoader determineExternalClassLoader(ConfigurationState configurationState) { return ( configurationState instanceof ConfigurationImpl ) ? ( (ConfigurationImpl) configurationState ).getExternalClassLoader() : null; } - static Set getConstraintMappings(TypeResolutionHelper typeResolutionHelper, + static Set determineConstraintMappings(TypeResolutionHelper typeResolutionHelper, ConfigurationState configurationState, JavaBeanHelper javaBeanHelper, ClassLoader externalClassLoader) { Set constraintMappings = newHashSet(); @@ -73,7 +73,7 @@ static Set getConstraintMappings(TypeResolutionHelper } // XML-defined constraint mapping contributors - List contributors = getPropertyConfiguredConstraintMappingContributors( configurationState.getProperties(), + List contributors = determinePropertyConfiguredConstraintMappingContributors( configurationState.getProperties(), externalClassLoader ); for ( ConstraintMappingContributor contributor : contributors ) { @@ -104,7 +104,7 @@ static boolean checkPropertiesForBoolean(Map properties, String * * @return a list with property-configured {@link ConstraintMappingContributor}s; May be empty but never {@code null} */ - static List getPropertyConfiguredConstraintMappingContributors( + static List determinePropertyConfiguredConstraintMappingContributors( Map properties, ClassLoader externalClassLoader) { @SuppressWarnings("deprecation") String deprecatedPropertyValue = properties.get( HibernateValidatorConfiguration.CONSTRAINT_MAPPING_CONTRIBUTOR ); @@ -138,7 +138,7 @@ static List getPropertyConfiguredConstraintMapping return contributors; } - static boolean getAllowParallelMethodsDefineParameterConstraints(AbstractConfigurationImpl hibernateSpecificConfig, Map properties) { + static boolean determineAllowParallelMethodsDefineParameterConstraints(AbstractConfigurationImpl hibernateSpecificConfig, Map properties) { return checkPropertiesForBoolean( properties, HibernateValidatorConfiguration.ALLOW_PARALLEL_METHODS_DEFINE_PARAMETER_CONSTRAINTS, @@ -146,7 +146,7 @@ static boolean getAllowParallelMethodsDefineParameterConstraints(AbstractConfigu ); } - static boolean getAllowMultipleCascadedValidationOnReturnValues(AbstractConfigurationImpl hibernateSpecificConfig, Map properties) { + static boolean determineAllowMultipleCascadedValidationOnReturnValues(AbstractConfigurationImpl hibernateSpecificConfig, Map properties) { return checkPropertiesForBoolean( properties, HibernateValidatorConfiguration.ALLOW_MULTIPLE_CASCADED_VALIDATION_ON_RESULT, @@ -154,7 +154,7 @@ static boolean getAllowMultipleCascadedValidationOnReturnValues(AbstractConfigur ); } - static boolean getAllowOverridingMethodAlterParameterConstraint(AbstractConfigurationImpl hibernateSpecificConfig, Map properties) { + static boolean determineAllowOverridingMethodAlterParameterConstraint(AbstractConfigurationImpl hibernateSpecificConfig, Map properties) { return checkPropertiesForBoolean( properties, HibernateValidatorConfiguration.ALLOW_PARAMETER_CONSTRAINT_OVERRIDE, @@ -162,7 +162,7 @@ static boolean getAllowOverridingMethodAlterParameterConstraint(AbstractConfigur ); } - static boolean getTraversableResolverResultCacheEnabled(AbstractConfigurationImpl configuration, Map properties) { + static boolean determineTraversableResolverResultCacheEnabled(AbstractConfigurationImpl configuration, Map properties) { return checkPropertiesForBoolean( properties, HibernateValidatorConfiguration.ENABLE_TRAVERSABLE_RESOLVER_RESULT_CACHE, @@ -170,7 +170,7 @@ static boolean getTraversableResolverResultCacheEnabled(AbstractConfigurationImp ); } - static boolean getFailFast(AbstractConfigurationImpl configuration, Map properties) { + static boolean determineFailFast(AbstractConfigurationImpl configuration, Map properties) { // check whether fail fast is programmatically enabled boolean tmpFailFast = configuration != null ? configuration.getFailFast() : false; @@ -187,7 +187,7 @@ static boolean getFailFast(AbstractConfigurationImpl configuration, Map properties, + static ScriptEvaluatorFactory determineScriptEvaluatorFactory(ConfigurationState configurationState, Map properties, ClassLoader externalClassLoader) { if ( configurationState instanceof ConfigurationImpl ) { ConfigurationImpl hibernateSpecificConfig = (ConfigurationImpl) configurationState; @@ -217,7 +217,7 @@ static ScriptEvaluatorFactory getScriptEvaluatorFactory(ConfigurationState confi return new DefaultScriptEvaluatorFactory( externalClassLoader ); } - static Duration getTemporalValidationTolerance(ConfigurationState configurationState, Map properties) { + static Duration determineTemporalValidationTolerance(ConfigurationState configurationState, Map properties) { if ( configurationState instanceof ConfigurationImpl ) { ConfigurationImpl hibernateSpecificConfig = (ConfigurationImpl) configurationState; if ( hibernateSpecificConfig.getTemporalValidationTolerance() != null ) { @@ -240,7 +240,7 @@ static Duration getTemporalValidationTolerance(ConfigurationState configurationS return Duration.ZERO; } - static Object getConstraintValidatorPayload(ConfigurationState configurationState) { + static Object determineConstraintValidatorPayload(ConfigurationState configurationState) { if ( configurationState instanceof ConfigurationImpl ) { ConfigurationImpl hibernateSpecificConfig = (ConfigurationImpl) configurationState; if ( hibernateSpecificConfig.getConstraintValidatorPayload() != null ) { @@ -252,7 +252,7 @@ static Object getConstraintValidatorPayload(ConfigurationState configurationStat return null; } - static GetterPropertySelectionStrategy getGetterPropertySelectionStrategy(AbstractConfigurationImpl hibernateSpecificConfig, Map properties, + static GetterPropertySelectionStrategy determineGetterPropertySelectionStrategy(AbstractConfigurationImpl hibernateSpecificConfig, Map properties, ClassLoader externalClassLoader) { if ( hibernateSpecificConfig.getGetterPropertySelectionStrategy() != null ) { LOG.usingGetterPropertySelectionStrategy( hibernateSpecificConfig.getGetterPropertySelectionStrategy().getClass() ); @@ -343,6 +343,4 @@ public ConstraintMapping addConstraintMapping() { return mapping; } } - - } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java index 0cddf32457..a075136fd8 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java @@ -6,14 +6,16 @@ */ package org.hibernate.validator.internal.engine; -import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getAllowMultipleCascadedValidationOnReturnValues; -import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getAllowOverridingMethodAlterParameterConstraint; -import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getAllowParallelMethodsDefineParameterConstraints; -import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getConstraintMappings; -import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getConstraintValidatorPayload; -import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getExternalClassLoader; -import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getFailFast; -import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.getTraversableResolverResultCacheEnabled; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowMultipleCascadedValidationOnReturnValues; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowOverridingMethodAlterParameterConstraint; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowParallelMethodsDefineParameterConstraints; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineConstraintMappings; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineConstraintValidatorPayload; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineExternalClassLoader; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineFailFast; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineScriptEvaluatorFactory; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineTemporalValidationTolerance; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineTraversableResolverResultCacheEnabled; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.logValidatorFactoryScopedConfiguration; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.registerCustomConstraintValidators; import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; @@ -123,7 +125,7 @@ public class ValidatorFactoryImpl implements HibernateValidatorFactory { private final ValidationOrderGenerator validationOrderGenerator; public ValidatorFactoryImpl(ConfigurationState configurationState) { - ClassLoader externalClassLoader = getExternalClassLoader( configurationState ); + ClassLoader externalClassLoader = determineExternalClassLoader( configurationState ); ConfigurationImpl hibernateSpecificConfig = null; if ( configurationState instanceof ConfigurationImpl ) { @@ -134,11 +136,11 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { this.methodValidationConfiguration = new MethodValidationConfiguration.Builder() .allowOverridingMethodAlterParameterConstraint( - getAllowOverridingMethodAlterParameterConstraint( hibernateSpecificConfig, properties ) + determineAllowOverridingMethodAlterParameterConstraint( hibernateSpecificConfig, properties ) ).allowMultipleCascadedValidationOnReturnValues( - getAllowMultipleCascadedValidationOnReturnValues( hibernateSpecificConfig, properties ) + determineAllowMultipleCascadedValidationOnReturnValues( hibernateSpecificConfig, properties ) ).allowParallelMethodsDefineParameterConstraints( - getAllowParallelMethodsDefineParameterConstraints( hibernateSpecificConfig, properties ) + determineAllowParallelMethodsDefineParameterConstraints( hibernateSpecificConfig, properties ) ).build(); this.validatorFactoryScopedContext = new ValidatorFactoryScopedContext( @@ -146,11 +148,11 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { configurationState.getTraversableResolver(), new ExecutableParameterNameProvider( configurationState.getParameterNameProvider() ), configurationState.getClockProvider(), - ValidatorFactoryConfigurationHelper.getTemporalValidationTolerance( configurationState, properties ), - ValidatorFactoryConfigurationHelper.getScriptEvaluatorFactory( configurationState, properties, externalClassLoader ), - getFailFast( hibernateSpecificConfig, properties ), - getTraversableResolverResultCacheEnabled( hibernateSpecificConfig, properties ), - getConstraintValidatorPayload( hibernateSpecificConfig ) + determineTemporalValidationTolerance( configurationState, properties ), + determineScriptEvaluatorFactory( configurationState, properties, externalClassLoader ), + determineFailFast( hibernateSpecificConfig, properties ), + determineTraversableResolverResultCacheEnabled( hibernateSpecificConfig, properties ), + determineConstraintValidatorPayload( hibernateSpecificConfig ) ); ConstraintValidatorManager constraintValidatorManager = new ConstraintValidatorManagerImpl( @@ -167,7 +169,7 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { this.constraintCreationContext = new ConstraintCreationContext( constraintHelper, constraintValidatorManager, typeResolutionHelper, valueExtractorManager ); this.executableHelper = new ExecutableHelper( typeResolutionHelper ); - this.javaBeanHelper = new JavaBeanHelper( ValidatorFactoryConfigurationHelper.getGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ) ); + this.javaBeanHelper = new JavaBeanHelper( ValidatorFactoryConfigurationHelper.determineGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ) ); // HV-302; don't load XmlMappingParser if not necessary if ( configurationState.getMappingStreams().isEmpty() ) { @@ -178,7 +180,7 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { } this.constraintMappings = Collections.unmodifiableSet( - getConstraintMappings( + determineConstraintMappings( typeResolutionHelper, configurationState, javaBeanHelper, From 80b4be4ad7d5257abf270cd648a2429b1b04f504 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 10 Dec 2018 14:39:38 +0100 Subject: [PATCH 145/393] HV-1667 Add a consistency check in PredefinedScopeValidatorFactoryImpl --- .../internal/engine/PredefinedScopeValidatorFactoryImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java index 9282f3952d..1566de54a2 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java @@ -50,6 +50,7 @@ import org.hibernate.validator.internal.metadata.provider.ProgrammaticMetaDataProvider; import org.hibernate.validator.internal.metadata.provider.XmlMetaDataProvider; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; +import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.TypeResolutionHelper; @@ -91,6 +92,8 @@ public class PredefinedScopeValidatorFactoryImpl implements PredefinedScopeHiber private final ValidationOrderGenerator validationOrderGenerator; public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState) { + Contracts.assertTrue( configurationState instanceof PredefinedScopeConfigurationImpl, "Only PredefinedScopeConfigurationImpl is supported." ); + ClassLoader externalClassLoader = determineExternalClassLoader( configurationState ); PredefinedScopeConfigurationImpl hibernateSpecificConfig = (PredefinedScopeConfigurationImpl) configurationState; From 7554f23c1d71ca5bfe3c68606face3b844f69d86 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 30 Nov 2018 14:26:33 +0100 Subject: [PATCH 146/393] HV-1670 Add the ability to preload a set of locales --- ...dScopeHibernateValidatorConfiguration.java | 4 + .../engine/AbstractConfigurationImpl.java | 26 +++-- .../PredefinedScopeConfigurationImpl.java | 7 ++ .../validator/internal/util/logging/Log.java | 5 +- .../AbstractMessageInterpolator.java | 76 +++++++++++++- .../ParameterMessageInterpolator.java | 10 ++ .../ResourceBundleMessageInterpolator.java | 56 +++++++++-- .../AggregateResourceBundleLocator.java | 78 +++++++++++++-- .../PlatformResourceBundleLocator.java | 98 +++++++++++++++++-- .../PredefinedScopeValidatorFactoryTest.java | 71 ++++++++++++++ 10 files changed, 391 insertions(+), 40 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java index 3e9e6b0381..72a9d9809a 100644 --- a/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java @@ -6,6 +6,7 @@ */ package org.hibernate.validator; +import java.util.Locale; import java.util.Set; /** @@ -21,4 +22,7 @@ public interface PredefinedScopeHibernateValidatorConfiguration extends BaseHibe @Incubating PredefinedScopeHibernateValidatorConfiguration initializeBeanMetaData(Set> beanClassesToInitialize); + + @Incubating + PredefinedScopeHibernateValidatorConfiguration initializeLocales(Set locales); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java index 728db7c919..d0152a8254 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java @@ -16,8 +16,10 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.time.Duration; +import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -77,11 +79,11 @@ public abstract class AbstractConfigurationImpl localesToInitialize = Collections.emptySet(); + protected AbstractConfigurationImpl(BootstrapState state) { this(); if ( state.getValidationProviderResolver() == null ) { @@ -131,9 +136,6 @@ protected AbstractConfigurationImpl(ValidationProvider provider) { private AbstractConfigurationImpl() { this.validationBootstrapParameters = new ValidationBootstrapParameters(); - this.defaultResourceBundleLocator = new PlatformResourceBundleLocator( - ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES - ); this.defaultTraversableResolver = TraversableResolvers.getDefault(); this.defaultConstraintValidatorFactory = new ConstraintValidatorFactoryImpl(); this.defaultParameterNameProvider = new DefaultParameterNameProvider(); @@ -496,7 +498,7 @@ public ClassLoader getExternalClassLoader() { @Override public final MessageInterpolator getDefaultMessageInterpolator() { if ( defaultMessageInterpolator == null ) { - defaultMessageInterpolator = new ResourceBundleMessageInterpolator( defaultResourceBundleLocator ); + defaultMessageInterpolator = new ResourceBundleMessageInterpolator( getDefaultResourceBundleLocator(), localesToInitialize ); } return defaultMessageInterpolator; @@ -514,6 +516,11 @@ public final ConstraintValidatorFactory getDefaultConstraintValidatorFactory() { @Override public final ResourceBundleLocator getDefaultResourceBundleLocator() { + if ( defaultResourceBundleLocator == null ) { + defaultResourceBundleLocator = new PlatformResourceBundleLocator( + ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, localesToInitialize ); + } + return defaultResourceBundleLocator; } @@ -648,10 +655,12 @@ private MessageInterpolator getDefaultMessageInterpolatorConfiguredWithClassLoad if ( externalClassLoader != null ) { PlatformResourceBundleLocator userResourceBundleLocator = new PlatformResourceBundleLocator( ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, + localesToInitialize, externalClassLoader ); PlatformResourceBundleLocator contributorResourceBundleLocator = new PlatformResourceBundleLocator( ResourceBundleMessageInterpolator.CONTRIBUTOR_VALIDATION_MESSAGES, + localesToInitialize, externalClassLoader, true ); @@ -664,7 +673,8 @@ private MessageInterpolator getDefaultMessageInterpolatorConfiguredWithClassLoad run( SetContextClassLoader.action( externalClassLoader ) ); return new ResourceBundleMessageInterpolator( userResourceBundleLocator, - contributorResourceBundleLocator + contributorResourceBundleLocator, + localesToInitialize ); } finally { @@ -676,6 +686,10 @@ private MessageInterpolator getDefaultMessageInterpolatorConfiguredWithClassLoad } } + protected void setLocalesToInitialize(Set localesToInitialize) { + this.localesToInitialize = localesToInitialize; + } + @SuppressWarnings("unchecked") protected T thisAsT() { return (T) this; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java index dde4fa0e56..248f311c31 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java @@ -6,6 +6,7 @@ */ package org.hibernate.validator.internal.engine; +import java.util.Locale; import java.util.Set; import javax.validation.spi.BootstrapState; @@ -40,4 +41,10 @@ public PredefinedScopeHibernateValidatorConfiguration initializeBeanMetaData(Set public Set> getBeanClassesToInitialize() { return beanClassesToInitialize; } + + @Override + public PredefinedScopeHibernateValidatorConfiguration initializeLocales(Set locales) { + setLocalesToInitialize( CollectionHelper.toImmutableSet( locales ) ); + return thisAsT(); + } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 928262bd27..c1043b0cc3 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -20,6 +20,7 @@ import java.time.Duration; import java.util.Collection; import java.util.List; +import java.util.Locale; import java.util.Set; import java.util.regex.PatternSyntaxException; @@ -64,7 +65,6 @@ import org.hibernate.validator.spi.scripting.ScriptEvaluationException; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; import org.hibernate.validator.spi.scripting.ScriptEvaluatorNotFoundException; - import org.jboss.logging.BasicLogger; import org.jboss.logging.annotations.Cause; import org.jboss.logging.annotations.FormatWith; @@ -878,4 +878,7 @@ ConstraintDefinitionException getConstraintValidatorDefinitionConstraintMismatch @Message(id = 249, value = "Uninitialized bean metadata for class: %s. Please register your bean class as a class to initialize when initializing your ValidatorFactory.") ValidationException uninitializedBeanMetaData(@FormatWith(ClassObjectFormatter.class) Class clazz); + + @Message(id = 250, value = "Uninitialized locale: %s. Please register your locale as a locale to initialize when initializing your ValidatorFactory.") + ValidationException uninitializedLocale(Locale locale); } diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java index 7830f2935e..39aa6a0f71 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java @@ -9,11 +9,13 @@ import static org.hibernate.validator.internal.util.ConcurrentReferenceHashMap.ReferenceType.SOFT; import java.lang.invoke.MethodHandles; +import java.util.Collections; import java.util.EnumSet; import java.util.List; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -40,6 +42,7 @@ * @author Gunnar Morling * @author Adam Stawicki * @author Marko Bekhta + * @author Guillaume Smet * * @since 5.2 */ @@ -124,12 +127,20 @@ public abstract class AbstractMessageInterpolator implements MessageInterpolator private static final Pattern SLASH = Pattern.compile( "\\\\", Pattern.LITERAL ); private static final Pattern DOLLAR = Pattern.compile( "\\$", Pattern.LITERAL ); + /** + * {@code MessageInterpolator} using the default resource bundle locators. + */ public AbstractMessageInterpolator() { - this( null ); + this( Collections.emptySet() ); } + /** + * {@code MessageInterpolator} taking a resource bundle locator. + * + * @param userResourceBundleLocator {@code ResourceBundleLocator} used to load user provided resource bundle + */ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator) { - this( userResourceBundleLocator, null ); + this( userResourceBundleLocator, Collections.emptySet() ); } /** @@ -141,7 +152,7 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat */ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator) { - this( userResourceBundleLocator, contributorResourceBundleLocator, true ); + this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet() ); } /** @@ -155,10 +166,64 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator, boolean cacheMessages) { + this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), cacheMessages ); + } + + /** + * {@code MessageInterpolator} using the default resource bundle locators. + * + * @param localesToInitialize The set of locales to initialize at bootstrap. + * + * @since 6.1 + */ + public AbstractMessageInterpolator(Set localesToInitialize) { + this( null, localesToInitialize ); + } + + /** + * {@code MessageInterpolator} taking a resource bundle locator. + * + * @param userResourceBundleLocator {@code ResourceBundleLocator} used to load user provided resource bundle + * @param localesToInitialize The set of locales to initialize at bootstrap. + * + * @since 6.1 + */ + public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, Set localesToInitialize) { + this( userResourceBundleLocator, null, localesToInitialize ); + } + + /** + * {@code MessageInterpolator} taking two resource bundle locators. + * + * @param userResourceBundleLocator {@code ResourceBundleLocator} used to load user provided resource bundle + * @param contributorResourceBundleLocator {@code ResourceBundleLocator} used to load resource bundle of constraint contributor + * @param localesToInitialize The set of locales to initialize at bootstrap. + * + * @since 6.1 + */ + public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, + ResourceBundleLocator contributorResourceBundleLocator, Set localesToInitialize) { + this( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize, true ); + } + + /** + * {@code MessageInterpolator} taking two resource bundle locators. + * + * @param userResourceBundleLocator {@code ResourceBundleLocator} used to load user provided resource bundle + * @param contributorResourceBundleLocator {@code ResourceBundleLocator} used to load resource bundle of constraint contributor + * @param localesToInitialize The set of locales to initialize at bootstrap. + * @param cacheMessages Whether resolved messages should be cached or not. + * + * @since 6.1 + */ + public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, + ResourceBundleLocator contributorResourceBundleLocator, + Set localesToInitialize, + boolean cacheMessages) { defaultLocale = Locale.getDefault(); if ( userResourceBundleLocator == null ) { - this.userResourceBundleLocator = new PlatformResourceBundleLocator( USER_VALIDATION_MESSAGES ); + this.userResourceBundleLocator = new PlatformResourceBundleLocator( USER_VALIDATION_MESSAGES, localesToInitialize ); } else { this.userResourceBundleLocator = userResourceBundleLocator; @@ -167,6 +232,7 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat if ( contributorResourceBundleLocator == null ) { this.contributorResourceBundleLocator = new PlatformResourceBundleLocator( CONTRIBUTOR_VALIDATION_MESSAGES, + localesToInitialize, null, true ); @@ -175,7 +241,7 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat this.contributorResourceBundleLocator = contributorResourceBundleLocator; } - this.defaultResourceBundleLocator = new PlatformResourceBundleLocator( DEFAULT_VALIDATION_MESSAGES ); + this.defaultResourceBundleLocator = new PlatformResourceBundleLocator( DEFAULT_VALIDATION_MESSAGES, localesToInitialize ); this.cachingEnabled = cacheMessages; if ( cachingEnabled ) { diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java index dad9705907..ba260bab17 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java @@ -7,7 +7,9 @@ package org.hibernate.validator.messageinterpolation; import java.lang.invoke.MethodHandles; +import java.util.Collections; import java.util.Locale; +import java.util.Set; import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTerm; import org.hibernate.validator.internal.engine.messageinterpolation.ParameterTermResolver; @@ -25,6 +27,14 @@ public class ParameterMessageInterpolator extends AbstractMessageInterpolator { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + public ParameterMessageInterpolator() { + this( Collections.emptySet() ); + } + + public ParameterMessageInterpolator(Set localesToInitialize) { + super( localesToInitialize ); + } + @Override public String interpolate(Context context, Locale locale, String term) { if ( InterpolationTerm.isElExpression( term ) ) { diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java index 856f3f12bf..d69c88eb2f 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java @@ -9,7 +9,9 @@ import java.lang.invoke.MethodHandles; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.Collections; import java.util.Locale; +import java.util.Set; import javax.el.ELManager; import javax.el.ExpressionFactory; @@ -38,35 +40,69 @@ public class ResourceBundleMessageInterpolator extends AbstractMessageInterpolat private final ExpressionFactory expressionFactory; public ResourceBundleMessageInterpolator() { - super(); - this.expressionFactory = buildExpressionFactory(); + this( Collections.emptySet() ); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator) { - super( userResourceBundleLocator ); - this.expressionFactory = buildExpressionFactory(); + this( userResourceBundleLocator, Collections.emptySet() ); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator) { - super( userResourceBundleLocator, contributorResourceBundleLocator ); + this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet() ); + } + + public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, + ResourceBundleLocator contributorResourceBundleLocator, + boolean cachingEnabled) { + this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), cachingEnabled ); + } + + public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, boolean cachingEnabled) { + this( userResourceBundleLocator, null, Collections.emptySet(), cachingEnabled ); + } + + public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, + boolean cachingEnabled, + ExpressionFactory expressionFactory) { + this( userResourceBundleLocator, null, Collections.emptySet(), cachingEnabled ); + } + + public ResourceBundleMessageInterpolator(Set localesToInitialize) { + super( localesToInitialize ); + this.expressionFactory = buildExpressionFactory(); + } + + public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, Set localesToInitialize) { + super( userResourceBundleLocator, localesToInitialize ); + this.expressionFactory = buildExpressionFactory(); + } + + public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, + ResourceBundleLocator contributorResourceBundleLocator, + Set localesToInitialize) { + super( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize ); this.expressionFactory = buildExpressionFactory(); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator, + Set localesToInitialize, boolean cachingEnabled) { - super( userResourceBundleLocator, contributorResourceBundleLocator, cachingEnabled ); + super( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize, cachingEnabled ); this.expressionFactory = buildExpressionFactory(); } - public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, boolean cachingEnabled) { - super( userResourceBundleLocator, null, cachingEnabled ); + public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, Set localesToInitialize, boolean cachingEnabled) { + super( userResourceBundleLocator, null, localesToInitialize, cachingEnabled ); this.expressionFactory = buildExpressionFactory(); } - public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, boolean cachingEnabled, ExpressionFactory expressionFactory) { - super( userResourceBundleLocator, null, cachingEnabled ); + public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, + Set localesToInitialize, + boolean cachingEnabled, + ExpressionFactory expressionFactory) { + super( userResourceBundleLocator, null, localesToInitialize, cachingEnabled ); this.expressionFactory = expressionFactory; } diff --git a/engine/src/main/java/org/hibernate/validator/resourceloading/AggregateResourceBundleLocator.java b/engine/src/main/java/org/hibernate/validator/resourceloading/AggregateResourceBundleLocator.java index f9360c1caf..daae9fa6fb 100644 --- a/engine/src/main/java/org/hibernate/validator/resourceloading/AggregateResourceBundleLocator.java +++ b/engine/src/main/java/org/hibernate/validator/resourceloading/AggregateResourceBundleLocator.java @@ -7,6 +7,7 @@ package org.hibernate.validator.resourceloading; import java.util.ArrayList; +import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; @@ -14,6 +15,7 @@ import java.util.Locale; import java.util.Map; import java.util.ResourceBundle; +import java.util.Set; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.Contracts; @@ -27,8 +29,8 @@ * @author Gunnar Morling */ public class AggregateResourceBundleLocator extends DelegatingResourceBundleLocator { - private final List bundleNames; - private final ClassLoader classLoader; + + private final List resourceBundleLocators; /** * Creates a locator that delivers a resource bundle merged from the given @@ -40,7 +42,7 @@ public class AggregateResourceBundleLocator extends DelegatingResourceBundleLoca * first bundle containing the key. */ public AggregateResourceBundleLocator(List bundleNames) { - this( bundleNames, null ); + this( bundleNames, Collections.emptySet(), null ); } /** @@ -56,7 +58,7 @@ public AggregateResourceBundleLocator(List bundleNames) { * source bundles. */ public AggregateResourceBundleLocator(List bundleNames, ResourceBundleLocator delegate) { - this( bundleNames, delegate, null ); + this( bundleNames, Collections.emptySet(), delegate, null ); } /** @@ -75,21 +77,77 @@ public AggregateResourceBundleLocator(List bundleNames, ResourceBundleLo */ public AggregateResourceBundleLocator(List bundleNames, ResourceBundleLocator delegate, ClassLoader classLoader) { + this( bundleNames, Collections.emptySet(), delegate, classLoader ); + } + + /** + * Creates a locator that delivers a resource bundle merged from the given + * list of source bundles. + * + * @param bundleNames A list with source bundle names. The returned bundle will + * contain all entries from all source bundles. In case a key occurs + * in multiple source bundles, the value will be taken from the + * first bundle containing the key. + * @param localesToInitialize The set of locales to initialize at bootstrap. + * + * @since 6.1 + */ + public AggregateResourceBundleLocator(List bundleNames, Set localesToInitialize) { + this( bundleNames, localesToInitialize, null ); + } + + /** + * Creates a locator that delivers a resource bundle merged from the given + * list of source bundles. + * + * @param bundleNames A list with source bundle names. The returned bundle will + * contain all keys from all source bundles. In case a key occurs + * in multiple source bundles, the value will be taken from the + * first bundle containing the key. + * @param localesToInitialize The set of locales to initialize at bootstrap. + * @param delegate A delegate resource bundle locator. The bundle returned by + * this locator will be added to the aggregate bundle after all + * source bundles. + * + * @since 6.1 + */ + public AggregateResourceBundleLocator(List bundleNames, Set localesToInitialize, ResourceBundleLocator delegate) { + this( bundleNames, localesToInitialize, delegate, null ); + } + + /** + * Creates a locator that delivers a resource bundle merged from the given + * list of source bundles. + * + * @param bundleNames A list with source bundle names. The returned bundle will + * contain all keys from all source bundles. In case a key occurs + * in multiple source bundles, the value will be taken from the + * first bundle containing the key. + * @param localesToInitialize The set of locales to initialize at bootstrap. + * @param delegate A delegate resource bundle locator. The bundle returned by + * this locator will be added to the aggregate bundle after all + * source bundles. + * @param classLoader The classloader to use for loading the bundle. + * + * @since 6.1 + */ + public AggregateResourceBundleLocator(List bundleNames, Set localesToInitialize, ResourceBundleLocator delegate, + ClassLoader classLoader) { super( delegate ); Contracts.assertValueNotNull( bundleNames, "bundleNames" ); - this.bundleNames = CollectionHelper.toImmutableList( bundleNames ); - this.classLoader = classLoader; + List tmpBundleLocators = new ArrayList<>( bundleNames.size() ); + for ( String bundleName : bundleNames ) { + tmpBundleLocators.add( new PlatformResourceBundleLocator( bundleName, localesToInitialize, classLoader ) ); + } + this.resourceBundleLocators = CollectionHelper.toImmutableList( tmpBundleLocators ); } @Override public ResourceBundle getResourceBundle(Locale locale) { List sourceBundles = new ArrayList(); - for ( String bundleName : bundleNames ) { - ResourceBundleLocator resourceBundleLocator = - new PlatformResourceBundleLocator( bundleName, classLoader ); - + for ( PlatformResourceBundleLocator resourceBundleLocator : resourceBundleLocators ) { ResourceBundle resourceBundle = resourceBundleLocator.getResourceBundle( locale ); if ( resourceBundle != null ) { diff --git a/engine/src/main/java/org/hibernate/validator/resourceloading/PlatformResourceBundleLocator.java b/engine/src/main/java/org/hibernate/validator/resourceloading/PlatformResourceBundleLocator.java index 2ba6139324..b757c5ea1a 100644 --- a/engine/src/main/java/org/hibernate/validator/resourceloading/PlatformResourceBundleLocator.java +++ b/engine/src/main/java/org/hibernate/validator/resourceloading/PlatformResourceBundleLocator.java @@ -10,6 +10,7 @@ import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES; import java.io.IOException; +import java.lang.invoke.MethodHandles; import java.lang.reflect.Method; import java.net.URL; import java.security.AccessController; @@ -17,17 +18,21 @@ import java.util.Collections; import java.util.Enumeration; import java.util.Locale; +import java.util.Map; import java.util.MissingResourceException; import java.util.Properties; import java.util.ResourceBundle; import java.util.Set; +import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.Contracts; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader; import org.hibernate.validator.internal.util.privilegedactions.GetMethod; import org.hibernate.validator.internal.util.privilegedactions.GetResources; +import org.hibernate.validator.internal.util.stereotypes.Immutable; import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; -import org.jboss.logging.Logger; /** * A resource bundle locator, that loads resource bundles by invoking {@code ResourceBundle.loadBundle(String, Local, ClassLoader)}. @@ -40,15 +45,23 @@ */ public class PlatformResourceBundleLocator implements ResourceBundleLocator { - private static final Logger log = Logger.getLogger( PlatformResourceBundleLocator.class.getName() ); + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); private static final boolean RESOURCE_BUNDLE_CONTROL_INSTANTIABLE = determineAvailabilityOfResourceBundleControl(); private final String bundleName; private final ClassLoader classLoader; private final boolean aggregate; + @Immutable + private final Map preloadedResourceBundles; + + /** + * Creates a new {@link PlatformResourceBundleLocator}. + * + * @param bundleName the name of the bundle to load + */ public PlatformResourceBundleLocator(String bundleName) { - this( bundleName, null ); + this( bundleName, Collections.emptySet() ); } /** @@ -62,7 +75,7 @@ public PlatformResourceBundleLocator(String bundleName) { * @since 5.2 */ public PlatformResourceBundleLocator(String bundleName, ClassLoader classLoader) { - this( bundleName, classLoader, false ); + this( bundleName, Collections.emptySet(), classLoader ); } /** @@ -77,12 +90,66 @@ public PlatformResourceBundleLocator(String bundleName, ClassLoader classLoader) * @since 5.2 */ public PlatformResourceBundleLocator(String bundleName, ClassLoader classLoader, boolean aggregate) { + this( bundleName, Collections.emptySet(), classLoader, aggregate ); + } + + /** + * Creates a new {@link PlatformResourceBundleLocator}. + * + * @param bundleName the name of the bundle to load + * @param localesToInitialize the set of locales to initialize at bootstrap. + * + * @since 6.1 + */ + public PlatformResourceBundleLocator(String bundleName, Set localesToInitialize) { + this( bundleName, localesToInitialize, null ); + } + + /** + * Creates a new {@link PlatformResourceBundleLocator}. + * + * @param bundleName the name of the bundle to load + * @param localesToInitialize the set of locales to initialize at bootstrap. + * @param classLoader the classloader to be used for loading the bundle. If {@code null}, the current thread context + * classloader and finally Hibernate Validator's own classloader will be used for loading the specified + * bundle. + * + * @since 6.1 + */ + public PlatformResourceBundleLocator(String bundleName, Set localesToInitialize, ClassLoader classLoader) { + this( bundleName, localesToInitialize, classLoader, false ); + } + + /** + * Creates a new {@link PlatformResourceBundleLocator}. + * + * @param bundleName the name of the bundle to load + * @param localesToInitialize the set of locales to initialize at bootstrap. + * @param classLoader the classloader to be used for loading the bundle. If {@code null}, the current thread context + * classloader and finally Hibernate Validator's own classloader will be used for loading the specified + * bundle. + * @param aggregate Whether or not all resource bundles of a given name should be loaded and potentially merged. + * + * @since 6.1 + */ + public PlatformResourceBundleLocator(String bundleName, Set localesToInitialize, ClassLoader classLoader, boolean aggregate) { Contracts.assertNotNull( bundleName, "bundleName" ); this.bundleName = bundleName; this.classLoader = classLoader; this.aggregate = aggregate && RESOURCE_BUNDLE_CONTROL_INSTANTIABLE; + + if ( !localesToInitialize.isEmpty() ) { + Map tmpPreloadedResourceBundles = CollectionHelper.newHashMap( localesToInitialize.size() ); + for ( Locale localeToPreload : localesToInitialize ) { + tmpPreloadedResourceBundles.put( localeToPreload, doGetResourceBundle( localeToPreload ) ); + } + this.preloadedResourceBundles = CollectionHelper.toImmutableMap( tmpPreloadedResourceBundles ); + } + else { + this.preloadedResourceBundles = Collections.emptyMap(); + } } /** @@ -95,6 +162,21 @@ public PlatformResourceBundleLocator(String bundleName, ClassLoader classLoader, */ @Override public ResourceBundle getResourceBundle(Locale locale) { + // we are in the preloading case + if ( !preloadedResourceBundles.isEmpty() ) { + // we need to use containsKey() as the cached resource bundle can be null + if ( preloadedResourceBundles.containsKey( locale ) ) { + return preloadedResourceBundles.get( locale ); + } + else { + throw LOG.uninitializedLocale( locale ); + } + } + + return doGetResourceBundle( locale ); + } + + private ResourceBundle doGetResourceBundle(Locale locale) { ResourceBundle rb = null; if ( classLoader != null ) { @@ -122,10 +204,10 @@ public ResourceBundle getResourceBundle(Locale locale) { ); } if ( rb != null ) { - log.debugf( "%s found.", bundleName ); + LOG.debugf( "%s found.", bundleName ); } else { - log.debugf( "%s not found.", bundleName ); + LOG.debugf( "%s not found.", bundleName ); } return rb; } @@ -150,7 +232,7 @@ private ResourceBundle loadBundle(ClassLoader classLoader, Locale locale, String } } catch (MissingResourceException e) { - log.trace( message ); + LOG.trace( message ); } return rb; } @@ -202,7 +284,7 @@ private static boolean determineAvailabilityOfResourceBundleControl() { return !isNamed; } catch (Throwable e) { - log.info( MESSAGES.unableToUseResourceBundleAggregation() ); + LOG.info( MESSAGES.unableToUseResourceBundleAggregation() ); return false; } } diff --git a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java index 2093841994..bd6eaab0d8 100644 --- a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java @@ -11,7 +11,9 @@ import static org.hibernate.validator.testutil.ConstraintViolationAssert.pathWith; import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; +import java.util.Collections; import java.util.HashSet; +import java.util.Locale; import java.util.Set; import javax.validation.ConstraintViolation; @@ -125,6 +127,62 @@ public void testValidationOnUnknownBeanConstructorReturnValue() throws NoSuchMet assertNoViolations( violations ); } + @Test + public void testExistingInitializedLocale() { + Locale defaultLocale = Locale.getDefault(); + + try { + Locale.setDefault( Locale.FRANCE ); + + Validator validator = getValidatorWithInitializedLocale( Locale.FRANCE ); + + Set> violations = validator.validate( new Bean( "", "invalid" ) ); + assertThat( violations ).containsOnlyViolations( + violationOf( Email.class ).withProperty( "email" ).withMessage( "doit être une adresse email bien formée" ) ); + } + finally { + Locale.setDefault( defaultLocale ); + } + } + + @Test + public void testUnavailableInitializedLocale() { + Locale defaultLocale = Locale.getDefault(); + + try { + Locale georgianLocale = new Locale( "ka", "GE" ); + + Locale.setDefault( georgianLocale ); + + Validator validator = getValidatorWithInitializedLocale( georgianLocale ); + + Set> violations = validator.validate( new Bean( "", "invalid" ) ); + assertThat( violations ).containsOnlyViolations( + violationOf( Email.class ).withProperty( "email" ).withMessage( "must be a well-formed email address" ) ); + } + finally { + Locale.setDefault( defaultLocale ); + } + } + + @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000250:.*") + public void testUninitializedLocale() { + Locale defaultLocale = Locale.getDefault(); + + try { + Locale.setDefault( Locale.FRANCE ); + + Validator validator = getValidatorWithInitializedLocale( Locale.ENGLISH ); + + Set> violations = validator.validate( new Bean( "", "invalid" ) ); + assertThat( violations ).containsOnlyViolations( + violationOf( Email.class ).withProperty( "email" ).withMessage( "doit être une adresse email bien formée" ) ); + } + finally { + Locale.setDefault( defaultLocale ); + } + } + private static Validator getValidator() { Set> beanMetaDataToInitialize = new HashSet<>(); beanMetaDataToInitialize.add( Bean.class ); @@ -137,6 +195,19 @@ private static Validator getValidator() { return validatorFactory.getValidator(); } + private static Validator getValidatorWithInitializedLocale(Locale locale) { + Set> beanMetaDataToInitialize = new HashSet<>(); + beanMetaDataToInitialize.add( Bean.class ); + + ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) + .configure() + .initializeBeanMetaData( beanMetaDataToInitialize ) + .initializeLocales( Collections.singleton( locale ) ) + .buildValidatorFactory(); + + return validatorFactory.getValidator(); + } + private static class Bean { @NotNull From e590ac9eff6fe1d4ba0978fb8b13af93db07bdc5 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Mon, 10 Dec 2018 12:21:19 +0000 Subject: [PATCH 147/393] HV-1677 Allow for an explicit environment variable to disable the JavaFX extensions --- .../ValueExtractorManager.java | 26 ++++++++++++++++++- tck-runner/src/test/resources/test.policy | 2 ++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorManager.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorManager.java index e872ac57ab..af427ff571 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorManager.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorManager.java @@ -36,10 +36,16 @@ public class ValueExtractorManager { @Immutable public static final Set SPEC_DEFINED_EXTRACTORS; + /** + * Set this environment variable to true to ensure the JavaFX integrations are disabled. + * Normally the JavaFX extensions are enabled if and only if JavaFX is found on classpath. + */ + private static final String HIBERNATE_VALIDATOR_FORCE_DISABLE_JAVAFX_INTEGRATION = "org.hibernate.validator.force-disable-javafx-integration"; + static { LinkedHashSet specDefinedExtractors = new LinkedHashSet<>(); - if ( isJavaFxInClasspath() ) { + if ( isJavaFxExtensionsEnabled() ) { specDefinedExtractors.add( ObservableValueValueExtractor.DESCRIPTOR ); specDefinedExtractors.add( ListPropertyValueExtractor.DESCRIPTOR ); specDefinedExtractors.add( ReadOnlyListPropertyValueExtractor.DESCRIPTOR ); @@ -177,6 +183,24 @@ public boolean equals(Object obj) { return registeredValueExtractors.equals( other.registeredValueExtractors ); } + private static boolean isJavaFxExtensionsEnabled() { + if ( isJavaFxForcefullyDisabled() ) { + return false; + } + else { + return isJavaFxInClasspath(); + } + } + + private static boolean isJavaFxForcefullyDisabled() { + return run( new PrivilegedAction() { + @Override + public Boolean run() { + return Boolean.valueOf( Boolean.getBoolean( HIBERNATE_VALIDATOR_FORCE_DISABLE_JAVAFX_INTEGRATION ) ); + } + } ); + } + private static boolean isJavaFxInClasspath() { return isClassPresent( "javafx.beans.value.ObservableValue", false ); } diff --git a/tck-runner/src/test/resources/test.policy b/tck-runner/src/test/resources/test.policy index 61b629f5db..c9026319dc 100644 --- a/tck-runner/src/test/resources/test.policy +++ b/tck-runner/src/test/resources/test.policy @@ -27,6 +27,7 @@ grant codeBase "file:${localRepository}/org/hibernate/validator/hibernate-valida permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; permission java.lang.RuntimePermission "accessDeclaredMembers"; permission java.lang.RuntimePermission "setContextClassLoader"; + permission java.util.PropertyPermission "org.hibernate.validator.force-disable-javafx-integration", "read"; permission org.hibernate.validator.HibernateValidatorPermission "accessPrivateMembers"; @@ -38,6 +39,7 @@ grant codeBase "file:${basedir}/../engine/target/hibernate-validator-${project.v permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; permission java.lang.RuntimePermission "accessDeclaredMembers"; permission java.lang.RuntimePermission "setContextClassLoader"; + permission java.util.PropertyPermission "org.hibernate.validator.force-disable-javafx-integration", "read"; permission org.hibernate.validator.HibernateValidatorPermission "accessPrivateMembers"; From c5bb144ffa68af1307924c3120e701d449d555b8 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 10 Dec 2018 18:07:48 +0100 Subject: [PATCH 148/393] HV-1667 Some additional ConstraintTree clean up --- .../constraintvalidation/ConstraintTree.java | 36 +++++-------------- .../ConstraintValidatorManager.java | 14 -------- .../ConstraintValidatorManagerImpl.java | 14 ++++++++ 3 files changed, 23 insertions(+), 41 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java index 22c7970548..c091d85f8d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java @@ -6,8 +6,6 @@ */ package org.hibernate.validator.internal.engine.constraintvalidation; -import static org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager.DUMMY_CONSTRAINT_VALIDATOR; - import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandles; import java.lang.reflect.Type; @@ -18,10 +16,8 @@ import javax.validation.ConstraintDeclarationException; import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorFactory; import javax.validation.ValidationException; -import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; import org.hibernate.validator.internal.engine.ValueContext; import org.hibernate.validator.internal.engine.validationcontext.ValidationContext; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; @@ -56,7 +52,8 @@ protected ConstraintTree(ConstraintValidatorManager constraintValidatorManager, this.descriptor = descriptor; this.validatedValueType = validatedValueType; - this.defaultInitializedConstraintValidator = getInitializedConstraintValidator( constraintValidatorManager, + this.defaultInitializedConstraintValidator = constraintValidatorManager.getInitializedValidator( validatedValueType, + descriptor, constraintValidatorManager.getDefaultConstraintValidatorFactory(), constraintValidatorManager.getDefaultConstraintValidatorInitializationContext() ); } @@ -131,36 +128,21 @@ private ValidationException getExceptionForNullValidator(Type validatedValueType // factory. Creating a lot of CHM for that cache might not be a good idea and we prefer being conservative // for now. Note that we have the ConstraintValidatorManager cache that mitigates the situation. // If you come up with a use case where it makes sense, please reach out to us. - validator = getInitializedConstraintValidator( validationContext.getConstraintValidatorManager(), validationContext.getConstraintValidatorFactory(), - validationContext.getConstraintValidatorInitializationContext() ); + validator = validationContext.getConstraintValidatorManager().getInitializedValidator( + validatedValueType, + descriptor, + validationContext.getConstraintValidatorFactory(), + validationContext.getConstraintValidatorInitializationContext() + ); } - if ( validator == DUMMY_CONSTRAINT_VALIDATOR ) { + if ( validator == null ) { throw getExceptionForNullValidator( validatedValueType, valueContext.getPropertyPath().asString() ); } return validator; } - @SuppressWarnings("unchecked") - private ConstraintValidator getInitializedConstraintValidator(ConstraintValidatorManager constraintValidatorManager, - ConstraintValidatorFactory constraintValidatorFactory, - HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext) { - ConstraintValidator validator = constraintValidatorManager.getInitializedValidator( - validatedValueType, - descriptor, - constraintValidatorFactory, - constraintValidatorInitializationContext - ); - - if ( validator != null ) { - return validator; - } - else { - return (ConstraintValidator) DUMMY_CONSTRAINT_VALIDATOR; - } - } - /** * @return an {@link Optional#empty()} if there is no violation or a corresponding {@link ConstraintValidatorContextImpl} * otherwise. diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManager.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManager.java index b35062c622..43bccf065e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManager.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManager.java @@ -10,9 +10,7 @@ import java.lang.reflect.Type; import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; import javax.validation.ConstraintValidatorFactory; -import javax.validation.constraints.Null; import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; @@ -24,18 +22,6 @@ */ public interface ConstraintValidatorManager { - /** - * Dummy {@code ConstraintValidator} used as placeholder for the case that for a given context there exists - * no matching constraint validator instance - */ - ConstraintValidator DUMMY_CONSTRAINT_VALIDATOR = new ConstraintValidator() { - - @Override - public boolean isValid(Object value, ConstraintValidatorContext context) { - return false; - } - }; - /** * @param validatedValueType the type of the value to be validated. Cannot be {@code null}. * @param descriptor the constraint descriptor for which to get an initialized constraint validator. Cannot be {@code null} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManagerImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManagerImpl.java index 4cd5425dc2..6d9c2dca14 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManagerImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManagerImpl.java @@ -15,7 +15,9 @@ import java.util.concurrent.ConcurrentHashMap; import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; import javax.validation.ConstraintValidatorFactory; +import javax.validation.constraints.Null; import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; @@ -34,6 +36,18 @@ public class ConstraintValidatorManagerImpl extends AbstractConstraintValidatorM private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + /** + * Dummy {@code ConstraintValidator} used as placeholder for the case that for a given context there exists + * no matching constraint validator instance + */ + private static final ConstraintValidator DUMMY_CONSTRAINT_VALIDATOR = new ConstraintValidator() { + + @Override + public boolean isValid(Object value, ConstraintValidatorContext context) { + return false; + } + }; + /** * The most recently used non default constraint validator factory. */ From c6da4b32cff4307b4c930db12afcc7f5a8621ee5 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 10 Dec 2018 17:47:38 +0100 Subject: [PATCH 149/393] HV-1667 Add an hopefully temporary workaround ConstraintValidatorFactory can be injected when using CDI and when initializing the CDI extension, the metadata are gathered before it being a proper bean, thus leading to NPE. See ManagedObjectsTest in container mode. --- .../constraintvalidation/ConstraintTree.java | 58 +++++++++++++------ .../ConstraintValidatorManager.java | 2 + .../ConstraintValidatorManagerImpl.java | 5 ++ ...edScopeConstraintValidatorManagerImpl.java | 5 ++ .../integrationtest/OsgiIntegrationTest.java | 2 +- 5 files changed, 53 insertions(+), 19 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java index c091d85f8d..760075ebfd 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java @@ -46,16 +46,18 @@ public abstract class ConstraintTree { private final Type validatedValueType; - private final ConstraintValidator defaultInitializedConstraintValidator; + private volatile ConstraintValidator defaultInitializedConstraintValidator; protected ConstraintTree(ConstraintValidatorManager constraintValidatorManager, ConstraintDescriptorImpl descriptor, Type validatedValueType) { this.descriptor = descriptor; this.validatedValueType = validatedValueType; - this.defaultInitializedConstraintValidator = constraintValidatorManager.getInitializedValidator( validatedValueType, - descriptor, - constraintValidatorManager.getDefaultConstraintValidatorFactory(), - constraintValidatorManager.getDefaultConstraintValidatorInitializationContext() ); + if ( constraintValidatorManager.isPredefinedScope() ) { + this.defaultInitializedConstraintValidator = constraintValidatorManager.getInitializedValidator( validatedValueType, + descriptor, + constraintValidatorManager.getDefaultConstraintValidatorFactory(), + constraintValidatorManager.getDefaultConstraintValidatorInitializationContext() ); + } } public static ConstraintTree of(ConstraintValidatorManager constraintValidatorManager, @@ -118,22 +120,42 @@ private ValidationException getExceptionForNullValidator(Type validatedValueType protected final ConstraintValidator getInitializedConstraintValidator(ValidationContext validationContext, ValueContext valueContext) { ConstraintValidator validator; - if ( validationContext.getConstraintValidatorFactory() == validationContext.getConstraintValidatorManager().getDefaultConstraintValidatorFactory() - && validationContext.getConstraintValidatorInitializationContext() == validationContext.getConstraintValidatorManager() - .getDefaultConstraintValidatorInitializationContext() ) { + if ( validationContext.getConstraintValidatorManager().isPredefinedScope() ) { validator = defaultInitializedConstraintValidator; } else { - // For now, we don't cache the result in the ConstraintTree if we don't use the default constraint validator - // factory. Creating a lot of CHM for that cache might not be a good idea and we prefer being conservative - // for now. Note that we have the ConstraintValidatorManager cache that mitigates the situation. - // If you come up with a use case where it makes sense, please reach out to us. - validator = validationContext.getConstraintValidatorManager().getInitializedValidator( - validatedValueType, - descriptor, - validationContext.getConstraintValidatorFactory(), - validationContext.getConstraintValidatorInitializationContext() - ); + if ( validationContext.getConstraintValidatorFactory() == validationContext.getConstraintValidatorManager().getDefaultConstraintValidatorFactory() + && validationContext.getConstraintValidatorInitializationContext() == validationContext.getConstraintValidatorManager() + .getDefaultConstraintValidatorInitializationContext() ) { + validator = defaultInitializedConstraintValidator; + + if ( validator == null ) { + synchronized ( this ) { + validator = defaultInitializedConstraintValidator; + if ( validator == null ) { + validator = validationContext.getConstraintValidatorManager().getInitializedValidator( + validatedValueType, + descriptor, + validationContext.getConstraintValidatorManager().getDefaultConstraintValidatorFactory(), + validationContext.getConstraintValidatorManager().getDefaultConstraintValidatorInitializationContext() ); + + defaultInitializedConstraintValidator = validator; + } + } + } + } + else { + // For now, we don't cache the result in the ConstraintTree if we don't use the default constraint validator + // factory. Creating a lot of CHM for that cache might not be a good idea and we prefer being conservative + // for now. Note that we have the ConstraintValidatorManager cache that mitigates the situation. + // If you come up with a use case where it makes sense, please reach out to us. + validator = validationContext.getConstraintValidatorManager().getInitializedValidator( + validatedValueType, + descriptor, + validationContext.getConstraintValidatorFactory(), + validationContext.getConstraintValidatorInitializationContext() + ); + } } if ( validator == null ) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManager.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManager.java index 43bccf065e..d6e34c4bf8 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManager.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManager.java @@ -43,4 +43,6 @@ public interface ConstraintValidatorManager { ConstraintValidatorFactory getDefaultConstraintValidatorFactory(); HibernateConstraintValidatorInitializationContext getDefaultConstraintValidatorInitializationContext(); + + boolean isPredefinedScope(); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManagerImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManagerImpl.java index 6d9c2dca14..bce18a9b8d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManagerImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorManagerImpl.java @@ -82,6 +82,11 @@ public ConstraintValidatorManagerImpl(ConstraintValidatorFactory defaultConstrai this.constraintValidatorCache = new ConcurrentHashMap<>(); } + @Override + public boolean isPredefinedScope() { + return false; + } + /** * @param validatedValueType the type of the value to be validated. Cannot be {@code null}. * @param descriptor the constraint descriptor for which to get an initialized constraint validator. Cannot be {@code null} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/PredefinedScopeConstraintValidatorManagerImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/PredefinedScopeConstraintValidatorManagerImpl.java index 473ba98da0..f341f51689 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/PredefinedScopeConstraintValidatorManagerImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/PredefinedScopeConstraintValidatorManagerImpl.java @@ -60,6 +60,11 @@ public PredefinedScopeConstraintValidatorManagerImpl( return createAndInitializeValidator( validatedValueType, descriptor, constraintValidatorFactory, initializationContext ); } + @Override + public boolean isPredefinedScope() { + return true; + } + @Override public void clear() { } diff --git a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java index 90ccc79411..e156542893 100644 --- a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java +++ b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java @@ -195,7 +195,7 @@ public void canConfigureCustomConstraintValidatorFactoryViaValidationXml() { .getValidator() .validate( new Customer() ); - assertEquals( 2, ExampleConstraintValidatorFactory.invocationCounter.get() ); + assertEquals( 1, ExampleConstraintValidatorFactory.invocationCounter.get() ); } @Test From 89f613aaf722c1130c1448cb928f05beb5bb1483 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Tue, 11 Dec 2018 10:18:12 +0000 Subject: [PATCH 150/393] [Jenkins release job] README.md updated by release build 6.1.0.Alpha1 --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5edbad0403..3e5ff4849f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hibernate Validator -*Version: 6.0.13.Final - 22-08-2018* +*Version: 6.1.0.Alpha1 - 11-12-2018* ## What is it? @@ -35,7 +35,7 @@ Logging will delegate any log requests to that provider. org.hibernate.validator hibernate-validator - 6.0.13.Final + 6.1.0.Alpha1 You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. @@ -54,7 +54,7 @@ extension by adding the following dependency: org.hibernate.validator hibernate-validator-cdi - 6.0.13.Final + 6.1.0.Alpha1 * _hibernate-validator-annotation-processor-<version>.jar_ is an optional jar which can be integrated with your build From 61c5ffbb0474123c1819a94b4e9b0e87ad9aa337 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Tue, 11 Dec 2018 10:18:12 +0000 Subject: [PATCH 151/393] [Jenkins release job] changelog.txt updated by release build 6.1.0.Alpha1 --- changelog.txt | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/changelog.txt b/changelog.txt index 4d3458aa8a..e7fb5a30db 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,67 @@ Hibernate Validator Changelog ============================= +6.1.0.Alpha1 (11-12-2018) +------------------------- + +** Bug + * HV-1650 - validators - French translations are badly encoded + * HV-1645 - extensions - Revert HV-1609 due to increased CDI startup caused by ValidateableBeanFilter + * HV-1644 - build - Using Hibernate Validator with Java 11 brings JavaFX on the classpath + * HV-1637 - translations - PropertyNotFoundException for @DecimalMax when using the German translation + * HV-1634 - engine - Deal with synthetic and implicit parameters properly when getting the generic type of a parameter + * HV-1510 - validators - @NotNull doesn't work in 50% when annotated method is extended from multiple classes + * HV-1450 - engine - BeanMetaDataImpl.BeanMetaDataBuilder#build() can choose ConstraintMetaData w/o constraints + +** Improvement + * HV-1662 - engine - Extract BeanMetaDataBuilder to its own class file + * HV-1661 - engine - Remove impossible case from ValidatorImpl#buildNewLocalExecutionContext() + * HV-1656 - translations - Add translation of Validation Messages for Japanese language + * HV-1653 - engine - Improve the javadoc of ParameterScriptAssert + * HV-1643 - translations - Fix Russian translation for @Null constraint + * HV-1636 - engine - Avoid instantiating unnecessary objects during constraint metadata creation + * HV-1631 - engine - Avoid doing two lookups in the read methods of AnnotationProcessingOptionsImpl + * HV-1630 - engine - Introduce StringHelper.format() + * HV-1629 - engine - Fix compiler warnings + * HV-1628 - annotation-processor, engine, tests - Configure a stricter forbidden-apis policy and remove calls deprecated in Java 10 + * HV-1626 - build - Remove useless Maven plugins and extensions + * HV-1623 - engine - Build an abstraction over reflection in engine + * HV-1622 - integration - Update the WildFly integration tests to use WildFly 13 + * HV-1617 - build - Make our pom files more consistent with WildFly and JBoss parent pom files + * HV-1599 - engine - Avoid creating later discarded violations when reportAsSingleViolation is true + * HV-1526 - engine - Create separate validation context for different validation kinds + * HV-1484 - build - Unify JPMS module names and OSGi bundle names + * HV-667 - engine - Consider to create descriptor model lazily + +** New Feature + * HV-1671 - engine - Allow to retrieve all the built-in constraint annotations from ConstraintHelper + * HV-1670 - engine - Add the ability to preload a set of locales + * HV-1667 - engine - Create a predefined scope ValidatorFactory which initializes things eagerly + * HV-1363 - engine - Support for non-standard Java beans + +** Remove Feature + * HV-1624 - engine - Remove the StaticFieldELResolver + +** Task + * HV-1677 - engine - Allow for an explicit environment variable to disable the JavaFX extensions + * HV-1674 - engine - Make the name of the default bundle public in AbstractMessageInterpolator + * HV-1673 - engine - Audit new privileged calls in the reflection abstraction + * HV-1669 - engine - Only enable the SafeHtml constraint if jsoup in in the classpath + * HV-1668 - engine - Properly register all built-in constraints + * HV-1659 - integration - Upgrade WildFly to 14.0.1 + * HV-1658 - engine - Remove a couple of stream usages in ConstraintHelper that cause a problem for another project + * HV-1649 - tck-runner - Upgrade to Bean Validation TCK 2.0.4.Final + * HV-1648 - build, integration - Reenable WildFly integration tests for JDK 11 + * HV-1647 - tck-runner - Allow running TCK tests in container mode with JDK 11 + * HV-1646 - build, integration, tck-runner - Upgrade WildFly to 14.0.0.Beta1 + * HV-1641 - build - Use the OSS snapshot repository to download the JavaFX dependencies when building with JDK 11 + * HV-1640 - build - Add compatibility with the latest JDK 11 build 22 + * HV-1635 - documentation - Remove specific instructions for building with JDK 9 from the README + * HV-1627 - build - Upgrade our JPA test dependency to 2.2 + * HV-1610 - integration - Reenable OSGi tests for JDK 10 + * HV-1608 - build - Have the build work with JDK 11 + * HV-1577 - engine - Use Stax instead of JAXB to parse the XML descriptors + 6.0.13.Final (22-08-2018) ------------------------- From 18810986a15b8616e8ed150cacc47f53c6e8e9f0 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Tue, 11 Dec 2018 10:18:21 +0000 Subject: [PATCH 152/393] [Jenkins release job] Preparing release 6.1.0.Alpha1 --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 6b70540803..81aa2db1dd 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 021058c8f5..f733897e66 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index 64d7dc2320..b046cdea4a 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index a60c2e907e..5af303461b 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 76e5181564..00d46083f9 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index 5fd0209f0b..3e8089944f 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 7e78f49241..53c7d8431d 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index b9eacc9ca4..fa8b3967f9 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 55c15d1c8c..fff8781e5a 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 28ce4576ea..18fea2e32f 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 1b9ec9f304..31fa61c927 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index fc4f7e3a85..dd2e3af3af 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index 09262ee135..ab7c4b5ca5 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 ../pom.xml diff --git a/pom.xml b/pom.xml index 077d502e5d..546e70cb5c 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 3f99228d35..2c0d074f88 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index acc9a54560..9bade1810d 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index d793ee6b6e..844b7cdb72 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index c2eba20d47..069989b61b 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 6516654b3f..1e2f0337b1 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 4b01b88584..e47353470f 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 3b0766e5c7..cb2d4aa195 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha1 hibernate-validator-test-utils From a92b69c53ebeb18b6228faecdc33c0bb7e530483 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Tue, 11 Dec 2018 10:22:27 +0000 Subject: [PATCH 153/393] [Jenkins release job] Preparing next development iteration --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 81aa2db1dd..6b70540803 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index f733897e66..021058c8f5 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index b046cdea4a..64d7dc2320 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index 5af303461b..a60c2e907e 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 00d46083f9..76e5181564 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index 3e8089944f..5fd0209f0b 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 53c7d8431d..7e78f49241 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index fa8b3967f9..b9eacc9ca4 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index fff8781e5a..55c15d1c8c 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 18fea2e32f..28ce4576ea 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 31fa61c927..1b9ec9f304 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index dd2e3af3af..fc4f7e3a85 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index ab7c4b5ca5..09262ee135 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 546e70cb5c..077d502e5d 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 2c0d074f88..3f99228d35 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index 9bade1810d..acc9a54560 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index 844b7cdb72..d793ee6b6e 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index 069989b61b..c2eba20d47 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 1e2f0337b1..6516654b3f 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index e47353470f..4b01b88584 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index cb2d4aa195..3b0766e5c7 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha1 + 6.1.0-SNAPSHOT hibernate-validator-test-utils From 071aea40dc598f895e85c60d208d93d6ffbe9d7d Mon Sep 17 00:00:00 2001 From: maffe Date: Thu, 13 Dec 2018 14:50:56 +0100 Subject: [PATCH 154/393] Update PlatformResourceBundleLocator.java Trivial typo fix --- .../resourceloading/PlatformResourceBundleLocator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/src/main/java/org/hibernate/validator/resourceloading/PlatformResourceBundleLocator.java b/engine/src/main/java/org/hibernate/validator/resourceloading/PlatformResourceBundleLocator.java index b757c5ea1a..93ecb09465 100644 --- a/engine/src/main/java/org/hibernate/validator/resourceloading/PlatformResourceBundleLocator.java +++ b/engine/src/main/java/org/hibernate/validator/resourceloading/PlatformResourceBundleLocator.java @@ -260,7 +260,7 @@ private static T run(PrivilegedAction action) { * * @see GAE JRE whitelist * @see HV-1023 - * @see ResourceBundle.Control */ private static boolean determineAvailabilityOfResourceBundleControl() { try { From abc470fabd98a897b57c055dc7dbcaaa05d5d3ca Mon Sep 17 00:00:00 2001 From: Andrew Guibert Date: Mon, 20 Aug 2018 15:55:57 -0500 Subject: [PATCH 155/393] HV-1651 Contribute additional language translations from OpenLiberty The OpenLiberty application server uses Hibernate Validator and provides translated messages in 15 languages, 6 of which are new languages not currently supported by Hibernate Validator. The new languages are: - Italian (it) - Japanese (ja) - Polish (pl) - Romanian (ro) - Chinese (Simplified) (zh) - Chinese (Traditional) (zh_TW) Signed-off-by: Andrew Guibert --- .../ValidationMessages_cs.properties | 78 ++++++++++----- .../ValidationMessages_de.properties | 89 ++++++++++------- .../ValidationMessages_es.properties | 98 +++++++++---------- .../ValidationMessages_fr.properties | 94 +++++++++--------- .../ValidationMessages_hu.properties | 78 ++++++++++----- .../ValidationMessages_it.properties | 53 ++++++++++ .../ValidationMessages_ko.properties | 87 +++++++++------- .../ValidationMessages_pl.properties | 53 ++++++++++ .../ValidationMessages_pt_BR.properties | 93 ++++++++++-------- .../ValidationMessages_ro.properties | 53 ++++++++++ .../ValidationMessages_ru.properties | 83 ++++++++++------ .../ValidationMessages_zh.properties | 53 ++++++++++ .../ValidationMessages_zh_TW.properties | 53 ++++++++++ 13 files changed, 672 insertions(+), 293 deletions(-) create mode 100644 engine/src/main/resources/org/hibernate/validator/ValidationMessages_it.properties create mode 100644 engine/src/main/resources/org/hibernate/validator/ValidationMessages_pl.properties create mode 100644 engine/src/main/resources/org/hibernate/validator/ValidationMessages_ro.properties create mode 100644 engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh.properties create mode 100644 engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh_TW.properties diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_cs.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_cs.properties index 19014e8c9d..3f52e33b96 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_cs.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_cs.properties @@ -1,27 +1,53 @@ -javax.validation.constraints.AssertFalse.message = mus\u00ed b\u00fdt ne -javax.validation.constraints.AssertTrue.message = mus\u00ed b\u00fdt ano -javax.validation.constraints.DecimalMax.message = mus\u00ed b\u00fdt men\u0161\u00ed ne\u017e nebo rovno {value} -javax.validation.constraints.DecimalMin.message = mus\u00ed b\u00fdt v\u011bt\u0161\u00ed ne\u017e nebo rovno {value} -javax.validation.constraints.Digits.message = \u010d\u00edseln\u00e1 hodnota mimo rozsah (o\u010dek\u00e1v\u00e1no <{integer} \u010d\u00edslic>.<{fraction} \u010d\u00edslic>) -javax.validation.constraints.Email.message = chybn\u00e1 emailov\u00e1 adresa -javax.validation.constraints.Future.message = mus\u00ed b\u00fdt v budoucnosti -javax.validation.constraints.Max.message = mus\u00ed b\u00fdt men\u0161\u00ed ne\u017e nebo rovno {value} -javax.validation.constraints.Min.message = mus\u00ed b\u00fdt v\u011bt\u0161\u00ed ne\u017e nebo rovno {value} -javax.validation.constraints.NotBlank.message = nem\u016f\u017ee b\u00fdt pr\u00e1zdn\u00fd/\u00e1/\u00e9 -javax.validation.constraints.NotEmpty.message = nem\u016f\u017ee b\u00fdt pr\u00e1zdn\u00fd/\u00e1/\u00e9 -javax.validation.constraints.NotNull.message = nesm\u00ed b\u00fdt null -javax.validation.constraints.Null.message = mus\u00ed b\u00fdt null -javax.validation.constraints.Past.message = mus\u00ed b\u00fdt v minulosti -javax.validation.constraints.Pattern.message = se mus\u00ed shodovat s "{regexp}" -javax.validation.constraints.Size.message = velikost mus\u00ed b\u00fdt mezi {min} a {max} +javax.validation.constraints.AssertFalse.message = mus\u00ed m\u00edt hodnotu ne +javax.validation.constraints.AssertTrue.message = mus\u00ed m\u00edt hodnotu ano +javax.validation.constraints.DecimalMax.message = mus\u00ed b\u00fdt men\u0161\u00ed ne\u017e ${inclusive == true ? 'nebo rovna hodnot\u011b ' : ''}{hodnota} +javax.validation.constraints.DecimalMin.message = mus\u00ed b\u00fdt v\u011bt\u0161\u00ed ne\u017e ${inclusive == true ? 'nebo rovna hodnot\u011b ' : ''}{hodnota} +javax.validation.constraints.Digits.message = \u010d\u00edseln\u00e1 hodnota mimo rozsah (o\u010dek\u00e1v\u00e1no: <{integer} \u010d\u00edslic>.<{fraction} \u010d\u00edslic>) +javax.validation.constraints.Email.message = mus\u00ed m\u00edt spr\u00e1vn\u011b utvo\u0159enou e-mailovou adresu +javax.validation.constraints.Future.message = mus\u00ed se jednat o datum v budoucnu +javax.validation.constraints.FutureOrPresent.message = mus\u00ed m\u00edt aktu\u00e1ln\u00ed nebo budouc\u00ed datum +javax.validation.constraints.Max.message = mus\u00ed b\u00fdt men\u0161\u00ed nebo rovna hodnot\u011b {value} +javax.validation.constraints.Min.message = mus\u00ed b\u00fdt v\u011bt\u0161\u00ed nebo rovna hodnot\u011b {value} +javax.validation.constraints.Negative.message = mus\u00ed b\u00fdt men\u0161\u00ed ne\u017e 0 +javax.validation.constraints.NegativeOrZero.message = mus\u00ed b\u00fdt men\u0161\u00ed ne\u017e nebo rovna hodnot\u011b 0 +javax.validation.constraints.NotBlank.message = nesm\u00ed b\u00fdt pr\u00e1zdn\u00e1 +javax.validation.constraints.NotEmpty.message = nesm\u00ed b\u00fdt pr\u00e1zdn\u00e1 +javax.validation.constraints.NotNull.message = nesm\u00ed m\u00edt hodnotu Null +javax.validation.constraints.Null.message = mus\u00ed m\u00edt hodnotu Null +javax.validation.constraints.Past.message = mus\u00ed se jednat o datum v minulosti +javax.validation.constraints.PastOrPresent.message = mus\u00ed b\u00fdt datum v minulosti nebo aktu\u00e1ln\u00ed +javax.validation.constraints.Pattern.message = mus\u00ed odpov\u00eddat "{regexp}" +javax.validation.constraints.Positive.message = mus\u00ed b\u00fdt v\u011bt\u0161\u00ed ne\u017e 0 +javax.validation.constraints.PositiveOrZero.message = mus\u00ed b\u00fdt v\u011bt\u0161\u00ed ne\u017e nebo rovna hodnot\u011b 0 +javax.validation.constraints.Size.message = velikost mus\u00ed le\u017eet v rozsahu {min} a\u017e {max} -org.hibernate.validator.constraints.CreditCardNumber.message = neplatn\u00e9 \u010d\u00edslo kreditn\u00ed karty -org.hibernate.validator.constraints.Email.message = chybn\u00e1 emailov\u00e1 adresa -org.hibernate.validator.constraints.Length.message = d\u00e9lka mus\u00ed b\u00fdt mezi {min} a {max} -org.hibernate.validator.constraints.CodePointLength.message = d\u00e9lka mus\u00ed b\u00fdt mezi {min} a {max} -org.hibernate.validator.constraints.NotBlank.message = nem\u016f\u017ee b\u00fdt pr\u00e1zdn\u00fd/\u00e1/\u00e9 -org.hibernate.validator.constraints.NotEmpty.message = nem\u016f\u017ee b\u00fdt pr\u00e1zdn\u00fd/\u00e1/\u00e9 -org.hibernate.validator.constraints.Range.message = mus\u00ed b\u00fdt mezi {min} a {max} -org.hibernate.validator.constraints.SafeHtml.message = m\u016f\u017ee obsahovat nebezpe\u010dn\u00fd html obsah -org.hibernate.validator.constraints.ScriptAssert.message = skriptovac\u00ed v\u00fdraz "{script}" nen\u00ed vyhodnocen na ano -org.hibernate.validator.constraints.URL.message = mus\u00ed b\u00fdt platn\u00e9 URL +org.hibernate.validator.constraints.CreditCardNumber.message = neplatn\u00e9 \u010d\u00edslo kreditn\u00ed karty +org.hibernate.validator.constraints.Currency.message = neplatn\u00e1 m\u011bna (mus\u00ed m\u00edt jednu z hodnot {hodnota}) +org.hibernate.validator.constraints.EAN.message = neplatn\u00fd \u010d\u00e1rov\u00fd k\u00f3d {typ} +org.hibernate.validator.constraints.Email.message = nejedn\u00e1 se o spr\u00e1vn\u011b utvo\u0159enou e-mailovou adresu +org.hibernate.validator.constraints.ISBN.message = neplatn\u00e9 ISBN +org.hibernate.validator.constraints.Length.message = d\u00e9lka mus\u00ed le\u017eet v rozsahu {min} a\u017e {max} +org.hibernate.validator.constraints.CodePointLength.message = d\u00e9lka mus\u00ed le\u017eet v rozsahu {min} a\u017e {max} +org.hibernate.validator.constraints.LuhnCheck.message = Kontroln\u00ed \u010d\u00edslice pro ${validatedValue} je neplatn\u00e1, kontroln\u00ed sou\u010det Luhn Modulo 10 se nezda\u0159il +org.hibernate.validator.constraints.Mod10Check.message = Kontroln\u00ed \u010d\u00edslice pro ${validatedValue} je neplatn\u00e1, kontroln\u00ed sou\u010det Modulo 10 se nezda\u0159il +org.hibernate.validator.constraints.Mod11Check.message = Kontroln\u00ed \u010d\u00edslice pro ${validatedValue} je neplatn\u00e1, kontroln\u00ed sou\u010det Modulo 11 se nezda\u0159il +org.hibernate.validator.constraints.ModCheck.message = Kontroln\u00ed \u010d\u00edslice pro ${validatedValue} je neplatn\u00e1, kontroln\u00ed sou\u010det ${modType} se nezda\u0159il +org.hibernate.validator.constraints.NotBlank.message = nesm\u00ed b\u00fdt pr\u00e1zdn\u00e1 +org.hibernate.validator.constraints.NotEmpty.message = nesm\u00ed b\u00fdt pr\u00e1zdn\u00e1 +org.hibernate.validator.constraints.ParametersScriptAssert.message = v\u00fdraz skriptu "{script}" se nevyhodnotil na true +org.hibernate.validator.constraints.Range.message = mus\u00ed le\u017eet v rozsahu {min} a\u017e {max} +org.hibernate.validator.constraints.SafeHtml.message = je mo\u017en\u00e9, \u017ee obsah html nen\u00ed bezpe\u010dn\u00fd +org.hibernate.validator.constraints.ScriptAssert.message = v\u00fdraz skriptu "{script}" se nevyhodnotil na true +org.hibernate.validator.constraints.UniqueElements.message = mus\u00ed obsahovat pouze jedine\u010dn\u00e9 prvky +org.hibernate.validator.constraints.URL.message = mus\u00ed b\u00fdt platnou adresou URL + +org.hibernate.validator.constraints.br.CNPJ.message = neplatn\u00e9 brazilsk\u00e9 registra\u010dn\u00ed \u010d\u00edslo pl\u00e1tce korpor\u00e1tn\u00ed dan\u011b (CNPJ) +org.hibernate.validator.constraints.br.CPF.message = neplatn\u00e9 brazilsk\u00e9 registra\u010dn\u00ed \u010d\u00edslo individu\u00e1ln\u00edho pl\u00e1tce dan\u011b (CPF) +org.hibernate.validator.constraints.br.TituloEleitoral.message = neplatn\u00e9 brazilsk\u00e9 \u010d\u00edslo karty Voter ID + +org.hibernate.validator.constraints.pl.REGON.message = Neplatn\u00e9 Polsk\u00e9 Identifika\u010dn\u00ed \u010d\u00edslo pl\u00e1tn\u011b dan\u011b (REGON) +org.hibernate.validator.constraints.pl.NIP.message = Neplatn\u00e9 da\u0148ov\u00e9 identifika\u010dn\u00ed \u010d\u00edslo (NIP) +org.hibernate.validator.constraints.pl.PESEL.message = Neplatn\u00e9 Polsk\u00e9 n\u00e1rodn\u00ed Identifika\u010dn\u00ed \u010d\u00edslo (PESEL) + +org.hibernate.validator.constraints.time.DurationMax.message = mus\u00ed b\u00fdt krat\u0161\u00ed ne\u017e${inclusive == true ? ' nebo rovno hodnot\u011b' : ''}${days == 0 ? '' : days == 1 ? ' 1 den' : ' ' += days += ' dny/\u016f'}${hours == 0 ? '' : hours == 1 ? ' 1 hod' : ' ' += hours += ' hod'}${minutes == 0 ? '' : minutes == 1 ? ' 1 min' : ' ' += minutes += ' min'}${seconds == 0 ? '' : seconds == 1 ? ' 1 s' : ' ' += seconds += ' s'}${millis == 0 ? '' : millis == 1 ? ' 1 ms' : ' ' += millis += ' ms'}${nanos == 0 ? '' : nanos == 1 ? ' 1 ns' : ' ' += nanos += ' ns'} +org.hibernate.validator.constraints.time.DurationMin.message = mus\u00ed b\u00fdt del\u0161\u00ed ne\u017e${inclusive == true ? ' nebo rovno hodnot\u011b' : ''}${days == 0 ? '' : days == 1 ? ' 1 den' : ' ' += days += ' dny/\u016f'}${hours == 0 ? '' : hours == 1 ? ' 1 hod' : ' ' += hours += ' hod'}${minutes == 0 ? '' : minutes == 1 ? ' 1 min' : ' ' += minutes += ' min'}${seconds == 0 ? '' : seconds == 1 ? ' 1 s' : ' ' += seconds += ' s'}${millis == 0 ? '' : millis == 1 ? ' 1 ms' : ' ' += millis += ' ms'}${nanos == 0 ? '' : nanos == 1 ? ' 1 ns' : ' ' += nanos += ' ns'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties index 46d5fba48d..b8365a0853 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties @@ -1,40 +1,53 @@ -javax.validation.constraints.AssertFalse.message = muss falsch sein -javax.validation.constraints.AssertTrue.message = muss wahr sein -javax.validation.constraints.DecimalMax.message = muss kleiner ${inclusive == true ? 'oder gleich ' : ''}{value} sein -javax.validation.constraints.DecimalMin.message = muss gr\u00F6\u00DFer ${inclusive == true ? 'oder gleich ' : ''}{value} sein -javax.validation.constraints.Digits.message = numerischer Wert au\u00DFerhalb erlaubten Wertebereichs (<{integer} Ziffern>,<{fraction} Ziffern> erwartet) -javax.validation.constraints.Email.message = keine g\u00FCltige E-Mail-Adresse -javax.validation.constraints.Future.message = muss in der Zukunft liegen -javax.validation.constraints.FutureOrPresent.message = muss in der Gegenwart oder Zukunft liegen -javax.validation.constraints.Max.message = muss kleiner oder gleich {value} sein -javax.validation.constraints.Min.message = muss gr\u00F6\u00DFer oder gleich {value} sein -javax.validation.constraints.Negative.message = muss kleiner 0 sein -javax.validation.constraints.NegativeOrZero.message = muss kleiner oder gleich 0 sein -javax.validation.constraints.NotBlank.message = darf nicht leer sein -javax.validation.constraints.NotEmpty.message = darf nicht leer sein -javax.validation.constraints.NotNull.message = darf nicht null sein -javax.validation.constraints.Null.message = muss null sein -javax.validation.constraints.Past.message = muss in der Vergangenheit liegen -javax.validation.constraints.PastOrPresent.message = muss in der Gegenwart oder Vergangenheit liegen -javax.validation.constraints.Pattern.message = muss auf Ausdruck "{regexp}" passen -javax.validation.constraints.Positive.message = muss gr\u00F6\u00DFer 0 sein -javax.validation.constraints.PositiveOrZero.message = muss gr\u00F6\u00DFer oder gleich 0 sein -javax.validation.constraints.Size.message = muss zwischen {min} und {max} liegen +javax.validation.constraints.AssertFalse.message = muss falsch sein +javax.validation.constraints.AssertTrue.message = muss wahr sein +javax.validation.constraints.DecimalMax.message = muss kleiner ${inclusive == true ? 'oder gleich ' : ''}{value} sein +javax.validation.constraints.DecimalMin.message = muss gr\u00f6\u00dfer ${inclusive == true ? 'oder gleich sein ' : ''}{value} +javax.validation.constraints.Digits.message = numerischer Wert au\u00dferhalb des g\u00fcltigen Bereichs (<{integer} digits>.<{fraction} digits> erwartet) +javax.validation.constraints.Email.message = muss eine korrekt formatierte E-Mail-Adresse sein. +javax.validation.constraints.Future.message = muss ein Datum in der Zukunft sein. +javax.validation.constraints.FutureOrPresent.message = muss ein Datum in der Gegenwart oder in der Zukunft sein. +javax.validation.constraints.Max.message = muss kleiner-gleich {value} sein. +javax.validation.constraints.Min.message = muss gr\u00f6\u00dfer-gleich {value} sein. +javax.validation.constraints.Negative.message = muss kleiner als 0 sein. +javax.validation.constraints.NegativeOrZero.message = muss kleiner-gleich 0 sein. +javax.validation.constraints.NotBlank.message = darf nicht leer sein. +javax.validation.constraints.NotEmpty.message = darf nicht leer sein. +javax.validation.constraints.NotNull.message = darf nicht null sein. +javax.validation.constraints.Null.message = muss null sein. +javax.validation.constraints.Past.message = muss ein Datum in der Vergangenheit sein. +javax.validation.constraints.PastOrPresent.message = muss ein Datum in der Vergangenheit oder in der Gegenwart sein. +javax.validation.constraints.Pattern.message = muss mit "{regexp}" \u00fcbereinstimmen. +javax.validation.constraints.Positive.message = muss gr\u00f6\u00dfer als 0 sein. +javax.validation.constraints.PositiveOrZero.message = muss gr\u00f6\u00dfer-gleich 0 sein. +javax.validation.constraints.Size.message = Gr\u00f6\u00dfe muss zwischen {min} und {max} sein. -org.hibernate.validator.constraints.CreditCardNumber.message = ung\u00FCltige Kreditkartennummer -org.hibernate.validator.constraints.Currency.message = ung\u00FCltige W\u00E4hrung (erlaubte Werte: {value}) -org.hibernate.validator.constraints.EAN.message = ung\u00FCltiger {type} Barcode -org.hibernate.validator.constraints.Email.message = keine g\u00FCltige E-Mail-Adresse -org.hibernate.validator.constraints.Length.message = muss zwischen {min} und {max} Zeichen lang sein -org.hibernate.validator.constraints.CodePointLength.message = muss zwischen {min} und {max} Zeichen lang sein -org.hibernate.validator.constraints.NotBlank.message = darf nicht leer sein -org.hibernate.validator.constraints.NotEmpty.message = darf nicht leer sein -org.hibernate.validator.constraints.ParametersScriptAssert.message = Skriptausdruck "{script}" gab nicht true zur\u00FCck -org.hibernate.validator.constraints.Range.message = muss zwischen {min} und {max} liegen -org.hibernate.validator.constraints.SafeHtml.message = k\u00F6nnte unsicheren HTML-Inhalt haben -org.hibernate.validator.constraints.ScriptAssert.message = Skriptausdruck "{script}" gab nicht true zur\u00FCck -org.hibernate.validator.constraints.UniqueElements.message = darf keine Duplikate enthalten -org.hibernate.validator.constraints.URL.message = muss eine g\u00FCltige URL sein +org.hibernate.validator.constraints.CreditCardNumber.message = ung\u00fcltige Kreditkartennummer +org.hibernate.validator.constraints.Currency.message = ung\u00fcltige W\u00e4hrung (muss eine der folgenden sein: {value}) +org.hibernate.validator.constraints.EAN.message = ung\u00fcltiger {type}-Barcode +org.hibernate.validator.constraints.Email.message = keine korrekt formatierte E-Mail-Adresse. +org.hibernate.validator.constraints.ISBN.message = Ung\u00fcltiger ISBN-Wert +org.hibernate.validator.constraints.Length.message = L\u00e4nge muss zwischen {min} und {max} sein. +org.hibernate.validator.constraints.CodePointLength.message = L\u00e4nge muss zwischen {min} und {max} sein. +org.hibernate.validator.constraints.LuhnCheck.message = die Pr\u00fcfziffer f\u00fcr ${validatedValue} ist ung\u00fcltig, Luhn Modulo 10-Kontrollsumme ist fehlgeschlagen +org.hibernate.validator.constraints.Mod10Check.message = die Pr\u00fcfziffer f\u00fcr ${validatedValue} ist ung\u00fcltig, Modulo 10-Kontrollsumme ist fehlgeschlagen +org.hibernate.validator.constraints.Mod11Check.message = die Pr\u00fcfziffer f\u00fcr ${validatedValue} ist ung\u00fcltig, Modulo 11-Kontrollsumme ist fehlgeschlagen +org.hibernate.validator.constraints.ModCheck.message = die Pr\u00fcfziffer f\u00fcr ${validatedValue} ist ung\u00fcltig, ${modType}-Kontrollsumme ist fehlgeschlagen +org.hibernate.validator.constraints.NotBlank.message = darf nicht leer sein. +org.hibernate.validator.constraints.NotEmpty.message = darf nicht leer sein. +org.hibernate.validator.constraints.ParametersScriptAssert.message = die Evaluierung des Scriptausdrucks "{script}" ergab nicht true +org.hibernate.validator.constraints.Range.message = muss zwischen {min} und {max} sein. +org.hibernate.validator.constraints.SafeHtml.message = hat m\u00f6glicherweise keinen gesch\u00fctzten HTML-Inhalt. +org.hibernate.validator.constraints.ScriptAssert.message = die Evaluierung des Scriptausdrucks "{script}" ergab nicht true +org.hibernate.validator.constraints.UniqueElements.message = dar nur eindeutige Elemente enthalten +org.hibernate.validator.constraints.URL.message = muss eine g\u00fcltige URL sein. -org.hibernate.validator.constraints.time.DurationMax.message = muss k\u00FCrzer${inclusive == true ? ' oder gleich' : ' als'}${days == 0 ? '' : days == 1 ? ' 1 Tag' : ' ' += days += ' Tage'}${hours == 0 ? '' : hours == 1 ? ' 1 Stunde' : ' ' += hours += ' Stunden'}${minutes == 0 ? '' : minutes == 1 ? ' 1 Minute' : ' ' += minutes += ' Minuten'}${seconds == 0 ? '' : seconds == 1 ? ' 1 Sekunde' : ' ' += seconds += ' Sekunden'}${millis == 0 ? '' : millis == 1 ? ' 1 Millisekunde' : ' ' += millis += ' Millisekunden'}${nanos == 0 ? '' : nanos == 1 ? ' 1 Nanosekunde' : ' ' += nanos += ' Nanosekunden'} sein -org.hibernate.validator.constraints.time.DurationMin.message = muss l\u00E4nger${inclusive == true ? ' oder gleich' : ' als'}${days == 0 ? '' : days == 1 ? ' 1 Tag' : ' ' += days += ' Tage'}${hours == 0 ? '' : hours == 1 ? ' 1 Stunde' : ' ' += hours += ' Stunden'}${minutes == 0 ? '' : minutes == 1 ? ' 1 Minute' : ' ' += minutes += ' Minuten'}${seconds == 0 ? '' : seconds == 1 ? ' 1 Sekunde' : ' ' += seconds += ' Sekunden'}${millis == 0 ? '' : millis == 1 ? ' 1 Millisekunde' : ' ' += millis += ' Millisekunden'}${nanos == 0 ? '' : nanos == 1 ? ' 1 Nanosekunde' : ' ' += nanos += ' Nanosekunden'} sein +org.hibernate.validator.constraints.br.CNPJ.message = ung\u00fcltige brasilianische Registriernummer f\u00fcr K\u00f6rperschaftssteuerzahlungen (CNPJ) +org.hibernate.validator.constraints.br.CPF.message = ung\u00fcltige brasilianische Registriernummer f\u00fcr Steuerzahlungen nat\u00fcrlicher Personen (CPF) +org.hibernate.validator.constraints.br.TituloEleitoral.message = ung\u00fcltige brasilianische ID-Karte f\u00fcr Entscheidungsberechtigte + +org.hibernate.validator.constraints.pl.REGON.message = ung\u00fcltige polnische Steuerzahleridentifikationsnummer (REGON) +org.hibernate.validator.constraints.pl.NIP.message = ung\u00fcltige Mehrwertsteueridentifikationsnummer (NIP) +org.hibernate.validator.constraints.pl.PESEL.message = ung\u00fcltige polnische nationale Identifikationsnummer (PESEL) + +org.hibernate.validator.constraints.time.DurationMax.message = muss k\u00fcrzer sein als${inclusive == true ? ' oder gleich' : ''}${days == 0 ? '' : days == 1 ? ' 1 Tag' : ' ' += days += ' Tage'}${hours == 0 ? '' : hours == 1 ? ' 1 Stunde' : ' ' += hours += ' Stunden'}${minutes == 0 ? '' : minutes == 1 ? ' 1 Minute' : ' ' += minutes += ' Minuten'}${seconds == 0 ? '' : seconds == 1 ? ' 1 Sekunde' : ' ' += seconds += ' Sekunden'}${millis == 0 ? '' : millis == 1 ? ' 1 Millisekunde' : ' ' += millis += ' Millisekunden'}${nanos == 0 ? '' : nanos == 1 ? ' 1 Nanosekunde' : ' ' += nanos += ' Nanosekunden'} +org.hibernate.validator.constraints.time.DurationMin.message = muss gr\u00f6\u00dfer sein als${inclusive == true ? ' oder gleich' : ''}${days == 0 ? '' : days == 1 ? ' 1 Tag' : ' ' += days += ' Tage'}${hours == 0 ? '' : hours == 1 ? ' 1 Stunde' : ' ' += hours += ' Stunden'}${minutes == 0 ? '' : minutes == 1 ? ' 1 Minute' : ' ' += minutes += ' Minuten'}${seconds == 0 ? '' : seconds == 1 ? ' 1 Sekunde' : ' ' += seconds += ' Sekunden'}${millis == 0 ? '' : millis == 1 ? ' 1 Millisekunde' : ' ' += millis += ' Millisekunden'}${nanos == 0 ? '' : nanos == 1 ? ' 1 Nanosekunde' : ' ' += nanos += ' Nanosekunden'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_es.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_es.properties index cea34f85f2..fcc03c0031 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_es.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_es.properties @@ -1,53 +1,53 @@ -javax.validation.constraints.AssertFalse.message = tiene que ser falso -javax.validation.constraints.AssertTrue.message = tiene que ser verdadero -javax.validation.constraints.DecimalMax.message = tiene que ser menor ${inclusive == true ? 'o igual que ' : ''}{value} -javax.validation.constraints.DecimalMin.message = tiene que ser mayor ${inclusive == true ? 'o igual que ' : ''}{value} -javax.validation.constraints.Digits.message = valor num\u00E9rico fuera de los l\u00EDmites (se esperaba <{integer} d\u00EDgitos>.<{fraction} d\u00EDgitos) -javax.validation.constraints.Email.message = no es una direcci\u00F3n de correo bien formada -javax.validation.constraints.Future.message = tiene que ser una fecha en el futuro -javax.validation.constraints.FutureOrPresent.message = tiene que ser una fecha en el presente o en el futuro -javax.validation.constraints.Max.message = tiene que ser menor o igual que {value} -javax.validation.constraints.Min.message = tiene que ser mayor o igual que {value} -javax.validation.constraints.Negative.message = tiene que ser menor que 0 -javax.validation.constraints.NegativeOrZero.message = tiene que ser menor o igual a 0 -javax.validation.constraints.NotBlank.message = no puede estar vac\u00EDo -javax.validation.constraints.NotEmpty.message = no puede estar vac\u00EDo -javax.validation.constraints.NotNull.message = no puede ser null -javax.validation.constraints.Null.message = tiene que ser null -javax.validation.constraints.Past.message = tiene que ser una fecha en el pasado -javax.validation.constraints.PastOrPresent.message = tiene que ser una fecha en el pasado o en el presente -javax.validation.constraints.Pattern.message = tiene que corresponder a la expresi\u00F3n regular "{regexp}" -javax.validation.constraints.Positive.message = tiene que ser mayor que 0 -javax.validation.constraints.PositiveOrZero.message = tiene que ser mayor o igual a 0 -javax.validation.constraints.Size.message = el tama\u00F1o tiene que estar entre {min} y {max} +javax.validation.constraints.AssertFalse.message = debe ser falso +javax.validation.constraints.AssertTrue.message = debe ser verdadero +javax.validation.constraints.DecimalMax.message = debe ser menor que ${inclusive == true ? 'o igual a ' : ''}{value} +javax.validation.constraints.DecimalMin.message = debe ser mayor que ${inclusive == true ? 'o igual a ' : ''}{value} +javax.validation.constraints.Digits.message = valor num\u00e9rico fuera de l\u00edmites (se esperaba <{integer} d\u00edgitos>.<{fraction} d\u00edgitos>) +javax.validation.constraints.Email.message = debe ser una direcci\u00f3n de correo electr\u00f3nico con formato correcto +javax.validation.constraints.Future.message = debe ser una fecha futura +javax.validation.constraints.FutureOrPresent.message = debe ser una fecha en el presente o en el futuro +javax.validation.constraints.Max.message = debe ser menor que o igual a {value} +javax.validation.constraints.Min.message = debe ser mayor que o igual a {value} +javax.validation.constraints.Negative.message = debe ser menor que 0 +javax.validation.constraints.NegativeOrZero.message = debe ser menor que o igual a 0 +javax.validation.constraints.NotBlank.message = no debe estar en blanco +javax.validation.constraints.NotEmpty.message = no debe estar vac\u00edo +javax.validation.constraints.NotNull.message = no debe ser nulo +javax.validation.constraints.Null.message = debe ser nulo +javax.validation.constraints.Past.message = debe ser una fecha pasada +javax.validation.constraints.PastOrPresent.message = debe ser una fecha en el pasado o en el presente +javax.validation.constraints.Pattern.message = debe coincidir con "{regexp}" +javax.validation.constraints.Positive.message = debe ser mayor que 0 +javax.validation.constraints.PositiveOrZero.message = debe ser mayor que o igual a 0 +javax.validation.constraints.Size.message = el tama\u00f1o debe estar entre {min} y {max} -org.hibernate.validator.constraints.CreditCardNumber.message = n\u00FAmero de tarjeta inv\u00E1lido -org.hibernate.validator.constraints.Currency.message = mon\u00E9da inv\u00E1lida (tiene que ser una de {value}) -org.hibernate.validator.constraints.EAN.message = c\u00F3digo de barras {type} inv\u00E1lido -org.hibernate.validator.constraints.Email.message = no es una direcci\u00F3n de correo bien formada -org.hibernate.validator.constraints.ISBN.message = ISBN inv\u00E1lido -org.hibernate.validator.constraints.Length.message = la longitud tiene que estar entre {min} y {max} -org.hibernate.validator.constraints.CodePointLength.message = la longitud tiene que estar entre {min} y {max} -org.hibernate.validator.constraints.LuhnCheck.message = el d\u00EDgito de verificaci\u00F3n para ${validatedValue} es inv\u00E1lido, la suma de verificaci\u00F3n Luhn M\u00F3dulo 10 fall\u00F3 -org.hibernate.validator.constraints.Mod10Check.message = el d\u00EDgito de verificaci\u00F3n para ${validatedValue} es inv\u00E1lido, la suma de verificaci\u00F3n M\u00F3dulo 10 fall\u00F3 -org.hibernate.validator.constraints.Mod11Check.message = el d\u00EDgito de verificaci\u00F3n para ${validatedValue} es inv\u00E1lido, la suma de verificaci\u00F3n M\u00F3dulo 11 fall\u00F3 -org.hibernate.validator.constraints.ModCheck.message = el d\u00EDgito de verificaci\u00F3n para ${validatedValue} es inv\u00E1lido, la suma de verificaci\u00F3n ${modType} fall\u00F3 -org.hibernate.validator.constraints.NotBlank.message = no puede estar vac\u00EDo -org.hibernate.validator.constraints.NotEmpty.message = no puede estar vac\u00EDo -org.hibernate.validator.constraints.ParametersScriptAssert.message = la expresi\u00F3n "{script}" no se ha evaluado como verdadera -org.hibernate.validator.constraints.Range.message = tiene que estar entre {min} y {max} -org.hibernate.validator.constraints.SafeHtml.message = puede tener un contenido html inseguro -org.hibernate.validator.constraints.ScriptAssert.message = la expresi\u00F3n "{script}" no se ha evaluado como verdadera -org.hibernate.validator.constraints.UniqueElements.message = tiene que contener elementos \u00FAnicos -org.hibernate.validator.constraints.URL.message = tiene que ser una URL v\u00E1lida +org.hibernate.validator.constraints.CreditCardNumber.message = n\u00famero de tarjeta de cr\u00e9dito no v\u00e1lido +org.hibernate.validator.constraints.Currency.message = moneda no v\u00e1lida (debe ser una de {value}) +org.hibernate.validator.constraints.EAN.message = c\u00f3digo de barras {type} no v\u00e1lido +org.hibernate.validator.constraints.Email.message = no es una direcci\u00f3n de correo electr\u00f3nico con formato correcto +org.hibernate.validator.constraints.ISBN.message = ISBN no v\u00e1lido +org.hibernate.validator.constraints.Length.message = la longitud debe estar entre {min} y {max} +org.hibernate.validator.constraints.CodePointLength.message = la longitud debe estar entre {min} y {max} +org.hibernate.validator.constraints.LuhnCheck.message = el d\u00edgito de comprobaci\u00f3n para ${validatedValue} no es v\u00e1lido, ha fallado la suma de comprobaci\u00f3n de Luhn Modulo 10 +org.hibernate.validator.constraints.Mod10Check.message = el d\u00edgito de comprobaci\u00f3n para ${validatedValue} no es v\u00e1lido, ha fallado la suma de comprobaci\u00f3n de Modulo 10 +org.hibernate.validator.constraints.Mod11Check.message = el d\u00edgito de comprobaci\u00f3n para ${validatedValue} no es v\u00e1lido, ha fallado la suma de comprobaci\u00f3n de Modulo 11 +org.hibernate.validator.constraints.ModCheck.message = el d\u00edgito de comprobaci\u00f3n para ${validatedValue} no es v\u00e1lido, ha fallado la suma de comprobaci\u00f3n ${modType} +org.hibernate.validator.constraints.NotBlank.message = no puede estar vac\u00edo +org.hibernate.validator.constraints.NotEmpty.message = no puede estar vac\u00edo +org.hibernate.validator.constraints.ParametersScriptAssert.message = la expresi\u00f3n de script "{script}" no se ha evaluado en verdadera +org.hibernate.validator.constraints.Range.message = debe estar entre {min} y {max} +org.hibernate.validator.constraints.SafeHtml.message = puede tener contenido HTML no seguro +org.hibernate.validator.constraints.ScriptAssert.message = la expresi\u00f3n de script "{script}" no se ha evaluado en verdadera +org.hibernate.validator.constraints.UniqueElements.message = solo debe contener elementos exclusivos +org.hibernate.validator.constraints.URL.message = debe ser un URL v\u00e1lido -org.hibernate.validator.constraints.br.CNPJ.message = n\u00FAmero de identificaci\u00F3n tributario corporativo Brazile\u00F1o (CNPJ) inv\u00E1lido -org.hibernate.validator.constraints.br.CPF.message = n\u00FAmero de identificaci\u00F3n tributario individual Brazile\u00F1o (CPF) inv\u00E1lido -org.hibernate.validator.constraints.br.TituloEleitoral.message = n\u00FAmero de identificaci\u00F3n electoral Brazile\u00F1o inv\u00E1lido +org.hibernate.validator.constraints.br.CNPJ.message = n\u00famero de registro de contribuyente corporativo de Brasil no v\u00e1lido (CNPJ) +org.hibernate.validator.constraints.br.CPF.message = n\u00famero de registro de contribuyente individual de Brasil no v\u00e1lido (CPF) +org.hibernate.validator.constraints.br.TituloEleitoral.message = n\u00famero de tarjeta de ID de votante de Brasil no v\u00e1lido -org.hibernate.validator.constraints.pl.REGON.message = n\u00FAmero de identificaci\u00F3n tributario Polaco (REGON) inv\u00E1lido -org.hibernate.validator.constraints.pl.NIP.message = n\u00FAmero de identificaci\u00F3n VAT (NIP) inv\u00E1lido -org.hibernate.validator.constraints.pl.PESEL.message = n\u00FAmero de identificaci\u00F3n nacional Polaco (PESEL) inv\u00E1lido +org.hibernate.validator.constraints.pl.REGON.message = N\u00famero de Identificaci\u00f3n de Contribuyente de Polonia no v\u00e1lido (REGON) +org.hibernate.validator.constraints.pl.NIP.message = N\u00famero de Identificaci\u00f3n de VAT no v\u00e1lido (NIP) +org.hibernate.validator.constraints.pl.PESEL.message = N\u00famero de Identificaci\u00f3n Nacional de Polonia no v\u00e1lido (PESEL) -org.hibernate.validator.constraints.time.DurationMax.message = tiene que durar menos {inclusive == true ? ' o igual que' : ''}${days == 0 ? '' : days == 1 ? ' 1 d\u00EDa' : ' ' += days += ' d\u00EDs'}${hours == 0 ? '' : hours == 1 ? ' 1 hora' : ' ' += hours += ' horas'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minuto' : ' ' += minutes += ' minutos'}${seconds == 0 ? '' : seconds == 1 ? ' 1 segundo' : ' ' += seconds += ' segundos'}${millis == 0 ? '' : millis == 1 ? ' 1 milisegundo' : ' ' += millis += ' milisegundos'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanosegundo' : ' ' += nanos += ' nanosegundos'} -org.hibernate.validator.constraints.time.DurationMin.message = tiene que durar mas {inclusive == true ? ' o igual que' : ''}${days == 0 ? '' : days == 1 ? ' 1 d\u00EDa' : ' ' += days += ' d\u00EDs'}${hours == 0 ? '' : hours == 1 ? ' 1 hora' : ' ' += hours += ' horas'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minuto' : ' ' += minutes += ' minutos'}${seconds == 0 ? '' : seconds == 1 ? ' 1 segundo' : ' ' += seconds += ' segundos'}${millis == 0 ? '' : millis == 1 ? ' 1 milisegundo' : ' ' += millis += ' milisegundos'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanosegundo' : ' ' += nanos += ' nanosegundos'} +org.hibernate.validator.constraints.time.DurationMax.message = debe tener una longitud menor que ${inclusive == true ? ' o igual a' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} +org.hibernate.validator.constraints.time.DurationMin.message = debe tener una longitud mayor que ${inclusive == true ? ' o igual a' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties index 675fb5251a..932ac217d3 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties @@ -1,53 +1,53 @@ -javax.validation.constraints.AssertFalse.message = doit \u00EAtre faux -javax.validation.constraints.AssertTrue.message = doit \u00EAtre vrai -javax.validation.constraints.DecimalMax.message = doit \u00EAtre ${inclusive == false ? 'strictement ' : ''}inf\u00E9rieur ${inclusive == true ? 'ou \u00E9gal ' : ''}\u00E0 {value} -javax.validation.constraints.DecimalMin.message = doit \u00EAtre ${inclusive == false ? 'strictement ' : ''}sup\u00E9rieur ${inclusive == true ? 'ou \u00E9gal ' : ''}\u00E0 {value} -javax.validation.constraints.Digits.message = valeur num\u00E9rique hors limite (<{integer} chiffres>.<{fraction} chiffres> attendu) -javax.validation.constraints.Email.message = doit \u00EAtre une adresse email bien form\u00E9e -javax.validation.constraints.Future.message = doit \u00EAtre dans le futur -javax.validation.constraints.FutureOrPresent.message = doit \u00EAtre dans le pr\u00E9sent ou dans le futur -javax.validation.constraints.Max.message = doit \u00EAtre au maximum \u00E9gal \u00E0 {value} -javax.validation.constraints.Min.message = doit \u00EAtre au minimum \u00E9gal \u00E0 {value} -javax.validation.constraints.Negative.message = doit \u00EAtre strictement n\u00E9gatif -javax.validation.constraints.NegativeOrZero.message = doit \u00EAtre n\u00E9gatif ou \u00E9gal \u00E0 0 -javax.validation.constraints.NotBlank.message = ne peut pas \u00EAtre vide -javax.validation.constraints.NotEmpty.message = ne peut pas \u00EAtre vide -javax.validation.constraints.NotNull.message = ne peut pas \u00EAtre nul +javax.validation.constraints.AssertFalse.message = doit avoir la valeur faux +javax.validation.constraints.AssertTrue.message = doit avoir la valeur vrai +javax.validation.constraints.DecimalMax.message = doit \u00eatre inf\u00e9rieur \u00e0 ${inclusive == true ? ' ou \u00e9gal \u00e0 ' : ''}{value} +javax.validation.constraints.DecimalMin.message = doit \u00eatre sup\u00e9rieur \u00e0 ${inclusive == true ? ' ou \u00e9gal \u00e0 ' : ''}{value} +javax.validation.constraints.Digits.message = valeur num\u00e9rique hors limites (<{integer} chiffres>.<{fraction} chiffres> attendu) +javax.validation.constraints.Email.message = doit \u00eatre une adresse \u00e9lectronique syntaxiquement correcte +javax.validation.constraints.Future.message = doit \u00eatre une date dans le futur +javax.validation.constraints.FutureOrPresent.message = doit \u00eatre une date dans le pr\u00e9sent ou le futur +javax.validation.constraints.Max.message = doit \u00eatre inf\u00e9rieur ou \u00e9gal \u00e0 {value} +javax.validation.constraints.Min.message = doit \u00eatre sup\u00e9rieur ou \u00e9gal \u00e0 {value} +javax.validation.constraints.Negative.message = doit \u00eatre inf\u00e9rieur \u00e0 0 +javax.validation.constraints.NegativeOrZero.message = doit \u00eatre inf\u00e9rieur ou \u00e9gal \u00e0 0 +javax.validation.constraints.NotBlank.message = ne doit pas \u00eatre blanc +javax.validation.constraints.NotEmpty.message = ne doit pas \u00eatre vide +javax.validation.constraints.NotNull.message = ne doit pas avoir la valeur NULL javax.validation.constraints.Null.message = doit \u00EAtre nul -javax.validation.constraints.Past.message = doit \u00EAtre dans le pass\u00E9 -javax.validation.constraints.PastOrPresent.message = doit \u00EAtre dans le pass\u00E9 ou dans le pr\u00E9sent -javax.validation.constraints.Pattern.message = doit respecter "{regexp}" -javax.validation.constraints.Positive.message = doit \u00EAtre strictement positif -javax.validation.constraints.PositiveOrZero.message = doit \u00EAtre positif ou \u00E9gal \u00E0 0 -javax.validation.constraints.Size.message = la taille doit \u00EAtre comprise entre {min} et {max} +javax.validation.constraints.Past.message = doit \u00eatre une date dans le pass\u00e9 +javax.validation.constraints.PastOrPresent.message = doit \u00eatre une date dans le pass\u00e9 ou le pr\u00e9sent +javax.validation.constraints.Pattern.message = doit correspondre \u00e0 "{regexp}" +javax.validation.constraints.Positive.message = doit \u00eatre sup\u00e9rieur \u00e0 +javax.validation.constraints.PositiveOrZero.message = doit \u00eatre sup\u00e9rieur ou \u00e9gal \u00e0 0 +javax.validation.constraints.Size.message = la taille doit \u00eatre comprise entre {min} et {max} -org.hibernate.validator.constraints.CreditCardNumber.message = num\u00E9ro de carte de cr\u00E9dit invalide -org.hibernate.validator.constraints.Currency.message = devise invalide (doit faire partie de {value}) -org.hibernate.validator.constraints.EAN.message = code barre {type} invalide -org.hibernate.validator.constraints.Email.message = adresse email mal form\u00E9e -org.hibernate.validator.constraints.ISBN.message = ISBN invalide -org.hibernate.validator.constraints.Length.message = la longueur doit \u00EAtre comprise entre {min} et {max} caract\u00E8res -org.hibernate.validator.constraints.CodePointLength.message = la longueur doit \u00EAtre comprise entre {min} et {max} caract\u00E8res -org.hibernate.validator.constraints.LuhnCheck.message = le chiffre de contr\u00F4le pour ${validatedValue} est invalide, le contr\u00F4le Luhn Modulo 10 a \u00E9chou\u00E9 -org.hibernate.validator.constraints.Mod10Check.message = le chiffre de contr\u00F4le pour ${validatedValue} est invalide, le contr\u00F4le Modulo 10 a \u00E9chou\u00E9 -org.hibernate.validator.constraints.Mod11Check.message = le chiffre de contr\u00F4le pour ${validatedValue} est invalide, le contr\u00F4le Modulo 11 a \u00E9chou\u00E9 -org.hibernate.validator.constraints.ModCheck.message = le chiffre de contr\u00F4le pour ${validatedValue} est invalide, le contr\u00F4le ${modType} a \u00E9chou\u00E9 -org.hibernate.validator.constraints.NotBlank.message = ne peut pas \u00EAtre vide -org.hibernate.validator.constraints.NotEmpty.message = ne peut pas \u00EAtre vide +org.hibernate.validator.constraints.CreditCardNumber.message = num\u00e9ro de carte de cr\u00e9dit non valide +org.hibernate.validator.constraints.Currency.message = devise non valide (il doit s'agit de l'une des valeurs suivantes : {value}) +org.hibernate.validator.constraints.EAN.message = code \u00e0 barres {type} non valide +org.hibernate.validator.constraints.Email.message = adresse \u00e9lectronique incorrecte syntaxiquement +org.hibernate.validator.constraints.ISBN.message = ISBN non valide +org.hibernate.validator.constraints.Length.message = la longueur doit \u00eatre comprise entre {min} et {max} +org.hibernate.validator.constraints.CodePointLength.message = la longueur doit \u00eatre comprise entre {min} et {max} +org.hibernate.validator.constraints.LuhnCheck.message = le chiffre cl\u00e9 pour ${validatedValue} n'est pas valide ; la somme de contr\u00f4le de l'algorithme de Luhn (modulo 10) a \u00e9chou\u00e9 +org.hibernate.validator.constraints.Mod10Check.message = le chiffre cl\u00e9 pour ${validatedValue} n'est pas valide ; la somme de contr\u00f4le de l'algorithme modulo 10 a \u00e9chou\u00e9 +org.hibernate.validator.constraints.Mod11Check.message = le chiffre cl\u00e9 pour ${validatedValue} n'est pas valide ; la somme de contr\u00f4le de l'algorithme modulo 11 a \u00e9chou\u00e9 +org.hibernate.validator.constraints.ModCheck.message = le chiffre cl\u00e9 pour ${validatedValue} n'est pas valide ; la somme de contr\u00f4le de l'algorithme ${modType} a \u00e9chou\u00e9 +org.hibernate.validator.constraints.NotBlank.message = ne peut pas \u00eatre vide +org.hibernate.validator.constraints.NotEmpty.message = ne peut pas \u00eatre vide org.hibernate.validator.constraints.ParametersScriptAssert.message = le script "{script}" n'a pas \u00E9t\u00E9 \u00E9valu\u00E9 \u00E0 vrai -org.hibernate.validator.constraints.Range.message = doit \u00EAtre entre {min} et {max} -org.hibernate.validator.constraints.SafeHtml.message = peut contenir du HTML dangereux -org.hibernate.validator.constraints.ScriptAssert.message = le script "{script}" n'a pas \u00E9t\u00E9 \u00E9valu\u00E9 \u00E0 vrai -org.hibernate.validator.constraints.UniqueElements.message = ne doit contenir que des \u00E9l\u00E9ments uniques -org.hibernate.validator.constraints.URL.message = URL mal form\u00E9e +org.hibernate.validator.constraints.Range.message = doit \u00eatre compris entre {min} et {max} +org.hibernate.validator.constraints.SafeHtml.message = peut comporter un contenu html non s\u00e9curis\u00e9 +org.hibernate.validator.constraints.ScriptAssert.message = l'\u00e9valuation de l'expression de script "{script}" n'est pas true +org.hibernate.validator.constraints.UniqueElements.message = doit contenir des \u00e9l\u00e9ments uniques seulement +org.hibernate.validator.constraints.URL.message = doit \u00eatre une URL valide -org.hibernate.validator.constraints.br.CNPJ.message = num\u00E9ro d'enregistrement br\u00E9silien de soci\u00E9t\u00E9 contribuable (CNPJ) invalide -org.hibernate.validator.constraints.br.CPF.message = num\u00E9ro d'enregistrement br\u00E9silien de contribuable individuel (CPF) invalide -org.hibernate.validator.constraints.br.TituloEleitoral.message = num\u00E9ro de carte d'\u00E9lecteur br\u00E9silienne invalide +org.hibernate.validator.constraints.br.CNPJ.message = num\u00e9ro de registre d'entreprise contribuable br\u00e9silien non valide (CNPJ) +org.hibernate.validator.constraints.br.CPF.message = num\u00e9ro de registre de contribuable individuel br\u00e9silien non valide (CPF) +org.hibernate.validator.constraints.br.TituloEleitoral.message = num\u00e9ro de carte d'\u00e9lecteur br\u00e9silien non valide -org.hibernate.validator.constraints.pl.REGON.message = num\u00E9ro d'imposition polonais (REGON) invalide -org.hibernate.validator.constraints.pl.NIP.message = num\u00E9ro d'identification de TVA polonais (NIP) invalide -org.hibernate.validator.constraints.pl.PESEL.message = num\u00E9ro d'identification national polonais (PESEL) invalide +org.hibernate.validator.constraints.pl.REGON.message = num\u00e9ro d'identification de contribuable polonais non valide (REGON) +org.hibernate.validator.constraints.pl.NIP.message = num\u00e9ro de TVA non valide (NIP) +org.hibernate.validator.constraints.pl.PESEL.message = num\u00e9ro de carte d'identit\u00e9 nationale polonais non valide (PESEL) -org.hibernate.validator.constraints.time.DurationMax.message = doit \u00EAtre plus court que${inclusive == true ? ' ou \u00E9gal \u00E0' : ''}${days == 0 ? '' : days == 1 ? ' 1 jour' : ' ' += days += ' jours'}${hours == 0 ? '' : hours == 1 ? ' 1 heure' : ' ' += hours += ' heures'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 seconde' : ' ' += seconds += ' secondes'}${millis == 0 ? '' : millis == 1 ? ' 1 milliseconde' : ' ' += millis += ' millisecondes'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanoseconde' : ' ' += nanos += ' nanosecondes'} -org.hibernate.validator.constraints.time.DurationMin.message = doit \u00EAtre plus long que${inclusive == true ? ' ou \u00E9gal \u00E0' : ''}${days == 0 ? '' : days == 1 ? ' 1 jour' : ' ' += days += ' jours'}${hours == 0 ? '' : hours == 1 ? ' 1 heure' : ' ' += hours += ' heures'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 seconde' : ' ' += seconds += ' secondes'}${millis == 0 ? '' : millis == 1 ? ' 1 milliseconde' : ' ' += millis += ' millisecondes'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanoseconde' : ' ' += nanos += ' nanosecondes'} +org.hibernate.validator.constraints.time.DurationMax.message = doit \u00eatre plus court que ${inclusive == true ? ' ou \u00e9gal \u00e0 ' : ''}${days == 0 ? '' : days == 1 ? ' 1 jour' : ' ' += days += ' jours'}${hours == 0 ? '' : hours == 1 ? ' 1 heure' : ' ' += hours += ' heures'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 seconde' : ' ' += seconds += ' secondes'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} +org.hibernate.validator.constraints.time.DurationMin.message = doit \u00eatre plus long que ${inclusive == true ? ' ou \u00e9gal \u00e0 ' : ''}${days == 0 ? '' : days == 1 ? ' 1 jour' : ' ' += days += ' jours'}${hours == 0 ? '' : hours == 1 ? ' 1 heure' : ' ' += hours += ' heures'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 seconde' : ' ' += seconds += ' secondes'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_hu.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_hu.properties index 05fa1151f3..1cee6de3e0 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_hu.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_hu.properties @@ -1,27 +1,53 @@ -javax.validation.constraints.AssertFalse.message = hamis kell legyen -javax.validation.constraints.AssertTrue.message = igaz kell legyen -javax.validation.constraints.DecimalMax.message = kisebb vagy egyenl\u0151 kell legyen mint {value} -javax.validation.constraints.DecimalMin.message = nagyobb vagy egyenl\u0151 kell legyen mint {value} -javax.validation.constraints.Digits.message = a sz\u00E1mform\u00E1tum nem felel meg a k\u00F6vetkez\u0151 form\u00E1nak\: <{integer} sz\u00E1mjegy>.<{fraction} tizedesjegy> -javax.validation.constraints.Email.message = nem felel meg az email c\u00EDmek form\u00E1tum\u00E1nak -javax.validation.constraints.Future.message = a j\u00F6v\u0151ben kell lennie -javax.validation.constraints.Max.message = kisebb vagy egyenl\u0151 kell legyen mint {value} -javax.validation.constraints.Min.message = nagyobb vagy egyenl\u0151 kell legyen mint {value} -javax.validation.constraints.NotBlank.message = nem lehet \u00FCres -javax.validation.constraints.NotEmpty.message = nem lehet \u00FCres -javax.validation.constraints.NotNull.message = nem lehet null-\u00E9rt\u00E9k -javax.validation.constraints.Null.message = null-\u00E9rt\u00E9knek kell lennie -javax.validation.constraints.Past.message = a m\u00FAltban kell lennie -javax.validation.constraints.Pattern.message = meg kell felelnie a "{regexp}" regul\u00E1ris kifejez\u00E9snek -javax.validation.constraints.Size.message = a m\u00E9retnek {min} \u00E9s {max} k\u00F6z\u00F6tt kell lennie +javax.validation.constraints.AssertFalse.message = hamis \u00e9rt\u00e9k\u0171nek kell lennie +javax.validation.constraints.AssertTrue.message = igaz \u00e9rt\u00e9k\u0171nek kell lennie +javax.validation.constraints.DecimalMax.message = kisebbnek ${inclusive == true ? 'or equal to ' : ''} kell lennie, mint {value} +javax.validation.constraints.DecimalMin.message = nagyobbnak ${inclusive == true ? 'or equal to ' : ''} kell lennie, mint {value} +javax.validation.constraints.Digits.message = a numerikus \u00e9rt\u00e9k a korl\u00e1tokon k\u00edv\u00fcl esik (<{integer} sz\u00e1mjegy>.<{fraction} sz\u00e1mjegy> sz\u00e1mot v\u00e1rt a rendszer) +javax.validation.constraints.Email.message = helyes form\u00e1tum\u00fa e-mail c\u00edmnek kell lennie +javax.validation.constraints.Future.message = j\u00f6v\u0151beli d\u00e1tumnak kell lennie +javax.validation.constraints.FutureOrPresent.message = jelen vagy j\u00f6v\u0151beli d\u00e1tumnak kell lennie +javax.validation.constraints.Max.message = kisebbnek, vagy egyenl\u0151nek kell lennie, mint {value} +javax.validation.constraints.Min.message = nagyobbnak, vagy egyenl\u0151nek kell lennie, mint {value} +javax.validation.constraints.Negative.message = kisebbnek kell lennie, mint 0 +javax.validation.constraints.NegativeOrZero.message = kisebbnek, vagy egyenl\u0151nek kell lennie, mint 0 +javax.validation.constraints.NotBlank.message = nem lehet \u00fcres +javax.validation.constraints.NotEmpty.message = nem lehet \u00fcres +javax.validation.constraints.NotNull.message = nem lehet null +javax.validation.constraints.Null.message = null\u00e9rt\u00e9k\u0171nek kell lennie +javax.validation.constraints.Past.message = m\u00faltbeli d\u00e1tumnak kell lennie +javax.validation.constraints.PastOrPresent.message = m\u00faltbeli vagy jelen d\u00e1tumnak kell lennie +javax.validation.constraints.Pattern.message = meg kell felelnie a(z) "{regexp}" kifejez\u00e9snek +javax.validation.constraints.Positive.message = nagyobbnak kell lennie, mint 0 +javax.validation.constraints.PositiveOrZero.message = nagyobbnak vagy egyenl\u0151nek kell lennie, mint 0 +javax.validation.constraints.Size.message = a m\u00e9retnek a(z) {min} \u00e9s {max} \u00e9rt\u00e9kek k\u00f6z\u00f6tt kell lennie -org.hibernate.validator.constraints.CreditCardNumber.message = hib\u00E1s hitelk\u00E1rtyasz\u00E1m -org.hibernate.validator.constraints.Email.message = nem felel meg az email c\u00EDmek form\u00E1tum\u00E1nak -org.hibernate.validator.constraints.Length.message = a hossznak {min} \u00E9s {max} k\u00F6z\u00F6tt kell lennie -org.hibernate.validator.constraints.CodePointLength.message = a hossznak {min} \u00E9s {max} k\u00F6z\u00F6tt kell lennie -org.hibernate.validator.constraints.NotBlank.message = nem lehet \u00FCres -org.hibernate.validator.constraints.NotEmpty.message = nem lehet \u00FCres -org.hibernate.validator.constraints.Range.message = az \u00E9rt\u00E9knek {min} \u00E9s {max} k\u00F6z\u00F6tt kell lennie -org.hibernate.validator.constraints.SafeHtml.message = lehet, hogy nem biztons\u00E1gos html tartalom -org.hibernate.validator.constraints.ScriptAssert.message = script kifejez\u00E9s "{script}" nem \u00E9rt\u00E9kel\u0151d\u00F6tt ki igazz\u00E1 -org.hibernate.validator.constraints.URL.message = \u00E9rv\u00E9nyes URL-nek kell lennie +org.hibernate.validator.constraints.CreditCardNumber.message = \u00e9rv\u00e9nytelen hitelk\u00e1rtyasz\u00e1m +org.hibernate.validator.constraints.Currency.message = \u00e9rv\u00e9nytelen p\u00e9nznem (a k\u00f6vetkez\u0151k egyike lehet: {value}) +org.hibernate.validator.constraints.EAN.message = \u00e9rv\u00e9nytelen {type} vonalk\u00f3d +org.hibernate.validator.constraints.Email.message = nem helyes form\u00e1tum\u00fa e-mail c\u00edm +org.hibernate.validator.constraints.ISBN.message = \u00e9rv\u00e9nytelen ISBN +org.hibernate.validator.constraints.Length.message = a hossznak a(z) {min} \u00e9s {max} \u00e9rt\u00e9kek k\u00f6z\u00f6tt kell lennie +org.hibernate.validator.constraints.CodePointLength.message = a hossznak a(z) {min} \u00e9s {max} \u00e9rt\u00e9kek k\u00f6z\u00f6tt kell lennie +org.hibernate.validator.constraints.LuhnCheck.message = a(z) ${validatedValue} ellen\u0151rz\u0151 sz\u00e1mjegye \u00e9rv\u00e9nytelen, a Luhn Modulo 10 ellen\u0151rz\u0151\u00f6sszeg meghi\u00fasult +org.hibernate.validator.constraints.Mod10Check.message = a(z) ${validatedValue} ellen\u0151rz\u0151 sz\u00e1mjegye \u00e9rv\u00e9nytelen, a Modulo 10 ellen\u0151rz\u0151\u00f6sszeg meghi\u00fasult +org.hibernate.validator.constraints.Mod11Check.message = a(z) ${validatedValue} ellen\u0151rz\u0151 sz\u00e1mjegye \u00e9rv\u00e9nytelen, a Modulo 11 ellen\u0151rz\u0151\u00f6sszeg meghi\u00fasult +org.hibernate.validator.constraints.ModCheck.message = a(z) ${validatedValue} ellen\u0151rz\u0151 sz\u00e1mjegye \u00e9rv\u00e9nytelen, a(z) ${modType} ellen\u0151rz\u0151\u00f6sszeg meghi\u00fasult +org.hibernate.validator.constraints.NotBlank.message = nem lehet \u00fcres +org.hibernate.validator.constraints.NotEmpty.message = nem lehet \u00fcres +org.hibernate.validator.constraints.ParametersScriptAssert.message = a(z) "{script}" parancsf\u00e1jl kifejez\u00e9s nem true \u00e9rt\u00e9kre \u00e9rt\u00e9kel\u0151d\u00f6tt ki +org.hibernate.validator.constraints.Range.message = a(z) {min} \u00e9s {max} \u00e9rt\u00e9kek k\u00f6z\u00f6tt kell lennie +org.hibernate.validator.constraints.SafeHtml.message = lehets\u00e9ges nem biztons\u00e1gos html tartalom +org.hibernate.validator.constraints.ScriptAssert.message = a(z) "{script}" parancsf\u00e1jl kifejez\u00e9s nem true \u00e9rt\u00e9kre \u00e9rt\u00e9kel\u0151d\u00f6tt ki +org.hibernate.validator.constraints.UniqueElements.message = csak egyedi elemeket tartalmazhat +org.hibernate.validator.constraints.URL.message = egy \u00e9rv\u00e9nyes URL c\u00edmnek kell lennie + +org.hibernate.validator.constraints.br.CNPJ.message = \u00e9rv\u00e9nytelen brazil v\u00e1llalati ad\u00f3nyilv\u00e1ntart\u00e1si sz\u00e1m (CNPJ) +org.hibernate.validator.constraints.br.CPF.message = \u00e9rv\u00e9nytelen brazil egy\u00e9ni ad\u00f3nyilv\u00e1ntart\u00e1si sz\u00e1m (CPF) +org.hibernate.validator.constraints.br.TituloEleitoral.message = \u00e9rv\u00e9nytelen brazil szavaz\u00f3azonos\u00edt\u00f3 k\u00e1rtyasz\u00e1m + +org.hibernate.validator.constraints.pl.REGON.message = \u00e9rv\u00e9nytelen lengyel ad\u00f3z\u00f3i azonos\u00edt\u00f3 sz\u00e1m (REGON) +org.hibernate.validator.constraints.pl.NIP.message = \u00e9rv\u00e9nytelen \u00c1FA azonos\u00edt\u00f3sz\u00e1m (NIP) +org.hibernate.validator.constraints.pl.PESEL.message = \u00e9rv\u00e9nytelen lengyel nemzeti azonos\u00edt\u00f3sz\u00e1m (PESEL) + +org.hibernate.validator.constraints.time.DurationMax.message = r\u00f6videbbnek kell lennie, mint ${inclusive == true ? ' or equal to' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} +org.hibernate.validator.constraints.time.DurationMin.message = hosszabbnak kell lennie, mint ${inclusive == true ? ' or equal to' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_it.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_it.properties new file mode 100644 index 0000000000..95e07c9d9e --- /dev/null +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_it.properties @@ -0,0 +1,53 @@ +javax.validation.constraints.AssertFalse.message = deve essere false +javax.validation.constraints.AssertTrue.message = deve essere true +javax.validation.constraints.DecimalMax.message = deve essere inferiore a ${inclusive == true ? 'o uguale a ' : ''}{value} +javax.validation.constraints.DecimalMin.message = deve essere superiore a ${inclusive == true ? 'o uguale a ' : ''}{value} +javax.validation.constraints.Digits.message = valore numerico fuori dai limiti (previsto <{integer} digits>.<{fraction} digits>) +javax.validation.constraints.Email.message = deve essere un indirizzo email nel formato corretto +javax.validation.constraints.Future.message = deve essere una data nel futuro +javax.validation.constraints.FutureOrPresent.message = deve essere una data nel presente o nel futuro +javax.validation.constraints.Max.message = deve essere inferiore o uguale a {value} +javax.validation.constraints.Min.message = deve essere superiore o uguale a {value} +javax.validation.constraints.Negative.message = deve essere inferiore a 0 +javax.validation.constraints.NegativeOrZero.message = deve essere inferiore o uguale a 0 +javax.validation.constraints.NotBlank.message = non deve essere spazio +javax.validation.constraints.NotEmpty.message = non deve essere vuoto +javax.validation.constraints.NotNull.message = non deve essere null +javax.validation.constraints.Null.message = deve essere null +javax.validation.constraints.Past.message = deve essere una data nel passato +javax.validation.constraints.PastOrPresent.message = deve essere una data nel passato o nel presente +javax.validation.constraints.Pattern.message = deve corrispondere a "{regexp}" +javax.validation.constraints.Positive.message = deve essere superiore a 0 +javax.validation.constraints.PositiveOrZero.message = deve essere superiore o uguale a 0 +javax.validation.constraints.Size.message = la dimensione deve essere compresa tra {min} e {max} + +org.hibernate.validator.constraints.CreditCardNumber.message = numero carta di credito non valido +org.hibernate.validator.constraints.Currency.message = valuta non valida (deve essere una di {value}) +org.hibernate.validator.constraints.EAN.message = codicie a barre {type} non valido +org.hibernate.validator.constraints.Email.message = non \u00e8 un indirizzo email nel formato corretto +org.hibernate.validator.constraints.ISBN.message = ISBN non valido +org.hibernate.validator.constraints.Length.message = la lunghezza deve essere compresa tra {min} e {max} +org.hibernate.validator.constraints.CodePointLength.message = la lunghezza deve essere compresa tra {min} e {max} +org.hibernate.validator.constraints.LuhnCheck.message = La cifra di controllo per ${validatedValue} non \u00e8 valida, checksum Luhn Modulo 10 non riuscito +org.hibernate.validator.constraints.Mod10Check.message = La cifra di controllo per ${validatedValue} non \u00e8 valida, checksum Modulo 10 non riuscito +org.hibernate.validator.constraints.Mod11Check.message = La cifra di controllo per ${validatedValue} non \u00e8 valida, checksum Modulo 11 non riuscito +org.hibernate.validator.constraints.ModCheck.message = La cifra di controllo per ${validatedValue} non \u00e8 valida, checksum ${modType} non riuscito +org.hibernate.validator.constraints.NotBlank.message = non pu\u00f2 essere vuoto +org.hibernate.validator.constraints.NotEmpty.message = non pu\u00f2 essere vuoto +org.hibernate.validator.constraints.ParametersScriptAssert.message = espressione script "{script}" non valutata true +org.hibernate.validator.constraints.Range.message = deve essere compresa tra {min} e {max} +org.hibernate.validator.constraints.SafeHtml.message = ha contenuto html non sicuro +org.hibernate.validator.constraints.ScriptAssert.message = espressione script "{script}" non valutata true +org.hibernate.validator.constraints.UniqueElements.message = deve contenere solo elementi univoci +org.hibernate.validator.constraints.URL.message = deve essere un URL valido + +org.hibernate.validator.constraints.br.CNPJ.message = numero registro contribuente aziendale (CNPJ) brasiliano non valido +org.hibernate.validator.constraints.br.CPF.message = numero registro contribuente individuale (CPF) brasiliano non valido +org.hibernate.validator.constraints.br.TituloEleitoral.message = numero scheda ID votante brasiliano non valido + +org.hibernate.validator.constraints.pl.REGON.message = Numero identificativo contribuente polacco (REGON) non valido +org.hibernate.validator.constraints.pl.NIP.message = Numero identificativo IVA (NIP) non valido +org.hibernate.validator.constraints.pl.PESEL.message = Numero identificativo nazionale polacco (PESEL) non valido + +org.hibernate.validator.constraints.time.DurationMax.message = deve essere inferiore a ${inclusive == true ? ' o uguale a' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} +org.hibernate.validator.constraints.time.DurationMin.message = deve essere superiore a ${inclusive == true ? ' o uguale a' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ko.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ko.properties index aa839b8366..86e2b6ca0f 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ko.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ko.properties @@ -1,36 +1,53 @@ -javax.validation.constraints.AssertFalse.message = \ubc18\ub4dc\uc2dc \uac70\uc9d3(false)\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.AssertTrue.message = \ubc18\ub4dc\uc2dc \ucc38(true)\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.DecimalMax.message = \ubc18\ub4dc\uc2dc {value}\ubcf4\ub2e4 ${inclusive == true ? '\uac19\uac70\ub098 \uc791\uc5b4\uc57c \ud569\ub2c8\ub2e4. ' : '\uc791\uc544\uc57c \ud569\ub2c8\ub2e4.'} -javax.validation.constraints.DecimalMin.message = \ubc18\ub4dc\uc2dc {value}\ubcf4\ub2e4 ${inclusive == true ? '\uac19\uac70\ub098 \ucee4\uc57c \ud569\ub2c8\ub2e4. ' : '\ucee4\uc57c \ud569\ub2c8\ub2e4.'} -javax.validation.constraints.Digits.message = \uc22b\uc790 \uac12\uc774 \ud5c8\uc6a9 \ubc94\uc704\ub97c \ubc97\uc5b4\ub0a9\ub2c8\ub2e4. (\ud5c8\uc6a9 \ubc94\uc704: <{integer} \uc790\ub9ac>.<{fraction} \uc790\ub9ac>) -javax.validation.constraints.Email.message = \uc774\uba54\uc77c \uc8fc\uc18c\uac00 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. -javax.validation.constraints.Future.message = \ubc18\ub4dc\uc2dc \ubbf8\ub798 \ub0a0\uc9dc\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.Max.message = \ubc18\ub4dc\uc2dc {value}\ubcf4\ub2e4 \uac19\uac70\ub098 \uc791\uc544\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.Min.message = \ubc18\ub4dc\uc2dc {value}\ubcf4\ub2e4 \uac19\uac70\ub098 \ucee4\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.NotBlank.message = \ubc18\ub4dc\uc2dc \uac12\uc774 \uc874\uc7ac\ud558\uace0 \uacf5\ubc31 \ubb38\uc790\ub97c \uc81c\uc678\ud55c \uae38\uc774\uac00 0\ubcf4\ub2e4 \ucee4\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.NotEmpty.message = \ubc18\ub4dc\uc2dc \uac12\uc774 \uc874\uc7ac\ud558\uace0 \uae38\uc774 \ud639\uc740 \ud06c\uae30\uac00 0\ubcf4\ub2e4 \ucee4\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.NotNull.message = \ubc18\ub4dc\uc2dc \uac12\uc774 \uc788\uc5b4\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.Null.message = \ubc18\ub4dc\uc2dc \uac12\uc774 \uc5c6\uc5b4\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.Past.message = \ubc18\ub4dc\uc2dc \uacfc\uac70 \ub0a0\uc9dc\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.Pattern.message = \uc815\uaddc \ud45c\ud604\uc2dd "{regexp}" \ud328\ud134\uacfc \uc77c\uce58\ud574\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.Size.message = \ubc18\ub4dc\uc2dc \ucd5c\uc18c\uac12 {min}\uacfc(\uc640) \ucd5c\ub300\uac12 {max} \uc0ac\uc774\uc758 \ud06c\uae30\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.AssertFalse.message = false\uc5ec\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.AssertTrue.message = true\uc5ec\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.DecimalMax.message = \ub2e4\uc74c \uac12 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4${inclusive == true ? ' ' : ''}{value} +javax.validation.constraints.DecimalMin.message = \ub2e4\uc74c \uac12 \uc774\uc0c1\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4${inclusive == true ? ' ' : ''}{value} +javax.validation.constraints.Digits.message = \uc22b\uc790 \uac12\uc774 \ud55c\uacc4\ub97c \ucd08\uacfc\ud569\ub2c8\ub2e4(<{integer} \uc790\ub9ac>.<{fraction} \uc790\ub9ac> \uc608\uc0c1). +javax.validation.constraints.Email.message = \uc62c\ubc14\ub978 \ud615\uc2dd\uc758 \uc774\uba54\uc77c \uc8fc\uc18c\uc5ec\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.Future.message = \ubbf8\ub798 \ub0a0\uc9dc\uc5ec\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.FutureOrPresent.message = \ud604\uc7ac \ub610\ub294 \ubbf8\ub798\uc758 \ub0a0\uc9dc\uc5ec\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.Max.message = {value} \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.Min.message = {value} \uc774\uc0c1\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.Negative.message = 0 \ubbf8\ub9cc\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.NegativeOrZero.message = 0 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.NotBlank.message = \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +javax.validation.constraints.NotEmpty.message = \ube44\uc5b4 \uc788\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +javax.validation.constraints.NotNull.message = \ub110\uc774\uc5b4\uc11c\ub294 \uc548\ub429\ub2c8\ub2e4. +javax.validation.constraints.Null.message = \ub110\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.Past.message = \uacfc\uac70 \ub0a0\uc9dc\uc5ec\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.PastOrPresent.message = \uacfc\uac70 \ub610\ub294 \ud604\uc7ac\uc758 \ub0a0\uc9dc\uc5ec\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.Pattern.message = "{regexp}"\uc640 \uc77c\uce58\ud574\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.Positive.message = 0\ubcf4\ub2e4 \ucee4\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.PositiveOrZero.message = 0 \uc774\uc0c1\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.Size.message = \ud06c\uae30\uac00 {min}\uc5d0\uc11c {max} \uc0ac\uc774\uc5ec\uc57c \ud569\ub2c8\ub2e4. -org.hibernate.validator.constraints.CreditCardNumber.message = \uc2e0\uc6a9\uce74\ub4dc \ubc88\ud638\uac00 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.EAN.message = {type} \ubc14\ucf54\ub4dc\uac00 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.Email.message = \uc774\uba54\uc77c \uc8fc\uc18c\uac00 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.Length.message = \ubc18\ub4dc\uc2dc \ucd5c\uc18c\uac12 {min}\uacfc(\uc640) \ucd5c\ub300\uac12 {max} \uc0ac\uc774\uc758 \uae38\uc774\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. -org.hibernate.validator.constraints.CodePointLength.message = \ubc18\ub4dc\uc2dc \ucd5c\uc18c\uac12 {min}\uacfc(\uc640) \ucd5c\ub300\uac12 {max} \uc0ac\uc774\uc758 \uae38\uc774\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. -org.hibernate.validator.constraints.LuhnCheck.message = ${value}\uc758 check digit\uac00 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. Luhn Modulo 10 checksum \uc624\ub958\uac00 \ubc1c\uc0dd\ud558\uc600\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.Mod10Check.message = ${value}\uc758 check digit\uac00 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. Modulo 10 checksum \uc624\ub958\uac00 \ubc1c\uc0dd\ud558\uc600\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.Mod11Check.message = ${value}\uc758 check digit\uac00 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. Modulo 11 checksum \uc624\ub958\uac00 \ubc1c\uc0dd\ud558\uc600\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.ModCheck.message = ${value}\uc758 check digit\uac00 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. ${modType} checksum \uc624\ub958\uac00 \ubc1c\uc0dd\ud558\uc600\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.NotBlank.message = \ubc18\ub4dc\uc2dc \uac12\uc774 \uc874\uc7ac\ud558\uace0 \uacf5\ubc31 \ubb38\uc790\ub97c \uc81c\uc678\ud55c \uae38\uc774\uac00 0\ubcf4\ub2e4 \ucee4\uc57c \ud569\ub2c8\ub2e4. -org.hibernate.validator.constraints.NotEmpty.message = \ubc18\ub4dc\uc2dc \uac12\uc774 \uc874\uc7ac\ud558\uace0 \uae38\uc774 \ud639\uc740 \ud06c\uae30\uac00 0\ubcf4\ub2e4 \ucee4\uc57c \ud569\ub2c8\ub2e4. -org.hibernate.validator.constraints.ParametersScriptAssert.message = \uc2a4\ud06c\ub9bd\ud2b8 \ud45c\ud604\uc2dd "{script}"\uc758 \uacb0\uacfc\uac00 \ucc38(true)\uc774 \uc544\ub2d9\ub2c8\ub2e4. -org.hibernate.validator.constraints.Range.message = \ubc18\ub4dc\uc2dc \ucd5c\uc18c\uac12 {min}\uacfc(\uc640) \ucd5c\ub300\uac12 {max} \uc0ac\uc774\uc758 \ubc94\uc704\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. -org.hibernate.validator.constraints.SafeHtml.message = \ud5c8\uc6a9\ub418\uc9c0 \uc54a\uc740 HTML \ucf54\ub4dc\uac00 \ud3ec\ud568\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.ScriptAssert.message = \uc2a4\ud06c\ub9bd\ud2b8 \ud45c\ud604\uc2dd "{script}"\uc758 \uacb0\uacfc\uac00 \ucc38(true)\uc774 \uc544\ub2d9\ub2c8\ub2e4. -org.hibernate.validator.constraints.URL.message = URL\uc774 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.br.CNPJ.message = \ube0c\ub77c\uc9c8 \uae30\uc5c5 \ub0a9\uc138\uc790 \ub4f1\ub85d \ubc88\ud638\uac00 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. (CNPJ) -org.hibernate.validator.constraints.br.CPF.message = \ube0c\ub77c\uc9c8 \uac1c\uc778 \ub0a9\uc138\uc790 \ub4f1\ub85d \ubc88\ud638\uac00 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. (CPF) -org.hibernate.validator.constraints.br.TituloEleitoral.message = \ube0c\ub77c\uc9c8 \uc720\uad8c\uc790 ID \uce74\ub4dc \ubc88\ud638\uac00 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +org.hibernate.validator.constraints.CreditCardNumber.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \uc2e0\uc6a9\uce74\ub4dc \ubc88\ud638\uc785\ub2c8\ub2e4. +org.hibernate.validator.constraints.Currency.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ud1b5\ud654\uc785\ub2c8\ub2e4({value} \uc911 \ud558\ub098\uc5ec\uc57c \ud568). +org.hibernate.validator.constraints.EAN.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 {type} \ubc14\ucf54\ub4dc\uc785\ub2c8\ub2e4. +org.hibernate.validator.constraints.Email.message = \uc798\ubabb\ub41c \ud615\uc2dd\uc758 \uc774\uba54\uc77c \uc8fc\uc18c\uc785\ub2c8\ub2e4. +org.hibernate.validator.constraints.ISBN.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 ISBN\uc785\ub2c8\ub2e4. +org.hibernate.validator.constraints.Length.message = \uae38\uc774\uac00 {min}\uc5d0\uc11c {max} \uc0ac\uc774\uc5ec\uc57c \ud569\ub2c8\ub2e4. +org.hibernate.validator.constraints.CodePointLength.message = \uae38\uc774\uac00 {min}\uc5d0\uc11c {max} \uc0ac\uc774\uc5ec\uc57c \ud569\ub2c8\ub2e4. +org.hibernate.validator.constraints.LuhnCheck.message = ${validatedValue}\uc758 \uccb4\ud06c \ub514\uc9c0\ud2b8\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. Luhn Modulo 10 \uccb4\ud06c\uc12c\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4. +org.hibernate.validator.constraints.Mod10Check.message = ${validatedValue}\uc758 \uccb4\ud06c \ub514\uc9c0\ud2b8\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. Modulo 10 \uccb4\ud06c\uc12c\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4. +org.hibernate.validator.constraints.Mod11Check.message = ${validatedValue}\uc758 \uccb4\ud06c \ub514\uc9c0\ud2b8\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. Modulo 11 \uccb4\ud06c\uc12c\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4. +org.hibernate.validator.constraints.ModCheck.message = ${validatedValue}\uc758 \uccb4\ud06c \ub514\uc9c0\ud2b8\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. ${modType} \uccb4\ud06c\uc12c\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4. +org.hibernate.validator.constraints.NotBlank.message = \ube44\uc5b4 \uc788\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +org.hibernate.validator.constraints.NotEmpty.message = \ube44\uc5b4 \uc788\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +org.hibernate.validator.constraints.ParametersScriptAssert.message = \uc2a4\ud06c\ub9bd\ud2b8 \ud45c\ud604\uc2dd "{script}"\uac00 true\ub85c \ud3c9\uac00\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4. +org.hibernate.validator.constraints.Range.message = {min}\uc5d0\uc11c {max} \uc0ac\uc774\uc5ec\uc57c \ud569\ub2c8\ub2e4. +org.hibernate.validator.constraints.SafeHtml.message = \uc548\uc804\ud558\uc9c0 \uc54a\uc740 html \ucee8\ud150\uce20\uac00 \uc788\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4. +org.hibernate.validator.constraints.ScriptAssert.message = \uc2a4\ud06c\ub9bd\ud2b8 \ud45c\ud604\uc2dd "{script}"\uac00 true\ub85c \ud3c9\uac00\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4. +org.hibernate.validator.constraints.UniqueElements.message = \uace0\uc720 \uc694\uc18c\ub9cc \ud3ec\ud568\ud574\uc57c \ud569\ub2c8\ub2e4. +org.hibernate.validator.constraints.URL.message = \uc62c\ubc14\ub978 URL\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. + +org.hibernate.validator.constraints.br.CNPJ.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ube0c\ub77c\uc9c8 \ubc95\uc778 \ub0a9\uc138\uc790 \ub4f1\ub85d \ubc88\ud638(CNPJ)\uc785\ub2c8\ub2e4. +org.hibernate.validator.constraints.br.CPF.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ube0c\ub77c\uc9c8 \uac1c\uc778 \ub0a9\uc138\uc790 \ub4f1\ub85d \ubc88\ud638(CPF)\uc785\ub2c8\ub2e4. +org.hibernate.validator.constraints.br.TituloEleitoral.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ube0c\ub77c\uc9c8 \uc720\uad8c\uc790 ID \uce74\ub4dc \ubc88\ud638\uc785\ub2c8\ub2e4. + +org.hibernate.validator.constraints.pl.REGON.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ud3f4\ub780\ub4dc \ub0a9\uc138\uc790 \uc2dd\ubcc4 \ubc88\ud638(REGON)\uc785\ub2c8\ub2e4. +org.hibernate.validator.constraints.pl.NIP.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 VAT \uc2dd\ubcc4 \ubc88\ud638(NIP)\uc785\ub2c8\ub2e4. +org.hibernate.validator.constraints.pl.PESEL.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ud3f4\ub780\ub4dc \uad6d\ubbfc \uc2dd\ubcc4 \ubc88\ud638(PESEL)\uc785\ub2c8\ub2e4. + +org.hibernate.validator.constraints.time.DurationMax.message = \ub2e4\uc74c \uac12\ubcf4\ub2e4 \uc9e7\uac70\ub098 \uac19\uc544\uc57c \ud569\ub2c8\ub2e4${inclusive == true ? ' ' : ''}${days == 0 ? '' : days == 1 ? ' 1\uc77c' : ' ' += days += '\uc77c'}${hours == 0 ? '' : hours == 1 ? ' 1\uc2dc\uac04' : ' ' += hours += '\uc2dc\uac04'}${minutes == 0 ? '' : minutes == 1 ? ' 1\ubd84' : ' ' += minutes += '\ubd84'}${seconds == 0 ? '' : seconds == 1 ? ' 1\ucd08' : ' ' += seconds += '\ucd08'}${millis == 0 ? '' : millis == 1 ? ' 1\ubc00\ub9ac' : ' ' += millis += '\ubc00\ub9ac'}${nanos == 0 ? '' : nanos == 1 ? ' 1\ub098\ub178' : ' ' += nanos += '\ub098\ub178'} +org.hibernate.validator.constraints.time.DurationMin.message = \ub2e4\uc74c \uac12\ubcf4\ub2e4 \uae38\uac70\ub098 \uac19\uc544\uc57c \ud569\ub2c8\ub2e4${inclusive == true ? ' ' : ''}${days == 0 ? '' : days == 1 ? ' 1\uc77c' : ' ' += days += '\uc77c'}${hours == 0 ? '' : hours == 1 ? ' 1\uc2dc\uac04' : ' ' += hours += '\uc2dc\uac04'}${minutes == 0 ? '' : minutes == 1 ? ' 1\ubd84' : ' ' += minutes += '\ubd84'}${seconds == 0 ? '' : seconds == 1 ? ' 1\ucd08' : ' ' += seconds += '\ucd08'}${millis == 0 ? '' : millis == 1 ? ' 1\ubc00\ub9ac' : ' ' += millis += '\ubc00\ub9ac'}${nanos == 0 ? '' : nanos == 1 ? ' 1\ub098\ub178' : ' ' += nanos += '\ub098\ub178'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pl.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pl.properties new file mode 100644 index 0000000000..20a4e29d56 --- /dev/null +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pl.properties @@ -0,0 +1,53 @@ +javax.validation.constraints.AssertFalse.message = musi mie\u0107 warto\u015b\u0107 false +javax.validation.constraints.AssertTrue.message = musi mie\u0107 warto\u015b\u0107 true +javax.validation.constraints.DecimalMax.message = musi by\u0107 ${inclusive == true ? 'r\u00f3wne lub ' : ''}mniejsze od {value} +javax.validation.constraints.DecimalMin.message = musi by\u0107 ${inclusive == true ? 'r\u00f3wne lub ' : ''}wi\u0119ksze od {value} +javax.validation.constraints.Digits.message = warto\u015b\u0107 liczbowa spoza zakresu (oczekiwano ,) +javax.validation.constraints.Email.message = musi by\u0107 poprawnie sformatowanym adresem e-mail +javax.validation.constraints.Future.message = musi by\u0107 dat\u0105 w przysz\u0142o\u015bci +javax.validation.constraints.FutureOrPresent.message = musi by\u0107 dat\u0105 bie\u017c\u0105c\u0105 lub w przysz\u0142o\u015bci +javax.validation.constraints.Max.message = musi by\u0107 r\u00f3wne lub mniejsze od {value} +javax.validation.constraints.Min.message = musi by\u0107 r\u00f3wne lub wi\u0119ksze od {value} +javax.validation.constraints.Negative.message = musi by\u0107 mniejsze od 0 +javax.validation.constraints.NegativeOrZero.message = musi by\u0107 r\u00f3wne lub mniejsze od 0 +javax.validation.constraints.NotBlank.message = nie mo\u017ce by\u0107 odst\u0119pem +javax.validation.constraints.NotEmpty.message = nie mo\u017ce by\u0107 puste +javax.validation.constraints.NotNull.message = nie mo\u017ce mie\u0107 warto\u015bci null +javax.validation.constraints.Null.message = musi mie\u0107 warto\u015b\u0107 null +javax.validation.constraints.Past.message = musi by\u0107 dat\u0105 w przesz\u0142o\u015bci +javax.validation.constraints.PastOrPresent.message = musi by\u0107 dat\u0105 bie\u017c\u0105c\u0105 lub w przesz\u0142o\u015bci +javax.validation.constraints.Pattern.message = musi pasowa\u0107 do wyra\u017cenia {regexp} +javax.validation.constraints.Positive.message = musi by\u0107 wi\u0119ksze od 0 +javax.validation.constraints.PositiveOrZero.message = musi by\u0107 r\u00f3wne lub wi\u0119ksze od 0 +javax.validation.constraints.Size.message = wielko\u015b\u0107 musi nale\u017ce\u0107 do zakresu od {min} do {max} + +org.hibernate.validator.constraints.CreditCardNumber.message = niepoprawny numer karty kredytowej +org.hibernate.validator.constraints.Currency.message = niepoprawna waluta (musi by\u0107 jedn\u0105 z nast\u0119puj\u0105cych: {value}) +org.hibernate.validator.constraints.EAN.message = niepoprawny kod paskowy {type} +org.hibernate.validator.constraints.Email.message = nie jest poprawnie sformatowanym adresem e-mail +org.hibernate.validator.constraints.ISBN.message = niepoprawny numer ISBN +org.hibernate.validator.constraints.Length.message = d\u0142ugo\u015b\u0107 musi wynosi\u0107 od {min} do {max} +org.hibernate.validator.constraints.CodePointLength.message = d\u0142ugo\u015b\u0107 musi wynosi\u0107 od {min} do {max} +org.hibernate.validator.constraints.LuhnCheck.message = Cyfra kontrolna dla warto\u015bci ${validatedValue} jest niepoprawna, sprawdzenie sumy kontrolnej za pomoc\u0105 algorytmu Luhn Modulo 10 nie powiod\u0142o si\u0119 +org.hibernate.validator.constraints.Mod10Check.message = Cyfra kontrolna dla warto\u015bci ${validatedValue} jest niepoprawna, sprawdzenie sumy kontrolnej za pomoc\u0105 algorytmu Modulo 10 nie powiod\u0142o si\u0119 +org.hibernate.validator.constraints.Mod11Check.message = Cyfra kontrolna dla warto\u015bci ${validatedValue} jest niepoprawna, sprawdzenie sumy kontrolnej za pomoc\u0105 algorytmu Modulo 11 nie powiod\u0142o si\u0119 +org.hibernate.validator.constraints.ModCheck.message = Cyfra kontrolna dla warto\u015bci ${validatedValue} jest niepoprawna, sprawdzenie sumy kontrolnej za pomoc\u0105 algorytmu ${modType} nie powiod\u0142o si\u0119 +org.hibernate.validator.constraints.NotBlank.message = nie mo\u017ce by\u0107 puste +org.hibernate.validator.constraints.NotEmpty.message = nie mo\u017ce by\u0107 puste +org.hibernate.validator.constraints.ParametersScriptAssert.message = warto\u015bciowanie wyra\u017cenia skryptu {script} nie zwr\u00f3ci\u0142o warto\u015bci true +org.hibernate.validator.constraints.Range.message = musi nale\u017ce\u0107 do zakresu od {min} do {max} +org.hibernate.validator.constraints.SafeHtml.message = mo\u017ce zawiera\u0107 niebezpieczn\u0105 tre\u015b\u0107 HTML +org.hibernate.validator.constraints.ScriptAssert.message = warto\u015bciowanie wyra\u017cenia skryptu {script} nie zwr\u00f3ci\u0142o warto\u015bci true +org.hibernate.validator.constraints.UniqueElements.message = musi zawiera\u0107 tylko unikalne elementy +org.hibernate.validator.constraints.URL.message = musi by\u0107 poprawnym adresem URL + +org.hibernate.validator.constraints.br.CNPJ.message = niepoprawny numer brazylijskiego rejestru podatkowego os\u00f3b prawnych (CNPJ) +org.hibernate.validator.constraints.br.CPF.message = niepoprawny numer brazylijskiego rejestru podatkowego os\u00f3b fizycznych (CPF) +org.hibernate.validator.constraints.br.TituloEleitoral.message = niepoprawny numer brazylijskiej karty identyfikacyjnej g\u0142osuj\u0105cego + +org.hibernate.validator.constraints.pl.REGON.message = Niepoprawny numer identyfikacyjny polskiego podatnika (REGON) +org.hibernate.validator.constraints.pl.NIP.message = Niepoprawny number identyfikacyjny VAT (NIP) +org.hibernate.validator.constraints.pl.PESEL.message = Niepoprawny polski narodowy numer identyfikacyjny (PESEL) + +org.hibernate.validator.constraints.time.DurationMax.message = musi by\u0107 ${inclusive == true ? 'r\u00f3wne lub ' : ''}kr\u00f3tsze ni\u017c${days == 0 ? '' : days == 1 ? ' 1 dzie\u0144' : ' ' += days += ' dni'}${hours == 0 ? '' : hours == 1 ? ' 1 godzina' : ' ' += hours += ' godz.'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minuta' : ' ' += minutes += ' min'}${seconds == 0 ? '' : seconds == 1 ? ' 1 sekunda' : ' ' += seconds += ' s'}${millis == 0 ? '' : millis == 1 ? ' 1 milisekunda' : ' ' += millis += ' ms'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanosekunda' : ' ' += nanos += ' ns'} +org.hibernate.validator.constraints.time.DurationMin.message = musi by\u0107 ${inclusive == true ? 'r\u00f3wne lub ' : ''}d\u0142u\u017csze ni\u017c${days == 0 ? '' : days == 1 ? ' 1 dzie\u0144' : ' ' += days += ' dni'}${hours == 0 ? '' : hours == 1 ? ' 1 godzina' : ' ' += hours += ' godz.'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minuta' : ' ' += minutes += ' min'}${seconds == 0 ? '' : seconds == 1 ? ' 1 sekunda' : ' ' += seconds += ' s'}${millis == 0 ? '' : millis == 1 ? ' 1 milisekunda' : ' ' += millis += ' ms'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanosekunda' : ' ' += nanos += ' ns'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties index 14861f48f2..85dd4bb102 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties @@ -1,42 +1,53 @@ -javax.validation.constraints.AssertFalse.message = deve ser falso -javax.validation.constraints.AssertTrue.message = deve ser verdadeiro -javax.validation.constraints.DecimalMax.message = deve ser menor ou igual a {value} -javax.validation.constraints.DecimalMin.message = deve ser maior ou igual a {value} -javax.validation.constraints.Digits.message = valor num\u00E9rico fora do limite (<{integer} d\u00EDgitos>.<{fraction} d\u00EDgitos> esperado) -javax.validation.constraints.Email.message = n\u00E3o \u00E9 um endere\u00E7o de e-mail -javax.validation.constraints.Future.message = deve estar no futuro -javax.validation.constraints.FutureOrPresent.message = deve de ser uma data em presente ou em futuro -javax.validation.constraints.Max.message = deve ser menor ou igual a {value} -javax.validation.constraints.Min.message = deve ser maior ou igual a {value} -javax.validation.constraints.Negative.message = deve ser menor que 0 -javax.validation.constraints.NegativeOrZero.message = deve ser menor ou igual a 0 -javax.validation.constraints.NotBlank.message = n\u00E3o pode estar em branco -javax.validation.constraints.NotEmpty.message = n\u00E3o pode estar vazio -javax.validation.constraints.NotNull.message = n\u00E3o pode ser nulo -javax.validation.constraints.Null.message = deve ser nulo -javax.validation.constraints.Past.message = deve estar no passado -javax.validation.constraints.PastOrPresent.message = deve de ser uma data em passado ou em presente -javax.validation.constraints.Pattern.message = deve corresponder \u00E0 "{regexp}" -javax.validation.constraints.Positive.message = deve ser maior que 0 -javax.validation.constraints.PositiveOrZero.message = deve ser maior ou igual a 0 -javax.validation.constraints.Size.message = tamanho deve estar entre {min} e {max} +javax.validation.constraints.AssertFalse.message = deve ser falso +javax.validation.constraints.AssertTrue.message = deve ser verdadeiro +javax.validation.constraints.DecimalMax.message = deve ser menor que ${inclusive == true ? 'ou igual a ' : ''}{valor} +javax.validation.constraints.DecimalMin.message = deve ser maior que ${inclusive == true ? 'ou igual a ' : ''}{valor} +javax.validation.constraints.Digits.message = valor n\u00famerico fora do limite (<{inteiro} d\u00edgito>.<{fra\u00e7\u00e3o} d\u00edgitos> esperar) +javax.validation.constraints.Email.message = deve ser um endere\u00e7o de e-mail bem formado +javax.validation.constraints.Future.message = deve ser uma data futura +javax.validation.constraints.FutureOrPresent.message = deve ser uma data no presente ou no futuro +javax.validation.constraints.Max.message = deve ser menor que ou igual \u00e0 {valor} +javax.validation.constraints.Min.message = deve ser maior que ou igual \u00e0 {valor} +javax.validation.constraints.Negative.message = deve ser menor que 0 +javax.validation.constraints.NegativeOrZero.message = deve ser menor ou igual a 0 +javax.validation.constraints.NotBlank.message = n\u00e3o deve estar em branco +javax.validation.constraints.NotEmpty.message = n\u00e3o deve estar vazio +javax.validation.constraints.NotNull.message = n\u00e3o deve ser nulo +javax.validation.constraints.Null.message = deve ser nulo +javax.validation.constraints.Past.message = deve ser uma data passada +javax.validation.constraints.PastOrPresent.message = deve ser uma data no passado ou no presente +javax.validation.constraints.Pattern.message = deve corresponder a "{regexp}" +javax.validation.constraints.Positive.message = deve ser maior que 0 +javax.validation.constraints.PositiveOrZero.message = deve ser maior ou igual a 0 +javax.validation.constraints.Size.message = tamanho deve ser entre {m\u00edn} e {max} -org.hibernate.validator.constraints.CreditCardNumber.message = n\u00FAmero de cart\u00E3o de cr\u00E9dito inv\u00E1lido -org.hibernate.validator.constraints.Email.message = n\u00E3o \u00E9 um endere\u00E7o de e-mail -org.hibernate.validator.constraints.EAN.message = c\u00F3digo de barras {type} inv\u00E1lido -org.hibernate.validator.constraints.Length.message = tamanho deve estar entre {min} e {max} -org.hibernate.validator.constraints.CodePointLength.message = tamanho deve estar entre {min} e {max} -org.hibernate.validator.constraints.LuhnCheck.message = digito verificador para ${validatedValue} \u00E9 inv\u00E1lido, verifica\u00E7\u00E3o M\u00F3dulo 10 de Luhn falhou -org.hibernate.validator.constraints.Mod10Check.message = digito verificador para ${validatedValue} \u00E9 inv\u00E1lido, verifica\u00E7\u00E3o M\u00F3dulo 10 falhou -org.hibernate.validator.constraints.Mod11Check.message = digito verificador para ${validatedValue} \u00E9 inv\u00E1lido, verifica\u00E7\u00E3o M\u00F3dulo 10 falhou -org.hibernate.validator.constraints.ModCheck.message = digito verificador para ${validatedValue} \u00E9 inv\u00E1lido, verifica\u00E7\u00E3o ${modType} falhou -org.hibernate.validator.constraints.NotBlank.message = n\u00E3o pode estar em branco -org.hibernate.validator.constraints.NotEmpty.message = n\u00E3o pode estar vazio -org.hibernate.validator.constraints.ParametersScriptAssert.message = o script "{script}" n\u00E3o retornou verdadeiro -org.hibernate.validator.constraints.Range.message = o valor precisa estar entre {min} e {max} -org.hibernate.validator.constraints.SafeHtml.message = pode ter conte\u00FAdo inseguro no html -org.hibernate.validator.constraints.ScriptAssert.message = express\u00E3o de script "{script}" n\u00E3o retornou verdadeiro -org.hibernate.validator.constraints.URL.message = deve ser uma URL v\u00E1lida -org.hibernate.validator.constraints.br.CNPJ.message = CNPJ inv\u00E1lido -org.hibernate.validator.constraints.br.CPF.message = CPF inv\u00E1lido -org.hibernate.validator.constraints.br.TituloEleitoral.message = T\u00EDtulo Eleitoral inv\u00E1lido +org.hibernate.validator.constraints.CreditCardNumber.message = n\u00famero do cart\u00e3o de cr\u00e9dito inv\u00e1lido +org.hibernate.validator.constraints.Currency.message = moeda inv\u00e1lida (deve ser uma de {valor}) +org.hibernate.validator.constraints.EAN.message = c\u00f3digo de barras {tipo} inv\u00e1lido +org.hibernate.validator.constraints.Email.message = n\u00e3o \u00e9 um endere\u00e7o de e-mail corretamente formado +org.hibernate.validator.constraints.ISBN.message = ISBN inv\u00e1lido +org.hibernate.validator.constraints.Length.message = o comprimento deve ser entre {m\u00edn} e {m\u00e1x} +org.hibernate.validator.constraints.CodePointLength.message = o comprimento deve ser entre {m\u00edn} e {m\u00e1x} +org.hibernate.validator.constraints.LuhnCheck.message = O d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o Luhn Modulo 10 com falha +org.hibernate.validator.constraints.Mod10Check.message = O d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o Modulo 10 com falha +org.hibernate.validator.constraints.Mod11Check.message = O d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o Modulo 11 com falha +org.hibernate.validator.constraints.ModCheck.message = O d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o ${modType} com falha +org.hibernate.validator.constraints.NotBlank.message = n\u00e3o deve estar vazio +org.hibernate.validator.constraints.NotEmpty.message = n\u00e3o deve estar vazio +org.hibernate.validator.constraints.ParametersScriptAssert.message = express\u00e3o de script "{script}" n\u00e3o avaliou para true +org.hibernate.validator.constraints.Range.message = deve estar entre {m\u00edn} e {m\u00e1x} +org.hibernate.validator.constraints.SafeHtml.message = pode ter conte\u00fado HTML n\u00e3o seguro +org.hibernate.validator.constraints.ScriptAssert.message = express\u00e3o de script "{script}" n\u00e3o avaliou para true +org.hibernate.validator.constraints.UniqueElements.message = deve conter apenas elementos exclusivos +org.hibernate.validator.constraints.URL.message = deve ser uma URL v\u00e1lida + +org.hibernate.validator.constraints.br.CNPJ.message = n\u00famero do registro de contribuinte corporativo brasileiro (CNPJ) inv\u00e1lido +org.hibernate.validator.constraints.br.CPF.message = n\u00famero do registro de contribuinte individual brasileiro (CPF) inv\u00e1lido +org.hibernate.validator.constraints.br.TituloEleitoral.message = n\u00famero do t\u00edtulo de eleitor brasileiro inv\u00e1lido + +org.hibernate.validator.constraints.pl.REGON.message = N\u00famero de identifica\u00e7\u00e3o de contribuinte polon\u00eas (REGON) inv\u00e1lido +org.hibernate.validator.constraints.pl.NIP.message = N\u00famero de identifica\u00e7\u00e3o de VAT (NIP) inv\u00e1lido +org.hibernate.validator.constraints.pl.PESEL.message = N\u00famero de identifica\u00e7\u00e3o nacional polonesa (PESEL) inv\u00e1lido + +org.hibernate.validator.constraints.time.DurationMax.message = deve ser menor que${inclusive == true ? ' ou igual a' : ''}${dias == 0 ? '' : dias == 1 ? ' 1 dia' : ' ' += dias += ' dias'}${horas == 0 ? '' : horas == 1 ? ' 1 hora' : ' ' += horas += ' horas'}${minutos == 0 ? '' : minutos == 1 ? ' 1 minuto' : ' ' += minutos += ' minutos'}${segundos == 0 ? '' : segundos == 1 ? ' 1 segundo' : ' ' += segundos += ' segundos'}${miliss == 0 ? '' : miliss == 1 ? ' 1 mili' : ' ' += miliss += ' miliss'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} +org.hibernate.validator.constraints.time.DurationMin.message = deve ser maior que${inclusive == true ? ' ou igual a' : ''}${dias == 0 ? '' : dias == 1 ? ' 1 dia' : ' ' += dias += ' dias'}${horas == 0 ? '' : horas == 1 ? ' 1 hora' : ' ' += horas += ' horas'}${minutos == 0 ? '' : minutos == 1 ? ' 1 minuto' : ' ' += minutos += ' minutos'}${segundos == 0 ? '' : segundos == 1 ? ' 1 segundo' : ' ' += segundos += ' segundos'}${miliss == 0 ? '' : miliss == 1 ? ' 1 mili' : ' ' += miliss += ' miliss'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ro.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ro.properties new file mode 100644 index 0000000000..502e9073b0 --- /dev/null +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ro.properties @@ -0,0 +1,53 @@ +javax.validation.constraints.AssertFalse.message = trebuie s\u0103 fie false +javax.validation.constraints.AssertTrue.message = trebuie s\u0103 fie true +javax.validation.constraints.DecimalMax.message = trebuie s\u0103 fie mai mic dec\u00e2t ${inclusiv == true ? 'sau egal cu ' : ''}{valoare} +javax.validation.constraints.DecimalMin.message = trebuie s\u0103 fie mai mare dec\u00e2t ${inclusiv == true ? 'sau egal cu ' : ''}{valoare} +javax.validation.constraints.Digits.message = valoare numeric\u0103 \u00een afara limitelor (<{num\u0103r \u00eentreg} digi\u0163i>.<{num\u0103r frac\u0163ionar} digi\u0163i> a\u015fteptat) +javax.validation.constraints.Email.message = trebuie s\u0103 fie o adres\u0103 de e-mail cu format corect +javax.validation.constraints.Future.message = trebuie s\u0103 fie o dat\u0103 viitoare +javax.validation.constraints.FutureOrPresent.message = trebuie s\u0103 fie o dat\u0103 \u00een prezent sau \u00een viitor +javax.validation.constraints.Max.message = trebuie s\u0103 fie mai mic sau egal dec\u00e2t {valoare} +javax.validation.constraints.Min.message = trebuie s\u0103 fie mai mare sau egal dec\u00e2t {valoare} +javax.validation.constraints.Negative.message = trebuie s\u0103 fie mai mic dec\u00e2t 0 +javax.validation.constraints.NegativeOrZero.message = trebuie s\u0103 fie mai mic sau egal dec\u00e2t 0 +javax.validation.constraints.NotBlank.message = nu trebuie s\u0103 fie blanc +javax.validation.constraints.NotEmpty.message = nu trebuie s\u0103 fie gol +javax.validation.constraints.NotNull.message = nu trebuie s\u0103 fie null +javax.validation.constraints.Null.message = trebuie s\u0103 fie null +javax.validation.constraints.Past.message = trebuie s\u0103 fie o dat\u0103 anterioar\u0103 +javax.validation.constraints.PastOrPresent.message = trebuie s\u0103 fie o dat\u0103 anterioar\u0103 sau din prezent +javax.validation.constraints.Pattern.message = trebuie s\u0103 se potriveasc\u0103 "{regexp}" +javax.validation.constraints.Positive.message = trebuie s\u0103 fie mai mare dec\u00e2t 0 +javax.validation.constraints.PositiveOrZero.message = trebuie s\u0103 fie mai mare sau egal dec\u00e2t 0 +javax.validation.constraints.Size.message = dimensiunea trebuie s\u0103 fie \u00eentre {min} \u015fi {max} + +org.hibernate.validator.constraints.CreditCardNumber.message = num\u0103r invalid de card de credit +org.hibernate.validator.constraints.Currency.message = moned\u0103 invalid\u0103 trebuie s\u0103 fie una din {valoare}) +org.hibernate.validator.constraints.EAN.message = cod de bare {tip} invalid +org.hibernate.validator.constraints.Email.message = adres\u0103 de e-mail cu format incorect +org.hibernate.validator.constraints.ISBN.message = ISBN invalid +org.hibernate.validator.constraints.Length.message = lungimea trebuie s\u0103 fie \u00eentre {min} \u015fi {max} +org.hibernate.validator.constraints.CodePointLength.message = lungimea trebuie s\u0103 fie \u00eentre {min} \u015fi {max} +org.hibernate.validator.constraints.LuhnCheck.message = Cifra de verificare pentru ${validatedValue} este invalid\u0103, suma de control Luhn Modulo 10 a e\u015fuat +org.hibernate.validator.constraints.Mod10Check.message = Cifra de verificare pentru ${validatedValue} este invalid\u0103, suma de control Modulo 10 a e\u015fuat +org.hibernate.validator.constraints.Mod11Check.message = Cifra de verificare pentru ${validatedValue} este invalid\u0103, suma de control Modulo 11 a e\u015fuat +org.hibernate.validator.constraints.ModCheck.message = Cifra de verificare pentru ${validatedValue} este invalid\u0103, suma de control ${modType} a e\u015fuat +org.hibernate.validator.constraints.NotBlank.message = poate s\u0103 nu fie gol +org.hibernate.validator.constraints.NotEmpty.message = poate s\u0103 nu fie gol +org.hibernate.validator.constraints.ParametersScriptAssert.message = expresia de script "{script}" nu s-a evaluat la true +org.hibernate.validator.constraints.Range.message = trebuie s\u0103 fie \u00eentre {min} \u015fi {max} +org.hibernate.validator.constraints.SafeHtml.message = poate avea con\u0163inut HTML periculos +org.hibernate.validator.constraints.ScriptAssert.message = expresia de script "{script}" nu s-a evaluat la true +org.hibernate.validator.constraints.UniqueElements.message = trebuie s\u0103 con\u0163in\u0103 numai elemente unice +org.hibernate.validator.constraints.URL.message = trebuie s\u0103 fie un URL valid + +org.hibernate.validator.constraints.br.CNPJ.message = num\u0103r de registru de contribuabil corporatist brazilian invalid (CNPJ) +org.hibernate.validator.constraints.br.CPF.message = num\u0103r de registru de contribuabil individual brazilian invalid (CPF) +org.hibernate.validator.constraints.br.TituloEleitoral.message = num\u0103r invalid de carte de identitate de votant brazilian + +org.hibernate.validator.constraints.pl.REGON.message = Num\u0103r invalid de identificare contribuabil polonez (REGON) +org.hibernate.validator.constraints.pl.NIP.message = Num\u0103r invalid de identificare VAT (NIP) +org.hibernate.validator.constraints.pl.PESEL.message = Num\u0103r invalid de identificare na\u0163ional polonez (PESEL) + +org.hibernate.validator.constraints.time.DurationMax.message = trebuie s\u0103 fie mai scurt dec\u00e2t${inclusiv == true ? ' sau egal cu' : ''}${zile == 0 ? '' : zile == 1 ? ' 1 zi' : ' ' += zile += ' zile'}${ore == 0 ? '' : ore == 1 ? ' 1 or\u0103' : ' ' += ore += ' ore'}${minute == 0 ? '' : minute == 1 ? ' 1 minut' : ' ' += minute += ' minute'}${secunde == 0 ? '' : secunde == 1 ? ' 1 secund\u0103' : ' ' += secunde += ' secunde'}${milisecunde == 0 ? '' : milisecunde == 1 ? ' 1 milisecund\u0103' : ' ' += milisecunde += ' milisecunde'}${nanosecunde == 0 ? '' : nanosecunde == 1 ? ' 1 nanosecund\u0103' : ' ' += nanosecunde += ' nanosecunde'} +org.hibernate.validator.constraints.time.DurationMin.message = trebuie s\u0103 fie mai lung dec\u00e2t${inclusiv == true ? ' sau egal cu' : ''}${zile == 0 ? '' : zile == 1 ? ' 1 zi' : ' ' += zile += ' zile'}${ore == 0 ? '' : ore == 1 ? ' 1 or\u0103' : ' ' += ore += ' ore'}${minute == 0 ? '' : minute == 1 ? ' 1 minut' : ' ' += minute += ' minute'}${secunde == 0 ? '' : secunde == 1 ? ' 1 secund\u0103' : ' ' += secunde += ' secunde'}${milisecunde == 0 ? '' : milisecunde == 1 ? ' 1 milisecund\u0103' : ' ' += milisecunde += ' milisecunde'}${nanosecunde == 0 ? '' : nanosecunde == 1 ? ' 1 nanosecund\u0103' : ' ' += nanosecunde += ' nanosecunde'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ru.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ru.properties index 6c89c64ab8..94e70ec254 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ru.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ru.properties @@ -1,32 +1,53 @@ -javax.validation.constraints.AssertFalse.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043B\u043E\u0436\u043D\u044B\u043C -javax.validation.constraints.AssertTrue.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0438\u0441\u0442\u0438\u043D\u043D\u044B\u043C -javax.validation.constraints.DecimalMax.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043C\u0435\u043D\u044C\u0448\u0435 \u0447\u0435\u043C ${inclusive == true ? '\u0438\u043B\u0438 \u0440\u0430\u0432\u043D\u043E ' : ''}{value} -javax.validation.constraints.DecimalMin.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0431\u043E\u043B\u044C\u0448\u0435 \u0447\u0435\u043C ${inclusive == true ? '\u0438\u043B\u0438 \u0440\u0430\u0432\u043D\u043E ' : ''}{value} -javax.validation.constraints.Email.message = email \u043E\u043F\u0440\u0435\u0434\u0435\u043B\u0435\u043D \u0432 \u043D\u0435\u0432\u0435\u0440\u043D\u043E\u043C \u0444\u043E\u0440\u043C\u0430\u0442\u0435 -javax.validation.constraints.Future.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043C -javax.validation.constraints.Max.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043C\u0435\u043D\u044C\u0448\u0435 \u0438\u043B\u0438 \u0440\u0430\u0432\u043D\u043E {value} -javax.validation.constraints.Min.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0431\u043E\u043B\u044C\u0448\u0435 \u0438\u043B\u0438 \u0440\u0430\u0432\u043D\u043E {value} -javax.validation.constraints.NotBlank.message = \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0443\u0441\u0442\u043E -javax.validation.constraints.NotEmpty.message = \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0443\u0441\u0442\u043E -javax.validation.constraints.NotNull.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0437\u0430\u0434\u0430\u043D\u043E -javax.validation.constraints.Null.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E -javax.validation.constraints.Past.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0432 \u043F\u0440\u043E\u0448\u043B\u043E\u043C -javax.validation.constraints.Pattern.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043E\u0432\u0430\u0442\u044C \u0448\u0430\u0431\u043B\u043E\u043D\u0443 "{regexp}" -javax.validation.constraints.Size.message = \u0440\u0430\u0437\u043C\u0435\u0440 \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u043C\u0435\u0436\u0434\u0443 {min} \u0438 {max} +javax.validation.constraints.AssertFalse.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0440\u0430\u0432\u043d\u043e false +javax.validation.constraints.AssertTrue.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0440\u0430\u0432\u043d\u043e true +javax.validation.constraints.DecimalMax.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043c\u0435\u043d\u044c\u0448\u0435, \u0447\u0435\u043c ${inclusive == true ? '\u0438\u043b\u0438 \u0440\u0430\u0432\u043d\u043e ' : ''}{value} +javax.validation.constraints.DecimalMin.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c ${inclusive == true ? '\u0438\u043b\u0438 \u0440\u0430\u0432\u043d\u043e ' : ''}{value} +javax.validation.constraints.Digits.message = \u0447\u0438\u0441\u043b\u043e \u0432\u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0433\u043e \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430 (\u043e\u0436\u0438\u0434\u0430\u043b\u043e\u0441\u044c <{integer} \u0440\u0430\u0437\u0440\u044f\u0434\u043e\u0432>.<{fraction} \u0440\u0430\u0437\u0440\u044f\u0434\u043e\u0432>) +javax.validation.constraints.Email.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0438\u043c\u0435\u0442\u044c \u0444\u043e\u0440\u043c\u0430\u0442 \u0430\u0434\u0440\u0435\u0441\u0430 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b +javax.validation.constraints.Future.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0434\u0430\u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0435\u0449\u0435 \u043d\u0435 \u043d\u0430\u0441\u0442\u0443\u043f\u0438\u043b\u0430 +javax.validation.constraints.FutureOrPresent.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0441\u0435\u0433\u043e\u0434\u043d\u044f\u0448\u043d\u0435\u0435 \u0447\u0438\u0441\u043b\u043e \u0438\u043b\u0438 \u0434\u0430\u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0435\u0449\u0435 \u043d\u0435 \u043d\u0430\u0441\u0442\u0443\u043f\u0438\u043b\u0430 +javax.validation.constraints.Max.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043d\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 {value} +javax.validation.constraints.Min.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043d\u0435 \u043c\u0435\u043d\u044c\u0448\u0435 {value} +javax.validation.constraints.Negative.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043c\u0435\u043d\u044c\u0448\u0435 0 +javax.validation.constraints.NegativeOrZero.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043d\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 0 +javax.validation.constraints.NotBlank.message = \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c +javax.validation.constraints.NotEmpty.message = \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c +javax.validation.constraints.NotNull.message = \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0440\u0430\u0432\u043d\u044f\u0442\u044c\u0441\u044f null +javax.validation.constraints.Null.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0440\u0430\u0432\u043d\u044f\u0442\u044c\u0441\u044f null +javax.validation.constraints.Past.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0448\u0435\u0434\u0448\u0443\u044e \u0434\u0430\u0442\u0443 +javax.validation.constraints.PastOrPresent.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0448\u0435\u0434\u0448\u0443\u044e \u0434\u0430\u0442\u0443 \u0438\u043b\u0438 \u0441\u0435\u0433\u043e\u0434\u043d\u044f\u0448\u043d\u0435\u0435 \u0447\u0438\u0441\u043b\u043e +javax.validation.constraints.Pattern.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c "{regexp}" +javax.validation.constraints.Positive.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 0 +javax.validation.constraints.PositiveOrZero.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u0438\u043b\u0438 \u0440\u0430\u0432\u043d\u043e 0 +javax.validation.constraints.Size.message = \u0440\u0430\u0437\u043c\u0435\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 \u043e\u0442 {min} \u0434\u043e {max} -org.hibernate.validator.constraints.CreditCardNumber.message = \u043D\u0435\u0432\u0435\u0440\u043D\u044B\u0439 \u043D\u043E\u043C\u0435\u0440 \u043A\u0440\u0435\u0434\u0438\u0442\u043D\u043E\u0439 \u043A\u0430\u0440\u0442\u044B -org.hibernate.validator.constraints.EAN.message = \u043D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u044B\u0439 \u0448\u0442\u0440\u0438\u0445\u043A\u043E\u0434 {type} -org.hibernate.validator.constraints.Email.message = email \u043E\u043F\u0440\u0435\u0434\u0435\u043B\u0435\u043D \u0432 \u043D\u0435\u0432\u0435\u0440\u043D\u043E\u043C \u0444\u043E\u0440\u043C\u0430\u0442\u0435 -org.hibernate.validator.constraints.Length.message = \u0434\u043B\u0438\u043D\u0430 \u0434\u043E\u043B\u0436\u043D\u0430 \u0431\u044B\u0442\u044C \u043C\u0435\u0436\u0434\u0443 {min} \u0438 {max} -org.hibernate.validator.constraints.CodePointLength.message = \u0434\u043B\u0438\u043D\u0430 \u0434\u043E\u043B\u0436\u043D\u0430 \u0431\u044B\u0442\u044C \u043C\u0435\u0436\u0434\u0443 {min} \u0438 {max} -org.hibernate.validator.constraints.LuhnCheck.message = \u043A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u0430\u044F \u0446\u0438\u0444\u0440\u0430 \u0434\u043B\u044F ${validatedValue} \u043D\u0435\u0432\u0435\u0440\u043D\u0430, \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043F\u043E \u0430\u043B\u0433\u043E\u0440\u0438\u0442\u043C\u0443 \u041B\u0443\u043D\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430 \u0441 \u043E\u0448\u0438\u0431\u043A\u043E\u0439 -org.hibernate.validator.constraints.Mod10Check.message = \u043A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u0430\u044F \u0446\u0438\u0444\u0440\u0430 \u0434\u043B\u044F ${validatedValue} \u043D\u0435\u0432\u0435\u0440\u043D\u0430, \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043F\u043E \u0430\u043B\u0433\u043E\u0440\u0438\u0442\u043C\u0443 Mod10 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430 \u0441 \u043E\u0448\u0438\u0431\u043A\u043E\u0439 -org.hibernate.validator.constraints.Mod11Check.message = \u043A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u0430\u044F \u0446\u0438\u0444\u0440\u0430 \u0434\u043B\u044F ${validatedValue} \u043D\u0435\u0432\u0435\u0440\u043D\u0430, \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043F\u043E \u0430\u043B\u0433\u043E\u0440\u0438\u0442\u043C\u0443 Mod11 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430 \u0441 \u043E\u0448\u0438\u0431\u043A\u043E\u0439 -org.hibernate.validator.constraints.ModCheck.message = \u043A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u0430\u044F \u0446\u0438\u0444\u0440\u0430 \u0434\u043B\u044F ${validatedValue} \u043D\u0435\u0432\u0435\u0440\u043D\u0430, \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043F\u043E ${modType} \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430 \u0441 \u043E\u0448\u0438\u0431\u043A\u043E\u0439 -org.hibernate.validator.constraints.NotBlank.message = \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0443\u0441\u0442\u043E -org.hibernate.validator.constraints.NotEmpty.message = \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0443\u0441\u0442\u043E -org.hibernate.validator.constraints.ParametersScriptAssert.message = \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u0435 "{script}" \u043D\u0435 \u044F\u0432\u043B\u044F\u0435\u0442\u0441\u044F \u0438\u0441\u0442\u0438\u043D\u043D\u044B\u043C -org.hibernate.validator.constraints.Range.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043C\u0435\u0436\u0434\u0443 {min} \u0438 {max} -org.hibernate.validator.constraints.SafeHtml.message = \u043C\u043E\u0436\u0435\u0442 \u0441\u043E\u0434\u0435\u0440\u0436\u0430\u0442\u044C \u043D\u0435\u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u044B\u0439 html \u043A\u043E\u043D\u0442\u0435\u043D\u0442 -org.hibernate.validator.constraints.ScriptAssert.message = \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u0435 "{script}" \u043D\u0435 \u044F\u0432\u043B\u044F\u0435\u0442\u0441\u044F \u0438\u0441\u0442\u0438\u043D\u043D\u044B\u043C -org.hibernate.validator.constraints.URL.message = \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u043C URL +org.hibernate.validator.constraints.CreditCardNumber.message = \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u043a\u0440\u0435\u0434\u0438\u0442\u043d\u043e\u0439 \u043a\u0430\u0440\u0442\u044b +org.hibernate.validator.constraints.Currency.message = \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u0430\u044f \u0434\u0435\u043d\u0435\u0436\u043d\u0430\u044f \u0435\u0434\u0438\u043d\u0438\u0446\u0430 (\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f: {value}) +org.hibernate.validator.constraints.EAN.message = \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 \u0448\u0442\u0440\u0438\u0445\u043e\u0432\u043e\u0439 \u043a\u043e\u0434 {type} +org.hibernate.validator.constraints.Email.message = \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u043c \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b +org.hibernate.validator.constraints.ISBN.message = \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 ISBN +org.hibernate.validator.constraints.Length.message = \u0434\u043b\u0438\u043d\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043e\u0442 {min} \u0434\u043e {max} +org.hibernate.validator.constraints.CodePointLength.message = \u0434\u043b\u0438\u043d\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043e\u0442 {min} \u0434\u043e {max} +org.hibernate.validator.constraints.LuhnCheck.message = \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u0440\u044f\u0434 \u0434\u043b\u044f ${validatedValue} \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u043e\u0439 \u0441\u0443\u043c\u043c\u044b Luhn Modulo 10 +org.hibernate.validator.constraints.Mod10Check.message = \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u0440\u044f\u0434 \u0434\u043b\u044f ${validatedValue} \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u043e\u0439 \u0441\u0443\u043c\u043c\u044b Modulo 10 +org.hibernate.validator.constraints.Mod11Check.message = \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u0440\u044f\u0434 \u0434\u043b\u044f ${validatedValue} \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u043e\u0439 \u0441\u0443\u043c\u043c\u044b Modulo 11 +org.hibernate.validator.constraints.ModCheck.message = \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u0440\u044f\u0434 \u0434\u043b\u044f ${validatedValue} \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u043e\u0439 \u0441\u0443\u043c\u043c\u044b ${modType} +org.hibernate.validator.constraints.NotBlank.message = \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c +org.hibernate.validator.constraints.NotEmpty.message = \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c +org.hibernate.validator.constraints.ParametersScriptAssert.message = \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f "{script}" \u043d\u0435 \u0440\u0430\u0432\u0435\u043d true +org.hibernate.validator.constraints.Range.message = \u0434\u043e\u043b\u0436\u043d\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 \u043e\u0442 {min} \u0434\u043e {max} +org.hibernate.validator.constraints.SafeHtml.message = \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u043d\u0435\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 html +org.hibernate.validator.constraints.ScriptAssert.message = \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f "{script}" \u043d\u0435 \u0440\u0430\u0432\u0435\u043d true +org.hibernate.validator.constraints.UniqueElements.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b +org.hibernate.validator.constraints.URL.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 URL + +org.hibernate.validator.constraints.br.CNPJ.message = \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 \u0431\u0440\u0430\u0437\u0438\u043b\u044c\u0441\u043a\u0438\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u043d\u0430\u043b\u043e\u0433\u043e\u043f\u043b\u0430\u0442\u0435\u043b\u044c\u0449\u0438\u043a\u0430-\u044e\u0440\u0438\u0434\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043b\u0438\u0446\u0430 (CNPJ) +org.hibernate.validator.constraints.br.CPF.message = \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 \u0431\u0440\u0430\u0437\u0438\u043b\u044c\u0441\u043a\u0438\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u043d\u0430\u043b\u043e\u0433\u043e\u043f\u043b\u0430\u0442\u0435\u043b\u044c\u0449\u0438\u043a\u0430-\u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043b\u0438\u0446\u0430 (CPF) +org.hibernate.validator.constraints.br.TituloEleitoral.message = \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 \u0431\u0440\u0430\u0437\u0438\u043b\u044c\u0441\u043a\u0438\u0439 \u043d\u043e\u043c\u0435\u0440 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0438 \u0438\u0437\u0431\u0438\u0440\u0430\u0442\u0435\u043b\u044f + +org.hibernate.validator.constraints.pl.REGON.message = \u041d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 \u043f\u043e\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u043d\u0430\u043b\u043e\u0433\u043e\u043f\u043b\u0430\u0442\u0435\u043b\u044c\u0449\u0438\u043a\u0430 (REGON) +org.hibernate.validator.constraints.pl.NIP.message = \u041d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 VAT (NIP) +org.hibernate.validator.constraints.pl.PESEL.message = \u041d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 \u043f\u043e\u043b\u044c\u0441\u043a\u0438\u0439 \u043d\u0430\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 (PESEL) + +org.hibernate.validator.constraints.time.DurationMax.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043a\u043e\u0440\u043e\u0447\u0435${inclusive == true ? ' \u0438\u043b\u0438 \u0440\u0430\u0432\u043d\u043e' : ''}${days == 0 ? '' : days == 1 ? ' 1 \u0434\u043d' : ' ' += days += ' \u0434\u043d'}${hours == 0 ? '' : hours == 1 ? ' 1 \u0447' : ' ' += hours += ' \u0447'}${minutes == 0 ? '' : minutes == 1 ? ' 1 \u043c\u0438\u043d' : ' ' += minutes += ' \u043c\u0438\u043d'}${seconds == 0 ? '' : seconds == 1 ? ' 1 \u0441' : ' ' += seconds += ' \u0441'}${millis == 0 ? '' : millis == 1 ? ' 1 \u043c\u0441' : ' ' += millis += ' \u043c\u0441'}${nanos == 0 ? '' : nanos == 1 ? ' 1 \u043d\u0441' : ' ' += nanos += ' \u043d\u0441'} +org.hibernate.validator.constraints.time.DurationMin.message = \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0434\u043b\u0438\u043d\u043d\u0435\u0435${inclusive == true ? ' \u0438\u043b\u0438 \u0440\u0430\u0432\u043d\u043e' : ''}${days == 0 ? '' : days == 1 ? ' 1 \u0434\u043d' : ' ' += days += ' \u0434\u043d'}${hours == 0 ? '' : hours == 1 ? ' 1 \u0447' : ' ' += hours += ' \u0447'}${minutes == 0 ? '' : minutes == 1 ? ' 1 \u043c\u0438\u043d' : ' ' += minutes += ' \u043c\u0438\u043d'}${seconds == 0 ? '' : seconds == 1 ? ' 1 \u0441' : ' ' += seconds += ' \u0441'}${millis == 0 ? '' : millis == 1 ? ' 1 \u043c\u0441' : ' ' += millis += ' \u043c\u0441'}${nanos == 0 ? '' : nanos == 1 ? ' 1 \u043d\u0441' : ' ' += nanos += ' \u043d\u0441'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh.properties new file mode 100644 index 0000000000..3c4c3de950 --- /dev/null +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh.properties @@ -0,0 +1,53 @@ +javax.validation.constraints.AssertFalse.message = \u5fc5\u987b\u4e3a false +javax.validation.constraints.AssertTrue.message = \u5fc5\u987b\u4e3a true +javax.validation.constraints.DecimalMax.message = \u5fc5\u987b\u5c0f\u4e8e ${inclusive == true ? 'or equal to ' : ''}{value} +javax.validation.constraints.DecimalMin.message = \u5fc5\u987b\u5927\u4e8e ${inclusive == true ? 'or equal to ' : ''}{value} +javax.validation.constraints.Digits.message = \u6570\u5b57\u503c\u8d85\u51fa\u4e86\u8fb9\u754c\uff08\u671f\u671b <{integer} digits>.<{fraction} digits>\uff09 +javax.validation.constraints.Email.message = \u5fc5\u987b\u4e3a\u683c\u5f0f\u89c4\u8303\u7684\u7535\u5b50\u90ae\u4ef6\u5730\u5740 +javax.validation.constraints.Future.message = \u5fc5\u987b\u662f\u672a\u6765\u7684\u65e5\u671f +javax.validation.constraints.FutureOrPresent.message = \u5fc5\u987b\u662f\u73b0\u5728\u6216\u5c06\u6765\u7684\u65e5\u671f +javax.validation.constraints.Max.message = \u5fc5\u987b\u5c0f\u4e8e\u6216\u7b49\u4e8e {value} +javax.validation.constraints.Min.message = \u5fc5\u987b\u5927\u4e8e\u6216\u7b49\u4e8e {value} +javax.validation.constraints.Negative.message = \u5fc5\u987b\u5c0f\u4e8e 0 +javax.validation.constraints.NegativeOrZero.message = \u5fc5\u987b\u5c0f\u4e8e\u6216\u7b49\u4e8e 0 +javax.validation.constraints.NotBlank.message = \u4e0d\u5f97\u4e3a\u7a7a\u767d +javax.validation.constraints.NotEmpty.message = \u4e0d\u5f97\u4e3a\u7a7a +javax.validation.constraints.NotNull.message = \u4e0d\u5f97\u4e3a null +javax.validation.constraints.Null.message = \u5fc5\u987b\u4e3a null +javax.validation.constraints.Past.message = \u5fc5\u987b\u662f\u8fc7\u53bb\u7684\u65e5\u671f +javax.validation.constraints.PastOrPresent.message = \u5fc5\u987b\u662f\u8fc7\u53bb\u6216\u73b0\u5728\u7684\u65e5\u671f +javax.validation.constraints.Pattern.message = \u5fc5\u987b\u4e0e "{regexp}" \u5339\u914d +javax.validation.constraints.Positive.message = \u5fc5\u987b\u5927\u4e8e 0 +javax.validation.constraints.PositiveOrZero.message = \u5fc5\u987b\u5927\u4e8e\u6216\u7b49\u4e8e 0 +javax.validation.constraints.Size.message = \u5927\u5c0f\u5fc5\u987b\u5728 {min} \u548c {max} \u4e4b\u95f4 + +org.hibernate.validator.constraints.CreditCardNumber.message = \u65e0\u6548\u4fe1\u7528\u5361\u5361\u53f7 +org.hibernate.validator.constraints.Currency.message = \u65e0\u6548\u8d27\u5e01\uff08\u5fc5\u987b\u4e3a {value} \u4e4b\u4e00\uff09 +org.hibernate.validator.constraints.EAN.message = \u65e0\u6548 {type} \u6761\u5f62\u7801 +org.hibernate.validator.constraints.Email.message = \u7535\u5b50\u90ae\u4ef6\u5730\u5740\u683c\u5f0f\u4e0d\u89c4\u8303 +org.hibernate.validator.constraints.ISBN.message = \u65e0\u6548 ISBN +org.hibernate.validator.constraints.Length.message = \u957f\u5ea6\u5fc5\u987b\u4ecb\u4e8e {min} \u4e0e {max} \u4e4b\u95f4 +org.hibernate.validator.constraints.CodePointLength.message = \u957f\u5ea6\u5fc5\u987b\u4ecb\u4e8e {min} \u4e0e {max} \u4e4b\u95f4 +org.hibernate.validator.constraints.LuhnCheck.message = ${validatedValue} \u7684\u6821\u9a8c\u4f4d\u65e0\u6548\uff0cLuhn Modulo 10 \u6821\u9a8c\u548c\u5931\u8d25 +org.hibernate.validator.constraints.Mod10Check.message = ${validatedValue} \u7684\u6821\u9a8c\u4f4d\u65e0\u6548\uff0cModulo 10 \u6821\u9a8c\u548c\u5931\u8d25 +org.hibernate.validator.constraints.Mod11Check.message = ${validatedValue} \u7684\u6821\u9a8c\u4f4d\u65e0\u6548\uff0cModulo 11 \u6821\u9a8c\u548c\u5931\u8d25 +org.hibernate.validator.constraints.ModCheck.message = ${validatedValue} \u7684\u6821\u9a8c\u4f4d\u65e0\u6548\uff0c${modType} \u6821\u9a8c\u548c\u5931\u8d25 +org.hibernate.validator.constraints.NotBlank.message = \u53ef\u80fd\u4e0d\u4e3a\u7a7a +org.hibernate.validator.constraints.NotEmpty.message = \u53ef\u80fd\u4e0d\u4e3a\u7a7a +org.hibernate.validator.constraints.ParametersScriptAssert.message = \u811a\u672c\u8868\u8fbe\u5f0f "{script}" \u672a\u6c42\u503c\u4e3a true +org.hibernate.validator.constraints.Range.message = \u5fc5\u987b\u4ecb\u4e8e {min} \u4e0e {max} \u4e4b\u95f4 +org.hibernate.validator.constraints.SafeHtml.message = \u53ef\u80fd\u5177\u6709\u4e0d\u5b89\u5168\u7684 HTML \u5185\u5bb9 +org.hibernate.validator.constraints.ScriptAssert.message = \u811a\u672c\u8868\u8fbe\u5f0f "{script}" \u672a\u6c42\u503c\u4e3a true +org.hibernate.validator.constraints.UniqueElements.message = \u5fc5\u987b\u4ec5\u5305\u542b\u552f\u4e00\u5143\u7d20 +org.hibernate.validator.constraints.URL.message = \u5fc5\u987b\u4e3a\u6709\u6548 URL + +org.hibernate.validator.constraints.br.CNPJ.message = \u65e0\u6548\u5df4\u897f\u4f01\u4e1a\u7eb3\u7a0e\u4eba\u767b\u8bb0\u53f7 (CNPJ) +org.hibernate.validator.constraints.br.CPF.message = \u65e0\u6548\u5df4\u897f\u4e2a\u4eba\u7eb3\u7a0e\u4eba\u767b\u8bb0\u53f7 (CPF) +org.hibernate.validator.constraints.br.TituloEleitoral.message = \u65e0\u6548\u5df4\u897f\u6295\u7968\u4eba\u8eab\u4efd\u8bc1\u53f7 + +org.hibernate.validator.constraints.pl.REGON.message = \u65e0\u6548\u6ce2\u5170\u7eb3\u7a0e\u4eba\u8bc6\u522b\u53f7 (REGON) +org.hibernate.validator.constraints.pl.NIP.message = \u65e0\u6548 VAT \u8bc6\u522b\u53f7 (NIP) +org.hibernate.validator.constraints.pl.PESEL.message = \u65e0\u6548\u6ce2\u5170\u8eab\u4efd\u8bc1\u53f7 (PESEL) + +org.hibernate.validator.constraints.time.DurationMax.message = \u5fc5\u987b\u77ed\u4e8e ${inclusive == true ? ' or equal to' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} +org.hibernate.validator.constraints.time.DurationMin.message = \u5fc5\u987b\u957f\u4e8e ${inclusive == true ? ' or equal to' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh_TW.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh_TW.properties new file mode 100644 index 0000000000..de7aca4d3e --- /dev/null +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh_TW.properties @@ -0,0 +1,53 @@ +javax.validation.constraints.AssertFalse.message = \u5fc5\u9808\u662f false +javax.validation.constraints.AssertTrue.message = \u5fc5\u9808\u662f true +javax.validation.constraints.DecimalMax.message = \u5fc5\u9808\u5c0f\u65bc ${inclusive == true ? 'or equal to ' : ''}{value} +javax.validation.constraints.DecimalMin.message = \u5fc5\u9808\u5927\u65bc ${inclusive == true ? 'or equal to ' : ''}{value} +javax.validation.constraints.Digits.message = \u6578\u503c\u8d85\u51fa\u7bc4\u570d\uff08\u9810\u671f\u70ba <{integer} digits>.<{fraction} digits>\uff09 +javax.validation.constraints.Email.message = \u5fc5\u9808\u662f\u5f62\u5f0f\u5b8c\u6574\u7684\u96fb\u5b50\u90f5\u4ef6\u4f4d\u5740 +javax.validation.constraints.Future.message = \u5fc5\u9808\u662f\u672a\u4f86\u7684\u65e5\u671f +javax.validation.constraints.FutureOrPresent.message = \u5fc5\u9808\u662f\u7576\u5929\u6216\u672a\u4f86\u7684\u65e5\u671f +javax.validation.constraints.Max.message = \u5fc5\u9808\u5c0f\u65bc\u6216\u7b49\u65bc {value} +javax.validation.constraints.Min.message = \u5fc5\u9808\u5927\u65bc\u6216\u7b49\u65bc {value} +javax.validation.constraints.Negative.message = \u5fc5\u9808\u5c0f\u65bc 0 +javax.validation.constraints.NegativeOrZero.message = \u5fc5\u9808\u5c0f\u65bc\u6216\u7b49\u65bc 0 +javax.validation.constraints.NotBlank.message = \u4e0d\u5f97\u7a7a\u767d +javax.validation.constraints.NotEmpty.message = \u4e0d\u5f97\u662f\u7a7a\u7684 +javax.validation.constraints.NotNull.message = \u4e0d\u5f97\u662f\u7a7a\u503c +javax.validation.constraints.Null.message = \u5fc5\u9808\u662f\u7a7a\u503c +javax.validation.constraints.Past.message = \u5fc5\u9808\u662f\u904e\u53bb\u7684\u65e5\u671f +javax.validation.constraints.PastOrPresent.message = \u5fc5\u9808\u662f\u904e\u53bb\u6216\u7576\u5929\u7684\u65e5\u671f +javax.validation.constraints.Pattern.message = \u5fc5\u9808\u7b26\u5408 "{regexp}" +javax.validation.constraints.Positive.message = \u5fc5\u9808\u5927\u65bc 0 +javax.validation.constraints.PositiveOrZero.message = \u5fc5\u9808\u5927\u65bc\u6216\u7b49\u65bc 0 +javax.validation.constraints.Size.message = \u5927\u5c0f\u5fc5\u9808\u5728 {min} \u548c {max} \u4e4b\u9593 + +org.hibernate.validator.constraints.CreditCardNumber.message = \u7121\u6548\u7684\u4fe1\u7528\u5361\u5361\u865f +org.hibernate.validator.constraints.Currency.message = \u7121\u6548\u7684\u8ca8\u5e63\uff08\u5fc5\u9808\u662f {value} \u4e4b\u4e00\uff09 +org.hibernate.validator.constraints.EAN.message = \u7121\u6548\u7684 {type} \u689d\u78bc +org.hibernate.validator.constraints.Email.message = \u4e0d\u662f\u5f62\u5f0f\u5b8c\u6574\u7684\u96fb\u5b50\u90f5\u4ef6\u4f4d\u5740 +org.hibernate.validator.constraints.ISBN.message = \u7121\u6548\u7684 ISBN +org.hibernate.validator.constraints.Length.message = \u9577\u5ea6\u5fc5\u9808\u5728 {min} \u548c {max} \u4e4b\u9593 +org.hibernate.validator.constraints.CodePointLength.message = \u9577\u5ea6\u5fc5\u9808\u5728 {min} \u548c {max} \u4e4b\u9593 +org.hibernate.validator.constraints.LuhnCheck.message = ${validatedValue} \u7684\u6aa2\u67e5\u78bc\u7121\u6548\uff0cLuhn \u6a21\u6578 10 \u7e3d\u548c\u6aa2\u67e5\u5931\u6557 +org.hibernate.validator.constraints.Mod10Check.message = ${validatedValue} \u7684\u6aa2\u67e5\u78bc\u7121\u6548\uff0c\u6a21\u6578 10 \u7e3d\u548c\u6aa2\u67e5\u5931\u6557 +org.hibernate.validator.constraints.Mod11Check.message = ${validatedValue} \u7684\u6aa2\u67e5\u78bc\u7121\u6548\uff0c\u6a21\u6578 11 \u7e3d\u548c\u6aa2\u67e5\u5931\u6557 +org.hibernate.validator.constraints.ModCheck.message = ${validatedValue} \u7684\u6aa2\u67e5\u78bc\u7121\u6548\uff0c${modType} \u7e3d\u548c\u6aa2\u67e5\u5931\u6557 +org.hibernate.validator.constraints.NotBlank.message = \u4e0d\u80fd\u662f\u7a7a\u7684 +org.hibernate.validator.constraints.NotEmpty.message = \u4e0d\u80fd\u662f\u7a7a\u7684 +org.hibernate.validator.constraints.ParametersScriptAssert.message = Script \u8868\u793a\u5f0f "{script}" \u4e0d\u662f\u6c42\u503c\u70ba true +org.hibernate.validator.constraints.Range.message = \u5fc5\u9808\u5728 {min} \u548c {max} \u4e4b\u9593 +org.hibernate.validator.constraints.SafeHtml.message = \u53ef\u80fd\u5177\u6709\u4e0d\u5b89\u5168\u7684 html \u5167\u5bb9 +org.hibernate.validator.constraints.ScriptAssert.message = Script \u8868\u793a\u5f0f "{script}" \u4e0d\u662f\u6c42\u503c\u70ba true +org.hibernate.validator.constraints.UniqueElements.message = \u53ea\u80fd\u5305\u542b\u552f\u4e00\u5143\u7d20 +org.hibernate.validator.constraints.URL.message = \u5fc5\u9808\u662f\u6709\u6548\u7684 URL + +org.hibernate.validator.constraints.br.CNPJ.message = \u7121\u6548\u7684\u5df4\u897f\u516c\u53f8\u7d0d\u7a05\u767b\u9304\u78bc (CNPJ) +org.hibernate.validator.constraints.br.CPF.message = \u7121\u6548\u7684\u5df4\u897f\u500b\u4eba\u7d0d\u7a05\u767b\u9304\u78bc (CPF) +org.hibernate.validator.constraints.br.TituloEleitoral.message = \u7121\u6548\u7684\u5df4\u897f\u9078\u6c11 ID \u5361\u865f + +org.hibernate.validator.constraints.pl.REGON.message = \u7121\u6548\u7684\u6ce2\u862d\u7d0d\u7a05\u4eba\u8b58\u5225\u78bc (REGON) +org.hibernate.validator.constraints.pl.NIP.message = \u7121\u6548\u7684 VAT \u8b58\u5225\u78bc (NIP) +org.hibernate.validator.constraints.pl.PESEL.message = \u7121\u6548\u7684\u6ce2\u862d\u570b\u5bb6\u8b58\u5225\u78bc (PESEL) + +org.hibernate.validator.constraints.time.DurationMax.message = \u5fc5\u9808\u77ed\u65bc ${inclusive == true ? ' or equal to' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} +org.hibernate.validator.constraints.time.DurationMin.message = \u5fc5\u9808\u9577\u65bc ${inclusive == true ? ' or equal to' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} From b723ee78c02e8c536150d4a2091d755ec191f510 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Sun, 9 Dec 2018 11:02:20 +0100 Subject: [PATCH 156/393] HV-1651 Some fixes and adjustments --- .../ValidationMessages_cs.properties | 16 ++-- .../ValidationMessages_de.properties | 52 +++++------ .../ValidationMessages_es.properties | 14 +-- .../ValidationMessages_fr.properties | 28 +++--- .../ValidationMessages_hu.properties | 2 +- .../ValidationMessages_it.properties | 18 ++-- .../ValidationMessages_ko.properties | 90 +++++++++---------- .../ValidationMessages_pl.properties | 18 ++-- .../ValidationMessages_pt_BR.properties | 18 ++-- .../ValidationMessages_ro.properties | 20 ++--- ...ageInterpolationWithDefaultBundleTest.java | 8 +- .../PredefinedScopeValidatorFactoryTest.java | 4 +- 12 files changed, 144 insertions(+), 144 deletions(-) diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_cs.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_cs.properties index 3f52e33b96..c8f282a168 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_cs.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_cs.properties @@ -24,14 +24,14 @@ javax.validation.constraints.Size.message = velikost mus\u00ed le\u01 org.hibernate.validator.constraints.CreditCardNumber.message = neplatn\u00e9 \u010d\u00edslo kreditn\u00ed karty org.hibernate.validator.constraints.Currency.message = neplatn\u00e1 m\u011bna (mus\u00ed m\u00edt jednu z hodnot {hodnota}) org.hibernate.validator.constraints.EAN.message = neplatn\u00fd \u010d\u00e1rov\u00fd k\u00f3d {typ} -org.hibernate.validator.constraints.Email.message = nejedn\u00e1 se o spr\u00e1vn\u011b utvo\u0159enou e-mailovou adresu +org.hibernate.validator.constraints.Email.message = mus\u00ed m\u00edt spr\u00e1vn\u011b utvo\u0159enou e-mailovou adresu org.hibernate.validator.constraints.ISBN.message = neplatn\u00e9 ISBN org.hibernate.validator.constraints.Length.message = d\u00e9lka mus\u00ed le\u017eet v rozsahu {min} a\u017e {max} org.hibernate.validator.constraints.CodePointLength.message = d\u00e9lka mus\u00ed le\u017eet v rozsahu {min} a\u017e {max} -org.hibernate.validator.constraints.LuhnCheck.message = Kontroln\u00ed \u010d\u00edslice pro ${validatedValue} je neplatn\u00e1, kontroln\u00ed sou\u010det Luhn Modulo 10 se nezda\u0159il -org.hibernate.validator.constraints.Mod10Check.message = Kontroln\u00ed \u010d\u00edslice pro ${validatedValue} je neplatn\u00e1, kontroln\u00ed sou\u010det Modulo 10 se nezda\u0159il -org.hibernate.validator.constraints.Mod11Check.message = Kontroln\u00ed \u010d\u00edslice pro ${validatedValue} je neplatn\u00e1, kontroln\u00ed sou\u010det Modulo 11 se nezda\u0159il -org.hibernate.validator.constraints.ModCheck.message = Kontroln\u00ed \u010d\u00edslice pro ${validatedValue} je neplatn\u00e1, kontroln\u00ed sou\u010det ${modType} se nezda\u0159il +org.hibernate.validator.constraints.LuhnCheck.message = kontroln\u00ed \u010d\u00edslice pro ${validatedValue} je neplatn\u00e1, kontroln\u00ed sou\u010det Luhn Modulo 10 se nezda\u0159il +org.hibernate.validator.constraints.Mod10Check.message = kontroln\u00ed \u010d\u00edslice pro ${validatedValue} je neplatn\u00e1, kontroln\u00ed sou\u010det Modulo 10 se nezda\u0159il +org.hibernate.validator.constraints.Mod11Check.message = kontroln\u00ed \u010d\u00edslice pro ${validatedValue} je neplatn\u00e1, kontroln\u00ed sou\u010det Modulo 11 se nezda\u0159il +org.hibernate.validator.constraints.ModCheck.message = kontroln\u00ed \u010d\u00edslice pro ${validatedValue} je neplatn\u00e1, kontroln\u00ed sou\u010det ${modType} se nezda\u0159il org.hibernate.validator.constraints.NotBlank.message = nesm\u00ed b\u00fdt pr\u00e1zdn\u00e1 org.hibernate.validator.constraints.NotEmpty.message = nesm\u00ed b\u00fdt pr\u00e1zdn\u00e1 org.hibernate.validator.constraints.ParametersScriptAssert.message = v\u00fdraz skriptu "{script}" se nevyhodnotil na true @@ -45,9 +45,9 @@ org.hibernate.validator.constraints.br.CNPJ.message = neplatn\u0 org.hibernate.validator.constraints.br.CPF.message = neplatn\u00e9 brazilsk\u00e9 registra\u010dn\u00ed \u010d\u00edslo individu\u00e1ln\u00edho pl\u00e1tce dan\u011b (CPF) org.hibernate.validator.constraints.br.TituloEleitoral.message = neplatn\u00e9 brazilsk\u00e9 \u010d\u00edslo karty Voter ID -org.hibernate.validator.constraints.pl.REGON.message = Neplatn\u00e9 Polsk\u00e9 Identifika\u010dn\u00ed \u010d\u00edslo pl\u00e1tn\u011b dan\u011b (REGON) -org.hibernate.validator.constraints.pl.NIP.message = Neplatn\u00e9 da\u0148ov\u00e9 identifika\u010dn\u00ed \u010d\u00edslo (NIP) -org.hibernate.validator.constraints.pl.PESEL.message = Neplatn\u00e9 Polsk\u00e9 n\u00e1rodn\u00ed Identifika\u010dn\u00ed \u010d\u00edslo (PESEL) +org.hibernate.validator.constraints.pl.REGON.message = neplatn\u00e9 Polsk\u00e9 Identifika\u010dn\u00ed \u010d\u00edslo pl\u00e1tn\u011b dan\u011b (REGON) +org.hibernate.validator.constraints.pl.NIP.message = neplatn\u00e9 da\u0148ov\u00e9 identifika\u010dn\u00ed \u010d\u00edslo (NIP) +org.hibernate.validator.constraints.pl.PESEL.message = neplatn\u00e9 Polsk\u00e9 n\u00e1rodn\u00ed Identifika\u010dn\u00ed \u010d\u00edslo (PESEL) org.hibernate.validator.constraints.time.DurationMax.message = mus\u00ed b\u00fdt krat\u0161\u00ed ne\u017e${inclusive == true ? ' nebo rovno hodnot\u011b' : ''}${days == 0 ? '' : days == 1 ? ' 1 den' : ' ' += days += ' dny/\u016f'}${hours == 0 ? '' : hours == 1 ? ' 1 hod' : ' ' += hours += ' hod'}${minutes == 0 ? '' : minutes == 1 ? ' 1 min' : ' ' += minutes += ' min'}${seconds == 0 ? '' : seconds == 1 ? ' 1 s' : ' ' += seconds += ' s'}${millis == 0 ? '' : millis == 1 ? ' 1 ms' : ' ' += millis += ' ms'}${nanos == 0 ? '' : nanos == 1 ? ' 1 ns' : ' ' += nanos += ' ns'} org.hibernate.validator.constraints.time.DurationMin.message = mus\u00ed b\u00fdt del\u0161\u00ed ne\u017e${inclusive == true ? ' nebo rovno hodnot\u011b' : ''}${days == 0 ? '' : days == 1 ? ' 1 den' : ' ' += days += ' dny/\u016f'}${hours == 0 ? '' : hours == 1 ? ' 1 hod' : ' ' += hours += ' hod'}${minutes == 0 ? '' : minutes == 1 ? ' 1 min' : ' ' += minutes += ' min'}${seconds == 0 ? '' : seconds == 1 ? ' 1 s' : ' ' += seconds += ' s'}${millis == 0 ? '' : millis == 1 ? ' 1 ms' : ' ' += millis += ' ms'}${nanos == 0 ? '' : nanos == 1 ? ' 1 ns' : ' ' += nanos += ' ns'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties index b8365a0853..413e0943b5 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties @@ -3,43 +3,43 @@ javax.validation.constraints.AssertTrue.message = muss wahr sein javax.validation.constraints.DecimalMax.message = muss kleiner ${inclusive == true ? 'oder gleich ' : ''}{value} sein javax.validation.constraints.DecimalMin.message = muss gr\u00f6\u00dfer ${inclusive == true ? 'oder gleich sein ' : ''}{value} javax.validation.constraints.Digits.message = numerischer Wert au\u00dferhalb des g\u00fcltigen Bereichs (<{integer} digits>.<{fraction} digits> erwartet) -javax.validation.constraints.Email.message = muss eine korrekt formatierte E-Mail-Adresse sein. -javax.validation.constraints.Future.message = muss ein Datum in der Zukunft sein. -javax.validation.constraints.FutureOrPresent.message = muss ein Datum in der Gegenwart oder in der Zukunft sein. +javax.validation.constraints.Email.message = muss eine korrekt formatierte E-Mail-Adresse sein +javax.validation.constraints.Future.message = muss ein Datum in der Zukunft sein +javax.validation.constraints.FutureOrPresent.message = muss ein Datum in der Gegenwart oder in der Zukunft sein javax.validation.constraints.Max.message = muss kleiner-gleich {value} sein. -javax.validation.constraints.Min.message = muss gr\u00f6\u00dfer-gleich {value} sein. -javax.validation.constraints.Negative.message = muss kleiner als 0 sein. -javax.validation.constraints.NegativeOrZero.message = muss kleiner-gleich 0 sein. -javax.validation.constraints.NotBlank.message = darf nicht leer sein. -javax.validation.constraints.NotEmpty.message = darf nicht leer sein. -javax.validation.constraints.NotNull.message = darf nicht null sein. -javax.validation.constraints.Null.message = muss null sein. -javax.validation.constraints.Past.message = muss ein Datum in der Vergangenheit sein. -javax.validation.constraints.PastOrPresent.message = muss ein Datum in der Vergangenheit oder in der Gegenwart sein. -javax.validation.constraints.Pattern.message = muss mit "{regexp}" \u00fcbereinstimmen. -javax.validation.constraints.Positive.message = muss gr\u00f6\u00dfer als 0 sein. -javax.validation.constraints.PositiveOrZero.message = muss gr\u00f6\u00dfer-gleich 0 sein. -javax.validation.constraints.Size.message = Gr\u00f6\u00dfe muss zwischen {min} und {max} sein. +javax.validation.constraints.Min.message = muss gr\u00f6\u00dfer-gleich {value} sein +javax.validation.constraints.Negative.message = muss kleiner als 0 sein +javax.validation.constraints.NegativeOrZero.message = muss kleiner-gleich 0 sein +javax.validation.constraints.NotBlank.message = darf nicht leer sein +javax.validation.constraints.NotEmpty.message = darf nicht leer sein +javax.validation.constraints.NotNull.message = darf nicht null sein +javax.validation.constraints.Null.message = muss null sein +javax.validation.constraints.Past.message = muss ein Datum in der Vergangenheit sein +javax.validation.constraints.PastOrPresent.message = muss ein Datum in der Vergangenheit oder in der Gegenwart sein +javax.validation.constraints.Pattern.message = muss mit "{regexp}" \u00fcbereinstimmen +javax.validation.constraints.Positive.message = muss gr\u00f6\u00dfer als 0 sein +javax.validation.constraints.PositiveOrZero.message = muss gr\u00f6\u00dfer-gleich 0 sein +javax.validation.constraints.Size.message = Gr\u00f6\u00dfe muss zwischen {min} und {max} sein org.hibernate.validator.constraints.CreditCardNumber.message = ung\u00fcltige Kreditkartennummer org.hibernate.validator.constraints.Currency.message = ung\u00fcltige W\u00e4hrung (muss eine der folgenden sein: {value}) org.hibernate.validator.constraints.EAN.message = ung\u00fcltiger {type}-Barcode -org.hibernate.validator.constraints.Email.message = keine korrekt formatierte E-Mail-Adresse. -org.hibernate.validator.constraints.ISBN.message = Ung\u00fcltiger ISBN-Wert -org.hibernate.validator.constraints.Length.message = L\u00e4nge muss zwischen {min} und {max} sein. -org.hibernate.validator.constraints.CodePointLength.message = L\u00e4nge muss zwischen {min} und {max} sein. +org.hibernate.validator.constraints.Email.message = muss eine korrekt formatierte E-Mail-Adresse sein +org.hibernate.validator.constraints.ISBN.message = ung\u00fcltige ISBN +org.hibernate.validator.constraints.Length.message = L\u00e4nge muss zwischen {min} und {max} sein +org.hibernate.validator.constraints.CodePointLength.message = L\u00e4nge muss zwischen {min} und {max} sein org.hibernate.validator.constraints.LuhnCheck.message = die Pr\u00fcfziffer f\u00fcr ${validatedValue} ist ung\u00fcltig, Luhn Modulo 10-Kontrollsumme ist fehlgeschlagen org.hibernate.validator.constraints.Mod10Check.message = die Pr\u00fcfziffer f\u00fcr ${validatedValue} ist ung\u00fcltig, Modulo 10-Kontrollsumme ist fehlgeschlagen org.hibernate.validator.constraints.Mod11Check.message = die Pr\u00fcfziffer f\u00fcr ${validatedValue} ist ung\u00fcltig, Modulo 11-Kontrollsumme ist fehlgeschlagen org.hibernate.validator.constraints.ModCheck.message = die Pr\u00fcfziffer f\u00fcr ${validatedValue} ist ung\u00fcltig, ${modType}-Kontrollsumme ist fehlgeschlagen -org.hibernate.validator.constraints.NotBlank.message = darf nicht leer sein. -org.hibernate.validator.constraints.NotEmpty.message = darf nicht leer sein. +org.hibernate.validator.constraints.NotBlank.message = darf nicht leer sein +org.hibernate.validator.constraints.NotEmpty.message = darf nicht leer sein org.hibernate.validator.constraints.ParametersScriptAssert.message = die Evaluierung des Scriptausdrucks "{script}" ergab nicht true -org.hibernate.validator.constraints.Range.message = muss zwischen {min} und {max} sein. -org.hibernate.validator.constraints.SafeHtml.message = hat m\u00f6glicherweise keinen gesch\u00fctzten HTML-Inhalt. +org.hibernate.validator.constraints.Range.message = muss zwischen {min} und {max} sein +org.hibernate.validator.constraints.SafeHtml.message = hat m\u00f6glicherweise keinen gesch\u00fctzten HTML-Inhalt org.hibernate.validator.constraints.ScriptAssert.message = die Evaluierung des Scriptausdrucks "{script}" ergab nicht true -org.hibernate.validator.constraints.UniqueElements.message = dar nur eindeutige Elemente enthalten -org.hibernate.validator.constraints.URL.message = muss eine g\u00fcltige URL sein. +org.hibernate.validator.constraints.UniqueElements.message = darf nur eindeutige Elemente enthalten +org.hibernate.validator.constraints.URL.message = muss eine g\u00fcltige URL sein org.hibernate.validator.constraints.br.CNPJ.message = ung\u00fcltige brasilianische Registriernummer f\u00fcr K\u00f6rperschaftssteuerzahlungen (CNPJ) org.hibernate.validator.constraints.br.CPF.message = ung\u00fcltige brasilianische Registriernummer f\u00fcr Steuerzahlungen nat\u00fcrlicher Personen (CPF) diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_es.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_es.properties index fcc03c0031..89bc7106c2 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_es.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_es.properties @@ -10,7 +10,7 @@ javax.validation.constraints.Max.message = debe ser menor que o igua javax.validation.constraints.Min.message = debe ser mayor que o igual a {value} javax.validation.constraints.Negative.message = debe ser menor que 0 javax.validation.constraints.NegativeOrZero.message = debe ser menor que o igual a 0 -javax.validation.constraints.NotBlank.message = no debe estar en blanco +javax.validation.constraints.NotBlank.message = no debe estar vac\u00edo javax.validation.constraints.NotEmpty.message = no debe estar vac\u00edo javax.validation.constraints.NotNull.message = no debe ser nulo javax.validation.constraints.Null.message = debe ser nulo @@ -24,7 +24,7 @@ javax.validation.constraints.Size.message = el tama\u00f1o debe estar org.hibernate.validator.constraints.CreditCardNumber.message = n\u00famero de tarjeta de cr\u00e9dito no v\u00e1lido org.hibernate.validator.constraints.Currency.message = moneda no v\u00e1lida (debe ser una de {value}) org.hibernate.validator.constraints.EAN.message = c\u00f3digo de barras {type} no v\u00e1lido -org.hibernate.validator.constraints.Email.message = no es una direcci\u00f3n de correo electr\u00f3nico con formato correcto +org.hibernate.validator.constraints.Email.message = debe ser una direcci\u00f3n de correo electr\u00f3nico con formato correcto org.hibernate.validator.constraints.ISBN.message = ISBN no v\u00e1lido org.hibernate.validator.constraints.Length.message = la longitud debe estar entre {min} y {max} org.hibernate.validator.constraints.CodePointLength.message = la longitud debe estar entre {min} y {max} @@ -32,8 +32,8 @@ org.hibernate.validator.constraints.LuhnCheck.message = el d\u00ed org.hibernate.validator.constraints.Mod10Check.message = el d\u00edgito de comprobaci\u00f3n para ${validatedValue} no es v\u00e1lido, ha fallado la suma de comprobaci\u00f3n de Modulo 10 org.hibernate.validator.constraints.Mod11Check.message = el d\u00edgito de comprobaci\u00f3n para ${validatedValue} no es v\u00e1lido, ha fallado la suma de comprobaci\u00f3n de Modulo 11 org.hibernate.validator.constraints.ModCheck.message = el d\u00edgito de comprobaci\u00f3n para ${validatedValue} no es v\u00e1lido, ha fallado la suma de comprobaci\u00f3n ${modType} -org.hibernate.validator.constraints.NotBlank.message = no puede estar vac\u00edo -org.hibernate.validator.constraints.NotEmpty.message = no puede estar vac\u00edo +org.hibernate.validator.constraints.NotBlank.message = no debe estar vac\u00edo +org.hibernate.validator.constraints.NotEmpty.message = no debe estar vac\u00edo org.hibernate.validator.constraints.ParametersScriptAssert.message = la expresi\u00f3n de script "{script}" no se ha evaluado en verdadera org.hibernate.validator.constraints.Range.message = debe estar entre {min} y {max} org.hibernate.validator.constraints.SafeHtml.message = puede tener contenido HTML no seguro @@ -45,9 +45,9 @@ org.hibernate.validator.constraints.br.CNPJ.message = n\u00famer org.hibernate.validator.constraints.br.CPF.message = n\u00famero de registro de contribuyente individual de Brasil no v\u00e1lido (CPF) org.hibernate.validator.constraints.br.TituloEleitoral.message = n\u00famero de tarjeta de ID de votante de Brasil no v\u00e1lido -org.hibernate.validator.constraints.pl.REGON.message = N\u00famero de Identificaci\u00f3n de Contribuyente de Polonia no v\u00e1lido (REGON) -org.hibernate.validator.constraints.pl.NIP.message = N\u00famero de Identificaci\u00f3n de VAT no v\u00e1lido (NIP) -org.hibernate.validator.constraints.pl.PESEL.message = N\u00famero de Identificaci\u00f3n Nacional de Polonia no v\u00e1lido (PESEL) +org.hibernate.validator.constraints.pl.REGON.message = n\u00famero de Identificaci\u00f3n de Contribuyente de Polonia no v\u00e1lido (REGON) +org.hibernate.validator.constraints.pl.NIP.message = n\u00famero de Identificaci\u00f3n de VAT no v\u00e1lido (NIP) +org.hibernate.validator.constraints.pl.PESEL.message = n\u00famero de Identificaci\u00f3n Nacional de Polonia no v\u00e1lido (PESEL) org.hibernate.validator.constraints.time.DurationMax.message = debe tener una longitud menor que ${inclusive == true ? ' o igual a' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} org.hibernate.validator.constraints.time.DurationMin.message = debe tener una longitud mayor que ${inclusive == true ? ' o igual a' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties index 932ac217d3..f12655d8ac 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties @@ -10,9 +10,9 @@ javax.validation.constraints.Max.message = doit \u00eatre inf\u00e9r javax.validation.constraints.Min.message = doit \u00eatre sup\u00e9rieur ou \u00e9gal \u00e0 {value} javax.validation.constraints.Negative.message = doit \u00eatre inf\u00e9rieur \u00e0 0 javax.validation.constraints.NegativeOrZero.message = doit \u00eatre inf\u00e9rieur ou \u00e9gal \u00e0 0 -javax.validation.constraints.NotBlank.message = ne doit pas \u00eatre blanc +javax.validation.constraints.NotBlank.message = ne doit pas \u00eatre vide javax.validation.constraints.NotEmpty.message = ne doit pas \u00eatre vide -javax.validation.constraints.NotNull.message = ne doit pas avoir la valeur NULL +javax.validation.constraints.NotNull.message = ne doit pas être nul javax.validation.constraints.Null.message = doit \u00EAtre nul javax.validation.constraints.Past.message = doit \u00eatre une date dans le pass\u00e9 javax.validation.constraints.PastOrPresent.message = doit \u00eatre une date dans le pass\u00e9 ou le pr\u00e9sent @@ -22,23 +22,23 @@ javax.validation.constraints.PositiveOrZero.message = doit \u00eatre sup\u00e9r javax.validation.constraints.Size.message = la taille doit \u00eatre comprise entre {min} et {max} org.hibernate.validator.constraints.CreditCardNumber.message = num\u00e9ro de carte de cr\u00e9dit non valide -org.hibernate.validator.constraints.Currency.message = devise non valide (il doit s'agit de l'une des valeurs suivantes : {value}) -org.hibernate.validator.constraints.EAN.message = code \u00e0 barres {type} non valide -org.hibernate.validator.constraints.Email.message = adresse \u00e9lectronique incorrecte syntaxiquement +org.hibernate.validator.constraints.Currency.message = devise non valide (il doit s'agir de l'une des valeurs suivantes : {value}) +org.hibernate.validator.constraints.EAN.message = code-barres {type} non valide +org.hibernate.validator.constraints.Email.message = doit \u00eatre une adresse \u00e9lectronique syntaxiquement correcte org.hibernate.validator.constraints.ISBN.message = ISBN non valide org.hibernate.validator.constraints.Length.message = la longueur doit \u00eatre comprise entre {min} et {max} org.hibernate.validator.constraints.CodePointLength.message = la longueur doit \u00eatre comprise entre {min} et {max} -org.hibernate.validator.constraints.LuhnCheck.message = le chiffre cl\u00e9 pour ${validatedValue} n'est pas valide ; la somme de contr\u00f4le de l'algorithme de Luhn (modulo 10) a \u00e9chou\u00e9 -org.hibernate.validator.constraints.Mod10Check.message = le chiffre cl\u00e9 pour ${validatedValue} n'est pas valide ; la somme de contr\u00f4le de l'algorithme modulo 10 a \u00e9chou\u00e9 -org.hibernate.validator.constraints.Mod11Check.message = le chiffre cl\u00e9 pour ${validatedValue} n'est pas valide ; la somme de contr\u00f4le de l'algorithme modulo 11 a \u00e9chou\u00e9 -org.hibernate.validator.constraints.ModCheck.message = le chiffre cl\u00e9 pour ${validatedValue} n'est pas valide ; la somme de contr\u00f4le de l'algorithme ${modType} a \u00e9chou\u00e9 -org.hibernate.validator.constraints.NotBlank.message = ne peut pas \u00eatre vide -org.hibernate.validator.constraints.NotEmpty.message = ne peut pas \u00eatre vide +org.hibernate.validator.constraints.LuhnCheck.message = la cl\u00e9 de contr\u00f4le pour ${validatedValue} n'est pas valide ; la somme de contr\u00f4le de l'algorithme de Luhn (modulo 10) a \u00e9chou\u00e9 +org.hibernate.validator.constraints.Mod10Check.message = la cl\u00e9 de contr\u00f4le pour ${validatedValue} n'est pas valide ; la somme de contr\u00f4le de l'algorithme modulo 10 a \u00e9chou\u00e9 +org.hibernate.validator.constraints.Mod11Check.message = la cl\u00e9 de contr\u00f4le pour ${validatedValue} n'est pas valide ; la somme de contr\u00f4le de l'algorithme modulo 11 a \u00e9chou\u00e9 +org.hibernate.validator.constraints.ModCheck.message = la cl\u00e9 de contr\u00f4le pour ${validatedValue} n'est pas valide ; la somme de contr\u00f4le de l'algorithme ${modType} a \u00e9chou\u00e9 +org.hibernate.validator.constraints.NotBlank.message = ne doit pas \u00eatre vide +org.hibernate.validator.constraints.NotEmpty.message = ne doit pas \u00eatre vide org.hibernate.validator.constraints.ParametersScriptAssert.message = le script "{script}" n'a pas \u00E9t\u00E9 \u00E9valu\u00E9 \u00E0 vrai org.hibernate.validator.constraints.Range.message = doit \u00eatre compris entre {min} et {max} -org.hibernate.validator.constraints.SafeHtml.message = peut comporter un contenu html non s\u00e9curis\u00e9 -org.hibernate.validator.constraints.ScriptAssert.message = l'\u00e9valuation de l'expression de script "{script}" n'est pas true -org.hibernate.validator.constraints.UniqueElements.message = doit contenir des \u00e9l\u00e9ments uniques seulement +org.hibernate.validator.constraints.SafeHtml.message = peut comporter un contenu HTML non s\u00e9curis\u00e9 +org.hibernate.validator.constraints.ScriptAssert.message = le script "{script}" n'a pas \u00E9t\u00E9 \u00E9valu\u00E9 \u00E0 vrai +org.hibernate.validator.constraints.UniqueElements.message = ne doit contenir que des \u00e9l\u00e9ments uniques org.hibernate.validator.constraints.URL.message = doit \u00eatre une URL valide org.hibernate.validator.constraints.br.CNPJ.message = num\u00e9ro de registre d'entreprise contribuable br\u00e9silien non valide (CNPJ) diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_hu.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_hu.properties index 1cee6de3e0..79ab3d3170 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_hu.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_hu.properties @@ -24,7 +24,7 @@ javax.validation.constraints.Size.message = a m\u00e9retnek a(z) {min org.hibernate.validator.constraints.CreditCardNumber.message = \u00e9rv\u00e9nytelen hitelk\u00e1rtyasz\u00e1m org.hibernate.validator.constraints.Currency.message = \u00e9rv\u00e9nytelen p\u00e9nznem (a k\u00f6vetkez\u0151k egyike lehet: {value}) org.hibernate.validator.constraints.EAN.message = \u00e9rv\u00e9nytelen {type} vonalk\u00f3d -org.hibernate.validator.constraints.Email.message = nem helyes form\u00e1tum\u00fa e-mail c\u00edm +org.hibernate.validator.constraints.Email.message = helyes form\u00e1tum\u00fa e-mail c\u00edmnek kell lennie org.hibernate.validator.constraints.ISBN.message = \u00e9rv\u00e9nytelen ISBN org.hibernate.validator.constraints.Length.message = a hossznak a(z) {min} \u00e9s {max} \u00e9rt\u00e9kek k\u00f6z\u00f6tt kell lennie org.hibernate.validator.constraints.CodePointLength.message = a hossznak a(z) {min} \u00e9s {max} \u00e9rt\u00e9kek k\u00f6z\u00f6tt kell lennie diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_it.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_it.properties index 95e07c9d9e..368780928e 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_it.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_it.properties @@ -28,12 +28,12 @@ org.hibernate.validator.constraints.Email.message = non \u00e8 org.hibernate.validator.constraints.ISBN.message = ISBN non valido org.hibernate.validator.constraints.Length.message = la lunghezza deve essere compresa tra {min} e {max} org.hibernate.validator.constraints.CodePointLength.message = la lunghezza deve essere compresa tra {min} e {max} -org.hibernate.validator.constraints.LuhnCheck.message = La cifra di controllo per ${validatedValue} non \u00e8 valida, checksum Luhn Modulo 10 non riuscito -org.hibernate.validator.constraints.Mod10Check.message = La cifra di controllo per ${validatedValue} non \u00e8 valida, checksum Modulo 10 non riuscito -org.hibernate.validator.constraints.Mod11Check.message = La cifra di controllo per ${validatedValue} non \u00e8 valida, checksum Modulo 11 non riuscito -org.hibernate.validator.constraints.ModCheck.message = La cifra di controllo per ${validatedValue} non \u00e8 valida, checksum ${modType} non riuscito -org.hibernate.validator.constraints.NotBlank.message = non pu\u00f2 essere vuoto -org.hibernate.validator.constraints.NotEmpty.message = non pu\u00f2 essere vuoto +org.hibernate.validator.constraints.LuhnCheck.message = la cifra di controllo per ${validatedValue} non \u00e8 valida, checksum Luhn Modulo 10 non riuscito +org.hibernate.validator.constraints.Mod10Check.message = la cifra di controllo per ${validatedValue} non \u00e8 valida, checksum Modulo 10 non riuscito +org.hibernate.validator.constraints.Mod11Check.message = la cifra di controllo per ${validatedValue} non \u00e8 valida, checksum Modulo 11 non riuscito +org.hibernate.validator.constraints.ModCheck.message = la cifra di controllo per ${validatedValue} non \u00e8 valida, checksum ${modType} non riuscito +org.hibernate.validator.constraints.NotBlank.message = non deve essere spazio +org.hibernate.validator.constraints.NotEmpty.message = non deve essere vuoto org.hibernate.validator.constraints.ParametersScriptAssert.message = espressione script "{script}" non valutata true org.hibernate.validator.constraints.Range.message = deve essere compresa tra {min} e {max} org.hibernate.validator.constraints.SafeHtml.message = ha contenuto html non sicuro @@ -45,9 +45,9 @@ org.hibernate.validator.constraints.br.CNPJ.message = numero reg org.hibernate.validator.constraints.br.CPF.message = numero registro contribuente individuale (CPF) brasiliano non valido org.hibernate.validator.constraints.br.TituloEleitoral.message = numero scheda ID votante brasiliano non valido -org.hibernate.validator.constraints.pl.REGON.message = Numero identificativo contribuente polacco (REGON) non valido -org.hibernate.validator.constraints.pl.NIP.message = Numero identificativo IVA (NIP) non valido -org.hibernate.validator.constraints.pl.PESEL.message = Numero identificativo nazionale polacco (PESEL) non valido +org.hibernate.validator.constraints.pl.REGON.message = numero identificativo contribuente polacco (REGON) non valido +org.hibernate.validator.constraints.pl.NIP.message = numero identificativo IVA (NIP) non valido +org.hibernate.validator.constraints.pl.PESEL.message = numero identificativo nazionale polacco (PESEL) non valido org.hibernate.validator.constraints.time.DurationMax.message = deve essere inferiore a ${inclusive == true ? ' o uguale a' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} org.hibernate.validator.constraints.time.DurationMin.message = deve essere superiore a ${inclusive == true ? ' o uguale a' : ''}${days == 0 ? '' : days == 1 ? ' 1 day' : ' ' += days += ' days'}${hours == 0 ? '' : hours == 1 ? ' 1 hour' : ' ' += hours += ' hours'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minute' : ' ' += minutes += ' minutes'}${seconds == 0 ? '' : seconds == 1 ? ' 1 second' : ' ' += seconds += ' seconds'}${millis == 0 ? '' : millis == 1 ? ' 1 milli' : ' ' += millis += ' millis'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ko.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ko.properties index 86e2b6ca0f..510d70b968 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ko.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ko.properties @@ -1,53 +1,53 @@ -javax.validation.constraints.AssertFalse.message = false\uc5ec\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.AssertTrue.message = true\uc5ec\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.AssertFalse.message = false\uc5ec\uc57c \ud569\ub2c8\ub2e4 +javax.validation.constraints.AssertTrue.message = true\uc5ec\uc57c \ud569\ub2c8\ub2e4 javax.validation.constraints.DecimalMax.message = \ub2e4\uc74c \uac12 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4${inclusive == true ? ' ' : ''}{value} javax.validation.constraints.DecimalMin.message = \ub2e4\uc74c \uac12 \uc774\uc0c1\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4${inclusive == true ? ' ' : ''}{value} -javax.validation.constraints.Digits.message = \uc22b\uc790 \uac12\uc774 \ud55c\uacc4\ub97c \ucd08\uacfc\ud569\ub2c8\ub2e4(<{integer} \uc790\ub9ac>.<{fraction} \uc790\ub9ac> \uc608\uc0c1). -javax.validation.constraints.Email.message = \uc62c\ubc14\ub978 \ud615\uc2dd\uc758 \uc774\uba54\uc77c \uc8fc\uc18c\uc5ec\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.Future.message = \ubbf8\ub798 \ub0a0\uc9dc\uc5ec\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.FutureOrPresent.message = \ud604\uc7ac \ub610\ub294 \ubbf8\ub798\uc758 \ub0a0\uc9dc\uc5ec\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.Max.message = {value} \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.Min.message = {value} \uc774\uc0c1\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.Negative.message = 0 \ubbf8\ub9cc\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.NegativeOrZero.message = 0 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.NotBlank.message = \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -javax.validation.constraints.NotEmpty.message = \ube44\uc5b4 \uc788\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -javax.validation.constraints.NotNull.message = \ub110\uc774\uc5b4\uc11c\ub294 \uc548\ub429\ub2c8\ub2e4. -javax.validation.constraints.Null.message = \ub110\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.Past.message = \uacfc\uac70 \ub0a0\uc9dc\uc5ec\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.PastOrPresent.message = \uacfc\uac70 \ub610\ub294 \ud604\uc7ac\uc758 \ub0a0\uc9dc\uc5ec\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.Pattern.message = "{regexp}"\uc640 \uc77c\uce58\ud574\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.Positive.message = 0\ubcf4\ub2e4 \ucee4\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.PositiveOrZero.message = 0 \uc774\uc0c1\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. -javax.validation.constraints.Size.message = \ud06c\uae30\uac00 {min}\uc5d0\uc11c {max} \uc0ac\uc774\uc5ec\uc57c \ud569\ub2c8\ub2e4. +javax.validation.constraints.Digits.message = \uc22b\uc790 \uac12\uc774 \ud55c\uacc4\ub97c \ucd08\uacfc\ud569\ub2c8\ub2e4(<{integer} \uc790\ub9ac>.<{fraction} \uc790\ub9ac> \uc608\uc0c1) +javax.validation.constraints.Email.message = \uc62c\ubc14\ub978 \ud615\uc2dd\uc758 \uc774\uba54\uc77c \uc8fc\uc18c\uc5ec\uc57c \ud569\ub2c8\ub2e4 +javax.validation.constraints.Future.message = \ubbf8\ub798 \ub0a0\uc9dc\uc5ec\uc57c \ud569\ub2c8\ub2e4 +javax.validation.constraints.FutureOrPresent.message = \ud604\uc7ac \ub610\ub294 \ubbf8\ub798\uc758 \ub0a0\uc9dc\uc5ec\uc57c \ud569\ub2c8\ub2e4 +javax.validation.constraints.Max.message = {value} \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4 +javax.validation.constraints.Min.message = {value} \uc774\uc0c1\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4 +javax.validation.constraints.Negative.message = 0 \ubbf8\ub9cc\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4 +javax.validation.constraints.NegativeOrZero.message = 0 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4 +javax.validation.constraints.NotBlank.message = \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4 +javax.validation.constraints.NotEmpty.message = \ube44\uc5b4 \uc788\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4 +javax.validation.constraints.NotNull.message = \ub110\uc774\uc5b4\uc11c\ub294 \uc548\ub429\ub2c8\ub2e4 +javax.validation.constraints.Null.message = \ub110\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4 +javax.validation.constraints.Past.message = \uacfc\uac70 \ub0a0\uc9dc\uc5ec\uc57c \ud569\ub2c8\ub2e4 +javax.validation.constraints.PastOrPresent.message = \uacfc\uac70 \ub610\ub294 \ud604\uc7ac\uc758 \ub0a0\uc9dc\uc5ec\uc57c \ud569\ub2c8\ub2e4 +javax.validation.constraints.Pattern.message = "{regexp}"\uc640 \uc77c\uce58\ud574\uc57c \ud569\ub2c8\ub2e4 +javax.validation.constraints.Positive.message = 0\ubcf4\ub2e4 \ucee4\uc57c \ud569\ub2c8\ub2e4 +javax.validation.constraints.PositiveOrZero.message = 0 \uc774\uc0c1\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4 +javax.validation.constraints.Size.message = \ud06c\uae30\uac00 {min}\uc5d0\uc11c {max} \uc0ac\uc774\uc5ec\uc57c \ud569\ub2c8\ub2e4 -org.hibernate.validator.constraints.CreditCardNumber.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \uc2e0\uc6a9\uce74\ub4dc \ubc88\ud638\uc785\ub2c8\ub2e4. -org.hibernate.validator.constraints.Currency.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ud1b5\ud654\uc785\ub2c8\ub2e4({value} \uc911 \ud558\ub098\uc5ec\uc57c \ud568). -org.hibernate.validator.constraints.EAN.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 {type} \ubc14\ucf54\ub4dc\uc785\ub2c8\ub2e4. -org.hibernate.validator.constraints.Email.message = \uc798\ubabb\ub41c \ud615\uc2dd\uc758 \uc774\uba54\uc77c \uc8fc\uc18c\uc785\ub2c8\ub2e4. -org.hibernate.validator.constraints.ISBN.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 ISBN\uc785\ub2c8\ub2e4. -org.hibernate.validator.constraints.Length.message = \uae38\uc774\uac00 {min}\uc5d0\uc11c {max} \uc0ac\uc774\uc5ec\uc57c \ud569\ub2c8\ub2e4. -org.hibernate.validator.constraints.CodePointLength.message = \uae38\uc774\uac00 {min}\uc5d0\uc11c {max} \uc0ac\uc774\uc5ec\uc57c \ud569\ub2c8\ub2e4. -org.hibernate.validator.constraints.LuhnCheck.message = ${validatedValue}\uc758 \uccb4\ud06c \ub514\uc9c0\ud2b8\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. Luhn Modulo 10 \uccb4\ud06c\uc12c\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.Mod10Check.message = ${validatedValue}\uc758 \uccb4\ud06c \ub514\uc9c0\ud2b8\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. Modulo 10 \uccb4\ud06c\uc12c\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.Mod11Check.message = ${validatedValue}\uc758 \uccb4\ud06c \ub514\uc9c0\ud2b8\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. Modulo 11 \uccb4\ud06c\uc12c\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.ModCheck.message = ${validatedValue}\uc758 \uccb4\ud06c \ub514\uc9c0\ud2b8\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. ${modType} \uccb4\ud06c\uc12c\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.NotBlank.message = \ube44\uc5b4 \uc788\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.NotEmpty.message = \ube44\uc5b4 \uc788\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.ParametersScriptAssert.message = \uc2a4\ud06c\ub9bd\ud2b8 \ud45c\ud604\uc2dd "{script}"\uac00 true\ub85c \ud3c9\uac00\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.Range.message = {min}\uc5d0\uc11c {max} \uc0ac\uc774\uc5ec\uc57c \ud569\ub2c8\ub2e4. -org.hibernate.validator.constraints.SafeHtml.message = \uc548\uc804\ud558\uc9c0 \uc54a\uc740 html \ucee8\ud150\uce20\uac00 \uc788\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.ScriptAssert.message = \uc2a4\ud06c\ub9bd\ud2b8 \ud45c\ud604\uc2dd "{script}"\uac00 true\ub85c \ud3c9\uac00\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4. -org.hibernate.validator.constraints.UniqueElements.message = \uace0\uc720 \uc694\uc18c\ub9cc \ud3ec\ud568\ud574\uc57c \ud569\ub2c8\ub2e4. -org.hibernate.validator.constraints.URL.message = \uc62c\ubc14\ub978 URL\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +org.hibernate.validator.constraints.CreditCardNumber.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \uc2e0\uc6a9\uce74\ub4dc \ubc88\ud638\uc785\ub2c8\ub2e4 +org.hibernate.validator.constraints.Currency.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ud1b5\ud654\uc785\ub2c8\ub2e4({value} \uc911 \ud558\ub098\uc5ec\uc57c \ud568) +org.hibernate.validator.constraints.EAN.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 {type} \ubc14\ucf54\ub4dc\uc785\ub2c8\ub2e4 +org.hibernate.validator.constraints.Email.message = \uc62c\ubc14\ub978 \ud615\uc2dd\uc758 \uc774\uba54\uc77c \uc8fc\uc18c\uc5ec\uc57c \ud569\ub2c8\ub2e4 +org.hibernate.validator.constraints.ISBN.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 ISBN\uc785\ub2c8\ub2e4 +org.hibernate.validator.constraints.Length.message = \uae38\uc774\uac00 {min}\uc5d0\uc11c {max} \uc0ac\uc774\uc5ec\uc57c \ud569\ub2c8\ub2e4 +org.hibernate.validator.constraints.CodePointLength.message = \uae38\uc774\uac00 {min}\uc5d0\uc11c {max} \uc0ac\uc774\uc5ec\uc57c \ud569\ub2c8\ub2e4 +org.hibernate.validator.constraints.LuhnCheck.message = ${validatedValue}\uc758 \uccb4\ud06c \ub514\uc9c0\ud2b8\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. Luhn Modulo 10 \uccb4\ud06c\uc12c\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4 +org.hibernate.validator.constraints.Mod10Check.message = ${validatedValue}\uc758 \uccb4\ud06c \ub514\uc9c0\ud2b8\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. Modulo 10 \uccb4\ud06c\uc12c\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4 +org.hibernate.validator.constraints.Mod11Check.message = ${validatedValue}\uc758 \uccb4\ud06c \ub514\uc9c0\ud2b8\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. Modulo 11 \uccb4\ud06c\uc12c\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4 +org.hibernate.validator.constraints.ModCheck.message = ${validatedValue}\uc758 \uccb4\ud06c \ub514\uc9c0\ud2b8\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. ${modType} \uccb4\ud06c\uc12c\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4 +org.hibernate.validator.constraints.NotBlank.message = \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4 +org.hibernate.validator.constraints.NotEmpty.message = \ube44\uc5b4 \uc788\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4 +org.hibernate.validator.constraints.ParametersScriptAssert.message = \uc2a4\ud06c\ub9bd\ud2b8 \ud45c\ud604\uc2dd "{script}"\uac00 true\ub85c \ud3c9\uac00\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4 +org.hibernate.validator.constraints.Range.message = {min}\uc5d0\uc11c {max} \uc0ac\uc774\uc5ec\uc57c \ud569\ub2c8\ub2e4 +org.hibernate.validator.constraints.SafeHtml.message = \uc548\uc804\ud558\uc9c0 \uc54a\uc740 html \ucee8\ud150\uce20\uac00 \uc788\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4 +org.hibernate.validator.constraints.ScriptAssert.message = \uc2a4\ud06c\ub9bd\ud2b8 \ud45c\ud604\uc2dd "{script}"\uac00 true\ub85c \ud3c9\uac00\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4 +org.hibernate.validator.constraints.UniqueElements.message = \uace0\uc720 \uc694\uc18c\ub9cc \ud3ec\ud568\ud574\uc57c \ud569\ub2c8\ub2e4 +org.hibernate.validator.constraints.URL.message = \uc62c\ubc14\ub978 URL\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4 -org.hibernate.validator.constraints.br.CNPJ.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ube0c\ub77c\uc9c8 \ubc95\uc778 \ub0a9\uc138\uc790 \ub4f1\ub85d \ubc88\ud638(CNPJ)\uc785\ub2c8\ub2e4. -org.hibernate.validator.constraints.br.CPF.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ube0c\ub77c\uc9c8 \uac1c\uc778 \ub0a9\uc138\uc790 \ub4f1\ub85d \ubc88\ud638(CPF)\uc785\ub2c8\ub2e4. -org.hibernate.validator.constraints.br.TituloEleitoral.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ube0c\ub77c\uc9c8 \uc720\uad8c\uc790 ID \uce74\ub4dc \ubc88\ud638\uc785\ub2c8\ub2e4. +org.hibernate.validator.constraints.br.CNPJ.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ube0c\ub77c\uc9c8 \ubc95\uc778 \ub0a9\uc138\uc790 \ub4f1\ub85d \ubc88\ud638(CNPJ)\uc785\ub2c8\ub2e4 +org.hibernate.validator.constraints.br.CPF.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ube0c\ub77c\uc9c8 \uac1c\uc778 \ub0a9\uc138\uc790 \ub4f1\ub85d \ubc88\ud638(CPF)\uc785\ub2c8\ub2e4 +org.hibernate.validator.constraints.br.TituloEleitoral.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ube0c\ub77c\uc9c8 \uc720\uad8c\uc790 ID \uce74\ub4dc \ubc88\ud638\uc785\ub2c8\ub2e4 -org.hibernate.validator.constraints.pl.REGON.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ud3f4\ub780\ub4dc \ub0a9\uc138\uc790 \uc2dd\ubcc4 \ubc88\ud638(REGON)\uc785\ub2c8\ub2e4. -org.hibernate.validator.constraints.pl.NIP.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 VAT \uc2dd\ubcc4 \ubc88\ud638(NIP)\uc785\ub2c8\ub2e4. -org.hibernate.validator.constraints.pl.PESEL.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ud3f4\ub780\ub4dc \uad6d\ubbfc \uc2dd\ubcc4 \ubc88\ud638(PESEL)\uc785\ub2c8\ub2e4. +org.hibernate.validator.constraints.pl.REGON.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ud3f4\ub780\ub4dc \ub0a9\uc138\uc790 \uc2dd\ubcc4 \ubc88\ud638(REGON)\uc785\ub2c8\ub2e4 +org.hibernate.validator.constraints.pl.NIP.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 VAT \uc2dd\ubcc4 \ubc88\ud638(NIP)\uc785\ub2c8\ub2e4 +org.hibernate.validator.constraints.pl.PESEL.message = \uc62c\ubc14\ub974\uc9c0 \uc54a\uc740 \ud3f4\ub780\ub4dc \uad6d\ubbfc \uc2dd\ubcc4 \ubc88\ud638(PESEL)\uc785\ub2c8\ub2e4 org.hibernate.validator.constraints.time.DurationMax.message = \ub2e4\uc74c \uac12\ubcf4\ub2e4 \uc9e7\uac70\ub098 \uac19\uc544\uc57c \ud569\ub2c8\ub2e4${inclusive == true ? ' ' : ''}${days == 0 ? '' : days == 1 ? ' 1\uc77c' : ' ' += days += '\uc77c'}${hours == 0 ? '' : hours == 1 ? ' 1\uc2dc\uac04' : ' ' += hours += '\uc2dc\uac04'}${minutes == 0 ? '' : minutes == 1 ? ' 1\ubd84' : ' ' += minutes += '\ubd84'}${seconds == 0 ? '' : seconds == 1 ? ' 1\ucd08' : ' ' += seconds += '\ucd08'}${millis == 0 ? '' : millis == 1 ? ' 1\ubc00\ub9ac' : ' ' += millis += '\ubc00\ub9ac'}${nanos == 0 ? '' : nanos == 1 ? ' 1\ub098\ub178' : ' ' += nanos += '\ub098\ub178'} org.hibernate.validator.constraints.time.DurationMin.message = \ub2e4\uc74c \uac12\ubcf4\ub2e4 \uae38\uac70\ub098 \uac19\uc544\uc57c \ud569\ub2c8\ub2e4${inclusive == true ? ' ' : ''}${days == 0 ? '' : days == 1 ? ' 1\uc77c' : ' ' += days += '\uc77c'}${hours == 0 ? '' : hours == 1 ? ' 1\uc2dc\uac04' : ' ' += hours += '\uc2dc\uac04'}${minutes == 0 ? '' : minutes == 1 ? ' 1\ubd84' : ' ' += minutes += '\ubd84'}${seconds == 0 ? '' : seconds == 1 ? ' 1\ucd08' : ' ' += seconds += '\ucd08'}${millis == 0 ? '' : millis == 1 ? ' 1\ubc00\ub9ac' : ' ' += millis += '\ubc00\ub9ac'}${nanos == 0 ? '' : nanos == 1 ? ' 1\ub098\ub178' : ' ' += nanos += '\ub098\ub178'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pl.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pl.properties index 20a4e29d56..b0a9853af3 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pl.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pl.properties @@ -24,15 +24,15 @@ javax.validation.constraints.Size.message = wielko\u015b\u0107 musi n org.hibernate.validator.constraints.CreditCardNumber.message = niepoprawny numer karty kredytowej org.hibernate.validator.constraints.Currency.message = niepoprawna waluta (musi by\u0107 jedn\u0105 z nast\u0119puj\u0105cych: {value}) org.hibernate.validator.constraints.EAN.message = niepoprawny kod paskowy {type} -org.hibernate.validator.constraints.Email.message = nie jest poprawnie sformatowanym adresem e-mail +org.hibernate.validator.constraints.Email.message = musi by\u0107 poprawnie sformatowanym adresem e-mail org.hibernate.validator.constraints.ISBN.message = niepoprawny numer ISBN org.hibernate.validator.constraints.Length.message = d\u0142ugo\u015b\u0107 musi wynosi\u0107 od {min} do {max} org.hibernate.validator.constraints.CodePointLength.message = d\u0142ugo\u015b\u0107 musi wynosi\u0107 od {min} do {max} -org.hibernate.validator.constraints.LuhnCheck.message = Cyfra kontrolna dla warto\u015bci ${validatedValue} jest niepoprawna, sprawdzenie sumy kontrolnej za pomoc\u0105 algorytmu Luhn Modulo 10 nie powiod\u0142o si\u0119 -org.hibernate.validator.constraints.Mod10Check.message = Cyfra kontrolna dla warto\u015bci ${validatedValue} jest niepoprawna, sprawdzenie sumy kontrolnej za pomoc\u0105 algorytmu Modulo 10 nie powiod\u0142o si\u0119 -org.hibernate.validator.constraints.Mod11Check.message = Cyfra kontrolna dla warto\u015bci ${validatedValue} jest niepoprawna, sprawdzenie sumy kontrolnej za pomoc\u0105 algorytmu Modulo 11 nie powiod\u0142o si\u0119 -org.hibernate.validator.constraints.ModCheck.message = Cyfra kontrolna dla warto\u015bci ${validatedValue} jest niepoprawna, sprawdzenie sumy kontrolnej za pomoc\u0105 algorytmu ${modType} nie powiod\u0142o si\u0119 -org.hibernate.validator.constraints.NotBlank.message = nie mo\u017ce by\u0107 puste +org.hibernate.validator.constraints.LuhnCheck.message = cyfra kontrolna dla warto\u015bci ${validatedValue} jest niepoprawna, sprawdzenie sumy kontrolnej za pomoc\u0105 algorytmu Luhn Modulo 10 nie powiod\u0142o si\u0119 +org.hibernate.validator.constraints.Mod10Check.message = cyfra kontrolna dla warto\u015bci ${validatedValue} jest niepoprawna, sprawdzenie sumy kontrolnej za pomoc\u0105 algorytmu Modulo 10 nie powiod\u0142o si\u0119 +org.hibernate.validator.constraints.Mod11Check.message = cyfra kontrolna dla warto\u015bci ${validatedValue} jest niepoprawna, sprawdzenie sumy kontrolnej za pomoc\u0105 algorytmu Modulo 11 nie powiod\u0142o si\u0119 +org.hibernate.validator.constraints.ModCheck.message = cyfra kontrolna dla warto\u015bci ${validatedValue} jest niepoprawna, sprawdzenie sumy kontrolnej za pomoc\u0105 algorytmu ${modType} nie powiod\u0142o si\u0119 +org.hibernate.validator.constraints.NotBlank.message = nie mo\u017ce by\u0107 odst\u0119pem org.hibernate.validator.constraints.NotEmpty.message = nie mo\u017ce by\u0107 puste org.hibernate.validator.constraints.ParametersScriptAssert.message = warto\u015bciowanie wyra\u017cenia skryptu {script} nie zwr\u00f3ci\u0142o warto\u015bci true org.hibernate.validator.constraints.Range.message = musi nale\u017ce\u0107 do zakresu od {min} do {max} @@ -45,9 +45,9 @@ org.hibernate.validator.constraints.br.CNPJ.message = niepoprawn org.hibernate.validator.constraints.br.CPF.message = niepoprawny numer brazylijskiego rejestru podatkowego os\u00f3b fizycznych (CPF) org.hibernate.validator.constraints.br.TituloEleitoral.message = niepoprawny numer brazylijskiej karty identyfikacyjnej g\u0142osuj\u0105cego -org.hibernate.validator.constraints.pl.REGON.message = Niepoprawny numer identyfikacyjny polskiego podatnika (REGON) -org.hibernate.validator.constraints.pl.NIP.message = Niepoprawny number identyfikacyjny VAT (NIP) -org.hibernate.validator.constraints.pl.PESEL.message = Niepoprawny polski narodowy numer identyfikacyjny (PESEL) +org.hibernate.validator.constraints.pl.REGON.message = niepoprawny numer identyfikacyjny polskiego podatnika (REGON) +org.hibernate.validator.constraints.pl.NIP.message = niepoprawny number identyfikacyjny VAT (NIP) +org.hibernate.validator.constraints.pl.PESEL.message = niepoprawny polski narodowy numer identyfikacyjny (PESEL) org.hibernate.validator.constraints.time.DurationMax.message = musi by\u0107 ${inclusive == true ? 'r\u00f3wne lub ' : ''}kr\u00f3tsze ni\u017c${days == 0 ? '' : days == 1 ? ' 1 dzie\u0144' : ' ' += days += ' dni'}${hours == 0 ? '' : hours == 1 ? ' 1 godzina' : ' ' += hours += ' godz.'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minuta' : ' ' += minutes += ' min'}${seconds == 0 ? '' : seconds == 1 ? ' 1 sekunda' : ' ' += seconds += ' s'}${millis == 0 ? '' : millis == 1 ? ' 1 milisekunda' : ' ' += millis += ' ms'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanosekunda' : ' ' += nanos += ' ns'} org.hibernate.validator.constraints.time.DurationMin.message = musi by\u0107 ${inclusive == true ? 'r\u00f3wne lub ' : ''}d\u0142u\u017csze ni\u017c${days == 0 ? '' : days == 1 ? ' 1 dzie\u0144' : ' ' += days += ' dni'}${hours == 0 ? '' : hours == 1 ? ' 1 godzina' : ' ' += hours += ' godz.'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minuta' : ' ' += minutes += ' min'}${seconds == 0 ? '' : seconds == 1 ? ' 1 sekunda' : ' ' += seconds += ' s'}${millis == 0 ? '' : millis == 1 ? ' 1 milisekunda' : ' ' += millis += ' ms'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanosekunda' : ' ' += nanos += ' ns'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties index 85dd4bb102..6cf00dc834 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties @@ -24,15 +24,15 @@ javax.validation.constraints.Size.message = tamanho deve ser entre {m org.hibernate.validator.constraints.CreditCardNumber.message = n\u00famero do cart\u00e3o de cr\u00e9dito inv\u00e1lido org.hibernate.validator.constraints.Currency.message = moeda inv\u00e1lida (deve ser uma de {valor}) org.hibernate.validator.constraints.EAN.message = c\u00f3digo de barras {tipo} inv\u00e1lido -org.hibernate.validator.constraints.Email.message = n\u00e3o \u00e9 um endere\u00e7o de e-mail corretamente formado +org.hibernate.validator.constraints.Email.message = deve ser um endere\u00e7o de e-mail bem formado org.hibernate.validator.constraints.ISBN.message = ISBN inv\u00e1lido org.hibernate.validator.constraints.Length.message = o comprimento deve ser entre {m\u00edn} e {m\u00e1x} org.hibernate.validator.constraints.CodePointLength.message = o comprimento deve ser entre {m\u00edn} e {m\u00e1x} -org.hibernate.validator.constraints.LuhnCheck.message = O d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o Luhn Modulo 10 com falha -org.hibernate.validator.constraints.Mod10Check.message = O d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o Modulo 10 com falha -org.hibernate.validator.constraints.Mod11Check.message = O d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o Modulo 11 com falha -org.hibernate.validator.constraints.ModCheck.message = O d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o ${modType} com falha -org.hibernate.validator.constraints.NotBlank.message = n\u00e3o deve estar vazio +org.hibernate.validator.constraints.LuhnCheck.message = o d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o Luhn Modulo 10 com falha +org.hibernate.validator.constraints.Mod10Check.message = o d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o Modulo 10 com falha +org.hibernate.validator.constraints.Mod11Check.message = o d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o Modulo 11 com falha +org.hibernate.validator.constraints.ModCheck.message = o d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o ${modType} com falha +org.hibernate.validator.constraints.NotBlank.message = n\u00e3o deve estar em branco org.hibernate.validator.constraints.NotEmpty.message = n\u00e3o deve estar vazio org.hibernate.validator.constraints.ParametersScriptAssert.message = express\u00e3o de script "{script}" n\u00e3o avaliou para true org.hibernate.validator.constraints.Range.message = deve estar entre {m\u00edn} e {m\u00e1x} @@ -45,9 +45,9 @@ org.hibernate.validator.constraints.br.CNPJ.message = n\u00famer org.hibernate.validator.constraints.br.CPF.message = n\u00famero do registro de contribuinte individual brasileiro (CPF) inv\u00e1lido org.hibernate.validator.constraints.br.TituloEleitoral.message = n\u00famero do t\u00edtulo de eleitor brasileiro inv\u00e1lido -org.hibernate.validator.constraints.pl.REGON.message = N\u00famero de identifica\u00e7\u00e3o de contribuinte polon\u00eas (REGON) inv\u00e1lido -org.hibernate.validator.constraints.pl.NIP.message = N\u00famero de identifica\u00e7\u00e3o de VAT (NIP) inv\u00e1lido -org.hibernate.validator.constraints.pl.PESEL.message = N\u00famero de identifica\u00e7\u00e3o nacional polonesa (PESEL) inv\u00e1lido +org.hibernate.validator.constraints.pl.REGON.message = n\u00famero de identifica\u00e7\u00e3o de contribuinte polon\u00eas (REGON) inv\u00e1lido +org.hibernate.validator.constraints.pl.NIP.message = n\u00famero de identifica\u00e7\u00e3o de VAT (NIP) inv\u00e1lido +org.hibernate.validator.constraints.pl.PESEL.message = n\u00famero de identifica\u00e7\u00e3o nacional polonesa (PESEL) inv\u00e1lido org.hibernate.validator.constraints.time.DurationMax.message = deve ser menor que${inclusive == true ? ' ou igual a' : ''}${dias == 0 ? '' : dias == 1 ? ' 1 dia' : ' ' += dias += ' dias'}${horas == 0 ? '' : horas == 1 ? ' 1 hora' : ' ' += horas += ' horas'}${minutos == 0 ? '' : minutos == 1 ? ' 1 minuto' : ' ' += minutos += ' minutos'}${segundos == 0 ? '' : segundos == 1 ? ' 1 segundo' : ' ' += segundos += ' segundos'}${miliss == 0 ? '' : miliss == 1 ? ' 1 mili' : ' ' += miliss += ' miliss'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} org.hibernate.validator.constraints.time.DurationMin.message = deve ser maior que${inclusive == true ? ' ou igual a' : ''}${dias == 0 ? '' : dias == 1 ? ' 1 dia' : ' ' += dias += ' dias'}${horas == 0 ? '' : horas == 1 ? ' 1 hora' : ' ' += horas += ' horas'}${minutos == 0 ? '' : minutos == 1 ? ' 1 minuto' : ' ' += minutos += ' minutos'}${segundos == 0 ? '' : segundos == 1 ? ' 1 segundo' : ' ' += segundos += ' segundos'}${miliss == 0 ? '' : miliss == 1 ? ' 1 mili' : ' ' += miliss += ' miliss'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ro.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ro.properties index 502e9073b0..453a27e153 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ro.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ro.properties @@ -24,16 +24,16 @@ javax.validation.constraints.Size.message = dimensiunea trebuie s\u01 org.hibernate.validator.constraints.CreditCardNumber.message = num\u0103r invalid de card de credit org.hibernate.validator.constraints.Currency.message = moned\u0103 invalid\u0103 trebuie s\u0103 fie una din {valoare}) org.hibernate.validator.constraints.EAN.message = cod de bare {tip} invalid -org.hibernate.validator.constraints.Email.message = adres\u0103 de e-mail cu format incorect +org.hibernate.validator.constraints.Email.message = trebuie s\u0103 fie o adres\u0103 de e-mail cu format corect org.hibernate.validator.constraints.ISBN.message = ISBN invalid org.hibernate.validator.constraints.Length.message = lungimea trebuie s\u0103 fie \u00eentre {min} \u015fi {max} org.hibernate.validator.constraints.CodePointLength.message = lungimea trebuie s\u0103 fie \u00eentre {min} \u015fi {max} -org.hibernate.validator.constraints.LuhnCheck.message = Cifra de verificare pentru ${validatedValue} este invalid\u0103, suma de control Luhn Modulo 10 a e\u015fuat -org.hibernate.validator.constraints.Mod10Check.message = Cifra de verificare pentru ${validatedValue} este invalid\u0103, suma de control Modulo 10 a e\u015fuat -org.hibernate.validator.constraints.Mod11Check.message = Cifra de verificare pentru ${validatedValue} este invalid\u0103, suma de control Modulo 11 a e\u015fuat -org.hibernate.validator.constraints.ModCheck.message = Cifra de verificare pentru ${validatedValue} este invalid\u0103, suma de control ${modType} a e\u015fuat -org.hibernate.validator.constraints.NotBlank.message = poate s\u0103 nu fie gol -org.hibernate.validator.constraints.NotEmpty.message = poate s\u0103 nu fie gol +org.hibernate.validator.constraints.LuhnCheck.message = cifra de verificare pentru ${validatedValue} este invalid\u0103, suma de control Luhn Modulo 10 a e\u015fuat +org.hibernate.validator.constraints.Mod10Check.message = cifra de verificare pentru ${validatedValue} este invalid\u0103, suma de control Modulo 10 a e\u015fuat +org.hibernate.validator.constraints.Mod11Check.message = cifra de verificare pentru ${validatedValue} este invalid\u0103, suma de control Modulo 11 a e\u015fuat +org.hibernate.validator.constraints.ModCheck.message = cifra de verificare pentru ${validatedValue} este invalid\u0103, suma de control ${modType} a e\u015fuat +org.hibernate.validator.constraints.NotBlank.message = nu trebuie s\u0103 fie blanc +org.hibernate.validator.constraints.NotEmpty.message = nu trebuie s\u0103 fie gol org.hibernate.validator.constraints.ParametersScriptAssert.message = expresia de script "{script}" nu s-a evaluat la true org.hibernate.validator.constraints.Range.message = trebuie s\u0103 fie \u00eentre {min} \u015fi {max} org.hibernate.validator.constraints.SafeHtml.message = poate avea con\u0163inut HTML periculos @@ -45,9 +45,9 @@ org.hibernate.validator.constraints.br.CNPJ.message = num\u0103r org.hibernate.validator.constraints.br.CPF.message = num\u0103r de registru de contribuabil individual brazilian invalid (CPF) org.hibernate.validator.constraints.br.TituloEleitoral.message = num\u0103r invalid de carte de identitate de votant brazilian -org.hibernate.validator.constraints.pl.REGON.message = Num\u0103r invalid de identificare contribuabil polonez (REGON) -org.hibernate.validator.constraints.pl.NIP.message = Num\u0103r invalid de identificare VAT (NIP) -org.hibernate.validator.constraints.pl.PESEL.message = Num\u0103r invalid de identificare na\u0163ional polonez (PESEL) +org.hibernate.validator.constraints.pl.REGON.message = num\u0103r invalid de identificare contribuabil polonez (REGON) +org.hibernate.validator.constraints.pl.NIP.message = num\u0103r invalid de identificare VAT (NIP) +org.hibernate.validator.constraints.pl.PESEL.message = num\u0103r invalid de identificare na\u0163ional polonez (PESEL) org.hibernate.validator.constraints.time.DurationMax.message = trebuie s\u0103 fie mai scurt dec\u00e2t${inclusiv == true ? ' sau egal cu' : ''}${zile == 0 ? '' : zile == 1 ? ' 1 zi' : ' ' += zile += ' zile'}${ore == 0 ? '' : ore == 1 ? ' 1 or\u0103' : ' ' += ore += ' ore'}${minute == 0 ? '' : minute == 1 ? ' 1 minut' : ' ' += minute += ' minute'}${secunde == 0 ? '' : secunde == 1 ? ' 1 secund\u0103' : ' ' += secunde += ' secunde'}${milisecunde == 0 ? '' : milisecunde == 1 ? ' 1 milisecund\u0103' : ' ' += milisecunde += ' milisecunde'}${nanosecunde == 0 ? '' : nanosecunde == 1 ? ' 1 nanosecund\u0103' : ' ' += nanosecunde += ' nanosecunde'} org.hibernate.validator.constraints.time.DurationMin.message = trebuie s\u0103 fie mai lung dec\u00e2t${inclusiv == true ? ' sau egal cu' : ''}${zile == 0 ? '' : zile == 1 ? ' 1 zi' : ' ' += zile += ' zile'}${ore == 0 ? '' : ore == 1 ? ' 1 or\u0103' : ' ' += ore += ' ore'}${minute == 0 ? '' : minute == 1 ? ' 1 minut' : ' ' += minute += ' minute'}${secunde == 0 ? '' : secunde == 1 ? ' 1 secund\u0103' : ' ' += secunde += ' secunde'}${milisecunde == 0 ? '' : milisecunde == 1 ? ' 1 milisecund\u0103' : ' ' += milisecunde += ' milisecunde'}${nanosecunde == 0 ? '' : nanosecunde == 1 ? ' 1 nanosecund\u0103' : ' ' += nanosecunde += ' nanosecunde'} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/MessageInterpolationWithDefaultBundleTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/MessageInterpolationWithDefaultBundleTest.java index 7d906e726d..cb8922b041 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/MessageInterpolationWithDefaultBundleTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/MessageInterpolationWithDefaultBundleTest.java @@ -74,8 +74,8 @@ public void testEmailAndRangeMessageGermanLocale() { user.setAge( 16 ); Set> constraintViolations = validator.validate( user ); assertThat( constraintViolations ).containsOnlyViolations( - violationOf( Email.class ).withMessage( "keine g\u00FCltige E-Mail-Adresse" ), - violationOf( Range.class ).withMessage( "muss zwischen 18 und 21 liegen" ) + violationOf( Email.class ).withMessage( "muss eine korrekt formatierte E-Mail-Adresse sein" ), + violationOf( Range.class ).withMessage( "muss zwischen 18 und 21 sein" ) ); } @@ -90,8 +90,8 @@ public void testEmailAndRangeMessageFrenchLocale() { user.setAge( 16 ); Set> constraintViolations = validator.validate( user ); assertThat( constraintViolations ).containsOnlyViolations( - violationOf( Email.class ).withMessage( "doit \u00EAtre une adresse email bien form\u00E9e" ), - violationOf( Range.class ).withMessage( "doit \u00EAtre entre 18 et 21" ) + violationOf( Email.class ).withMessage( "doit être une adresse électronique syntaxiquement correcte" ), + violationOf( Range.class ).withMessage( "doit être compris entre 18 et 21" ) ); } diff --git a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java index bd6eaab0d8..0b368644f3 100644 --- a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java @@ -138,7 +138,7 @@ public void testExistingInitializedLocale() { Set> violations = validator.validate( new Bean( "", "invalid" ) ); assertThat( violations ).containsOnlyViolations( - violationOf( Email.class ).withProperty( "email" ).withMessage( "doit être une adresse email bien formée" ) ); + violationOf( Email.class ).withProperty( "email" ).withMessage( "doit être une adresse électronique syntaxiquement correcte" ) ); } finally { Locale.setDefault( defaultLocale ); @@ -176,7 +176,7 @@ public void testUninitializedLocale() { Set> violations = validator.validate( new Bean( "", "invalid" ) ); assertThat( violations ).containsOnlyViolations( - violationOf( Email.class ).withProperty( "email" ).withMessage( "doit être une adresse email bien formée" ) ); + violationOf( Email.class ).withProperty( "email" ).withMessage( "doit être une adresse électronique syntaxiquement correcte" ) ); } finally { Locale.setDefault( defaultLocale ); From c7361569410ab2e9e869c5d186ffba4ee644f481 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Thu, 15 Nov 2018 12:27:45 +0100 Subject: [PATCH 157/393] HV-1681 Remove bean type from value context This property can be removed from value context as it is not used in the code. --- .../internal/engine/ValidatorImpl.java | 2 +- .../internal/engine/ValueContext.java | 23 +++++-------------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index e5e32b449c..121125cae0 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -1246,7 +1246,7 @@ private ValueContext getValueContextForValueValidation(Class rootBe propertyPath.removeLeafNode(); - return ValueContext.getLocalExecutionContext( validatorScopedContext.getParameterNameProvider(), clazz, beanMetaData, propertyPath ); + return ValueContext.getLocalExecutionContext( validatorScopedContext.getParameterNameProvider(), beanMetaData, propertyPath ); } private boolean isValidationRequired(BaseBeanValidationContext validationContext, diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValueContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValueContext.java index 024b5419ec..a2e38b4a5f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValueContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValueContext.java @@ -39,11 +39,6 @@ public class ValueContext { */ private final T currentBean; - /** - * The class of the current bean. - */ - private final Class currentBeanType; - /** * The metadata of the current bean. */ @@ -75,32 +70,31 @@ public static ValueContext getLocalExecutionContext(BeanMetaDataMan ExecutableParameterNameProvider parameterNameProvider, T value, Validatable validatable, PathImpl propertyPath) { @SuppressWarnings("unchecked") Class rootBeanType = (Class) value.getClass(); - return new ValueContext<>( parameterNameProvider, value, rootBeanType, beanMetaDataManager.getBeanMetaData( rootBeanType ), validatable, propertyPath ); + return new ValueContext<>( parameterNameProvider, value, beanMetaDataManager.getBeanMetaData( rootBeanType ), validatable, propertyPath ); } @SuppressWarnings("unchecked") public static ValueContext getLocalExecutionContext(ExecutableParameterNameProvider parameterNameProvider, T value, BeanMetaData currentBeanMetaData, PathImpl propertyPath) { Class rootBeanType = (Class) value.getClass(); - return new ValueContext<>( parameterNameProvider, value, rootBeanType, (BeanMetaData) currentBeanMetaData, currentBeanMetaData, propertyPath ); + return new ValueContext<>( parameterNameProvider, value, (BeanMetaData) currentBeanMetaData, currentBeanMetaData, propertyPath ); } public static ValueContext getLocalExecutionContext(BeanMetaDataManager beanMetaDataManager, ExecutableParameterNameProvider parameterNameProvider, Class rootBeanType, Validatable validatable, PathImpl propertyPath) { BeanMetaData rootBeanMetaData = rootBeanType != null ? beanMetaDataManager.getBeanMetaData( rootBeanType ) : null; - return new ValueContext<>( parameterNameProvider, null, rootBeanType, rootBeanMetaData, validatable, propertyPath ); + return new ValueContext<>( parameterNameProvider, null, rootBeanMetaData, validatable, propertyPath ); } @SuppressWarnings("unchecked") - public static ValueContext getLocalExecutionContext(ExecutableParameterNameProvider parameterNameProvider, Class currentBeanType, + public static ValueContext getLocalExecutionContext(ExecutableParameterNameProvider parameterNameProvider, BeanMetaData currentBeanMetaData, PathImpl propertyPath) { - return new ValueContext<>( parameterNameProvider, null, currentBeanType, (BeanMetaData) currentBeanMetaData, currentBeanMetaData, propertyPath ); + return new ValueContext<>( parameterNameProvider, null, (BeanMetaData) currentBeanMetaData, currentBeanMetaData, propertyPath ); } - private ValueContext(ExecutableParameterNameProvider parameterNameProvider, T currentBean, Class currentBeanType, BeanMetaData currentBeanMetaData, Validatable validatable, PathImpl propertyPath) { + private ValueContext(ExecutableParameterNameProvider parameterNameProvider, T currentBean, BeanMetaData currentBeanMetaData, Validatable validatable, PathImpl propertyPath) { this.parameterNameProvider = parameterNameProvider; this.currentBean = currentBean; - this.currentBeanType = currentBeanType; this.currentBeanMetaData = currentBeanMetaData; this.currentValidatable = validatable; this.propertyPath = propertyPath; @@ -118,10 +112,6 @@ public final T getCurrentBean() { return currentBean; } - public final Class getCurrentBeanType() { - return currentBeanType; - } - public final BeanMetaData getCurrentBeanMetaData() { return currentBeanMetaData; } @@ -221,7 +211,6 @@ public String toString() { final StringBuilder sb = new StringBuilder(); sb.append( "ValueContext" ); sb.append( "{currentBean=" ).append( currentBean ); - sb.append( ", currentBeanType=" ).append( currentBeanType ); sb.append( ", propertyPath=" ).append( propertyPath ); sb.append( ", currentGroup=" ).append( currentGroup ); sb.append( ", currentValue=" ).append( currentValue ); From 9e0626b8318ba4bdf55580aacae3947410278129 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Wed, 21 Nov 2018 23:41:26 +0100 Subject: [PATCH 158/393] HV-1681 Separate out bean metadata aware ValueContext into own class - move all value context related classes to their own package - create ValueContexts helper class that contains static methods to create different contexts based on the needs - split existing ValueContext into two classes, to separate out bean metadata related functionality --- .../internal/engine/ValidatorImpl.java | 72 ++++++++----------- .../ComposingConstraintTree.java | 2 +- .../constraintvalidation/ConstraintTree.java | 2 +- .../SimpleConstraintTree.java | 2 +- .../AbstractValidationContext.java | 2 +- .../BaseBeanValidationContext.java | 2 +- .../BeanValidationContext.java | 2 +- .../ParameterExecutableValidationContext.java | 2 +- .../PropertyValidationContext.java | 4 +- ...eturnValueExecutableValidationContext.java | 2 +- .../validationcontext/ValidationContext.java | 2 +- .../engine/valuecontext/BeanValueContext.java | 31 ++++++++ .../{ => valuecontext}/ValueContext.java | 56 ++++----------- .../engine/valuecontext/ValueContexts.java | 50 +++++++++++++ .../metadata/core/MetaConstraint.java | 5 +- 15 files changed, 139 insertions(+), 97 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/BeanValueContext.java rename engine/src/main/java/org/hibernate/validator/internal/engine/{ => valuecontext}/ValueContext.java (69%) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/ValueContexts.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index 121125cae0..ba531590eb 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -47,6 +47,9 @@ import org.hibernate.validator.internal.engine.validationcontext.ExecutableValidationContext; import org.hibernate.validator.internal.engine.validationcontext.ValidationContextBuilder; import org.hibernate.validator.internal.engine.validationcontext.ValidatorScopedContext; +import org.hibernate.validator.internal.engine.valuecontext.BeanValueContext; +import org.hibernate.validator.internal.engine.valuecontext.ValueContext; +import org.hibernate.validator.internal.engine.valuecontext.ValueContexts; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorDescriptor; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorHelper; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; @@ -155,7 +158,7 @@ public final Set> validate(T object, Class... grou } ValidationOrder validationOrder = determineGroupValidationOrder( groups ); - ValueContext valueContext = ValueContext.getLocalExecutionContext( + BeanValueContext valueContext = ValueContexts.getLocalExecutionContextForBean( validatorScopedContext.getParameterNameProvider(), object, validationContext.getRootBeanMetaData(), @@ -178,7 +181,7 @@ public final Set> validateProperty(T object, String p return Collections.emptySet(); } - ValueContext valueContext = getValueContextForPropertyValidation( validationContext, propertyPath ); + BeanValueContext valueContext = getValueContextForPropertyValidation( validationContext, propertyPath ); if ( valueContext.getCurrentBean() == null ) { throw LOG.getUnableToReachPropertyToValidateException( validationContext.getRootBean(), propertyPath ); @@ -356,7 +359,7 @@ private ValidationOrder determineGroupValidationOrder(Class[] groups) { * * @return Set of constraint violations or the empty set if there were no violations. */ - private Set> validateInContext(BaseBeanValidationContext validationContext, ValueContext valueContext, + private Set> validateInContext(BaseBeanValidationContext validationContext, BeanValueContext valueContext, ValidationOrder validationOrder) { if ( valueContext.getCurrentBean() == null ) { return Collections.emptySet(); @@ -416,7 +419,7 @@ private Set> validateInContext(BaseBeanValidationC return validationContext.getFailingConstraints(); } - private void validateConstraintsForCurrentGroup(BaseBeanValidationContext validationContext, ValueContext valueContext) { + private void validateConstraintsForCurrentGroup(BaseBeanValidationContext validationContext, BeanValueContext valueContext) { // we are not validating the default group there is nothing special to consider. If we are validating the default // group sequence we have to consider that a class in the hierarchy could redefine the default group sequence. if ( !valueContext.validatingDefault() ) { @@ -427,7 +430,7 @@ private void validateConstraintsForCurrentGroup(BaseBeanValidationContext val } } - private void validateConstraintsForDefaultGroup(BaseBeanValidationContext validationContext, ValueContext valueContext) { + private void validateConstraintsForDefaultGroup(BaseBeanValidationContext validationContext, BeanValueContext valueContext) { final BeanMetaData beanMetaData = valueContext.getCurrentBeanMetaData(); final Map, Class> validatedInterfaces = new HashMap<>(); @@ -499,7 +502,7 @@ private boolean validateConstraintsForSingleDefaultGroupElement(BaseBeanVali return validationSuccessful; } - private void validateConstraintsForNonDefaultGroup(BaseBeanValidationContext validationContext, ValueContext valueContext) { + private void validateConstraintsForNonDefaultGroup(BaseBeanValidationContext validationContext, BeanValueContext valueContext) { validateMetaConstraints( validationContext, valueContext, valueContext.getCurrentBean(), valueContext.getCurrentBeanMetaData().getMetaConstraints() ); validationContext.markCurrentBeanAsProcessed( valueContext ); } @@ -516,7 +519,7 @@ private void validateMetaConstraints(BaseBeanValidationContext validationCont } private boolean validateMetaConstraint(BaseBeanValidationContext validationContext, ValueContext valueContext, Object parent, MetaConstraint metaConstraint) { - ValueContext.ValueState originalValueState = valueContext.getCurrentValueState(); + BeanValueContext.ValueState originalValueState = valueContext.getCurrentValueState(); valueContext.appendNode( metaConstraint.getLocation() ); boolean success = true; @@ -546,7 +549,7 @@ private boolean validateMetaConstraint(BaseBeanValidationContext validationCo */ private void validateCascadedConstraints(BaseBeanValidationContext validationContext, ValueContext valueContext) { Validatable validatable = valueContext.getCurrentValidatable(); - ValueContext.ValueState originalValueState = valueContext.getCurrentValueState(); + BeanValueContext.ValueState originalValueState = valueContext.getCurrentValueState(); for ( Cascadable cascadable : validatable.getCascadables() ) { valueContext.appendNode( cascadable ); @@ -596,7 +599,7 @@ private void validateCascadedAnnotatedObjectForCurrentGroup(Object value, BaseBe // already and need only to pass the current element ValidationOrder validationOrder = validationOrderGenerator.getValidationOrder( currentGroup, currentGroup != originalGroup ); - ValueContext cascadedValueContext = buildNewLocalExecutionContext( valueContext, value ); + BeanValueContext cascadedValueContext = buildNewLocalExecutionContext( valueContext, value ); validateInContext( validationContext, cascadedValueContext, validationOrder ); } @@ -674,7 +677,7 @@ private void doValidate(Object value, String nodeName) { // already and need only to pass the current element ValidationOrder validationOrder = validationOrderGenerator.getValidationOrder( currentGroup, currentGroup != originalGroup ); - ValueContext cascadedValueContext = buildNewLocalExecutionContext( valueContext, value ); + BeanValueContext cascadedValueContext = buildNewLocalExecutionContext( valueContext, value ); if ( cascadingMetaData.getDeclaredContainerClass() != null ) { cascadedValueContext.setTypeParameter( cascadingMetaData.getDeclaredContainerClass(), cascadingMetaData.getDeclaredTypeParameterIndex() ); @@ -736,13 +739,14 @@ private void validateCascadedContainerElementsInContext(Object value, BaseBeanVa } } - private ValueContext buildNewLocalExecutionContext(ValueContext valueContext, Object value) { - ValueContext newValueContext; + private BeanValueContext buildNewLocalExecutionContext(ValueContext valueContext, Object value) { + BeanValueContext newValueContext; Contracts.assertNotNull( value, "value cannot be null" ); - newValueContext = ValueContext.getLocalExecutionContext( + BeanMetaData beanMetaData = beanMetaDataManager.getBeanMetaData( value.getClass() ); + newValueContext = ValueContexts.getLocalExecutionContextForBean( validatorScopedContext.getParameterNameProvider(), value, - beanMetaDataManager.getBeanMetaData( value.getClass() ), + beanMetaData, valueContext.getPropertyPath() ); newValueContext.setCurrentValidatedValue( value ); @@ -752,7 +756,7 @@ private ValueContext buildNewLocalExecutionContext(ValueContext private Set> validateValueInContext(BaseBeanValidationContext validationContext, Object value, PathImpl propertyPath, ValidationOrder validationOrder) { - ValueContext valueContext = getValueContextForValueValidation( validationContext.getRootBeanClass(), propertyPath ); + BeanValueContext valueContext = getValueContextForValueValidation( validationContext.getRootBeanClass(), propertyPath ); valueContext.setCurrentValidatedValue( value ); BeanMetaData beanMetaData = valueContext.getCurrentBeanMetaData(); @@ -835,8 +839,7 @@ private void validateParametersInContext(ExecutableValidationContext vali } } - ValueContext cascadingValueContext = ValueContext.getLocalExecutionContext( - beanMetaDataManager, + ValueContext cascadingValueContext = ValueContexts.getLocalExecutionContextForExecutable( validatorScopedContext.getParameterNameProvider(), parameterValues, executableMetaData.getValidatableParametersMetaData(), @@ -968,24 +971,12 @@ private void validateParametersForSingleGroup(ExecutableValidationContext private ValueContext getExecutableValueContext(T object, ExecutableMetaData executableMetaData, Validatable validatable, Class group) { ValueContext valueContext; - if ( object != null ) { - valueContext = ValueContext.getLocalExecutionContext( - beanMetaDataManager, - validatorScopedContext.getParameterNameProvider(), - object, - validatable, - PathImpl.createPathForExecutable( executableMetaData ) - ); - } - else { - valueContext = ValueContext.getLocalExecutionContext( - beanMetaDataManager, - validatorScopedContext.getParameterNameProvider(), - (Class) null, //the type is not required in this case (only for cascaded validation) - validatable, - PathImpl.createPathForExecutable( executableMetaData ) - ); - } + valueContext = ValueContexts.getLocalExecutionContextForExecutable( + validatorScopedContext.getParameterNameProvider(), + object, + validatable, + PathImpl.createPathForExecutable( executableMetaData ) + ); valueContext.setCurrentGroup( group ); @@ -1021,8 +1012,7 @@ private void validateReturnValueInContext(ExecutableValidationContext ValueContext cascadingValueContext = null; if ( value != null ) { - cascadingValueContext = ValueContext.getLocalExecutionContext( - beanMetaDataManager, + cascadingValueContext = ValueContexts.getLocalExecutionContextForExecutable( validatorScopedContext.getParameterNameProvider(), value, executableMetaData.getReturnValueMetaData(), @@ -1132,7 +1122,7 @@ private void validateReturnValueForSingleGroup(BaseBeanValidationContext * @return Returns an instance of {@code ValueContext} which describes the local validation context associated to * the given property path. */ - private ValueContext getValueContextForPropertyValidation(BaseBeanValidationContext validationContext, PathImpl propertyPath) { + private BeanValueContext getValueContextForPropertyValidation(BaseBeanValidationContext validationContext, PathImpl propertyPath) { Class clazz = validationContext.getRootBeanClass(); BeanMetaData beanMetaData = validationContext.getRootBeanMetaData(); Object value = validationContext.getRootBean(); @@ -1194,7 +1184,7 @@ else if ( propertyPathNode.getKey() != null ) { propertyPath.removeLeafNode(); - return ValueContext.getLocalExecutionContext( validatorScopedContext.getParameterNameProvider(), value, beanMetaData, propertyPath ); + return ValueContexts.getLocalExecutionContextForBean( validatorScopedContext.getParameterNameProvider(), value, beanMetaData, propertyPath ); } /** @@ -1208,7 +1198,7 @@ else if ( propertyPathNode.getKey() != null ) { * @return Returns an instance of {@code ValueContext} which describes the local validation context associated to * the given property path. */ - private ValueContext getValueContextForValueValidation(Class rootBeanClass, + private BeanValueContext getValueContextForValueValidation(Class rootBeanClass, PathImpl propertyPath) { Class clazz = rootBeanClass; BeanMetaData beanMetaData = null; @@ -1246,7 +1236,7 @@ private ValueContext getValueContextForValueValidation(Class rootBe propertyPath.removeLeafNode(); - return ValueContext.getLocalExecutionContext( validatorScopedContext.getParameterNameProvider(), beanMetaData, propertyPath ); + return ValueContexts.getLocalExecutionContextForValueValidation( validatorScopedContext.getParameterNameProvider(), beanMetaData, propertyPath ); } private boolean isValidationRequired(BaseBeanValidationContext validationContext, diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java index 6e1a021c71..ea6db39743 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ComposingConstraintTree.java @@ -22,8 +22,8 @@ import javax.validation.ConstraintValidator; import org.hibernate.validator.constraints.CompositionType; -import org.hibernate.validator.internal.engine.ValueContext; import org.hibernate.validator.internal.engine.validationcontext.ValidationContext; +import org.hibernate.validator.internal.engine.valuecontext.ValueContext; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.logging.Log; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java index 760075ebfd..ecf5f75f9c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java @@ -18,7 +18,7 @@ import javax.validation.ConstraintValidator; import javax.validation.ValidationException; -import org.hibernate.validator.internal.engine.ValueContext; +import org.hibernate.validator.internal.engine.valuecontext.ValueContext; import org.hibernate.validator.internal.engine.validationcontext.ValidationContext; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.util.logging.Log; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java index 882786cf34..aae2dbb8ad 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/SimpleConstraintTree.java @@ -13,8 +13,8 @@ import javax.validation.ConstraintValidator; -import org.hibernate.validator.internal.engine.ValueContext; import org.hibernate.validator.internal.engine.validationcontext.ValidationContext; +import org.hibernate.validator.internal.engine.valuecontext.ValueContext; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java index 5700eb9ec1..c782d8fca3 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java @@ -25,11 +25,11 @@ import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; import org.hibernate.validator.internal.engine.MessageInterpolatorContext; -import org.hibernate.validator.internal.engine.ValueContext; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext; import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.engine.valuecontext.ValueContext; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BaseBeanValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BaseBeanValidationContext.java index 8428b05483..5656460d4a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BaseBeanValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BaseBeanValidationContext.java @@ -11,8 +11,8 @@ import javax.validation.Validator; import org.hibernate.validator.internal.engine.ValidatorImpl; -import org.hibernate.validator.internal.engine.ValueContext; import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.engine.valuecontext.ValueContext; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.core.MetaConstraint; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BeanValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BeanValidationContext.java index 3a6afdb698..ab7aa153d8 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BeanValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/BeanValidationContext.java @@ -14,9 +14,9 @@ import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; import org.hibernate.validator.internal.engine.ConstraintViolationImpl; -import org.hibernate.validator.internal.engine.ValueContext; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext; +import org.hibernate.validator.internal.engine.valuecontext.ValueContext; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; /** diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ParameterExecutableValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ParameterExecutableValidationContext.java index c7eaa48498..0cdf280854 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ParameterExecutableValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ParameterExecutableValidationContext.java @@ -19,12 +19,12 @@ import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; import org.hibernate.validator.internal.engine.ConstraintViolationImpl; -import org.hibernate.validator.internal.engine.ValueContext; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext; import org.hibernate.validator.internal.engine.constraintvalidation.CrossParameterConstraintValidatorContextImpl; import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.engine.valuecontext.ValueContext; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java index ba79e43a76..7151bcd59d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/PropertyValidationContext.java @@ -17,13 +17,13 @@ import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; import org.hibernate.validator.internal.engine.ConstraintViolationImpl; -import org.hibernate.validator.internal.engine.ValueContext; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext; +import org.hibernate.validator.internal.engine.valuecontext.ValueContext; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.core.MetaConstraint; -import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.location.AbstractPropertyConstraintLocation; +import org.hibernate.validator.internal.metadata.location.ConstraintLocation; import org.hibernate.validator.internal.metadata.location.TypeArgumentConstraintLocation; /** diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ReturnValueExecutableValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ReturnValueExecutableValidationContext.java index da619edddc..0c7715db79 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ReturnValueExecutableValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ReturnValueExecutableValidationContext.java @@ -17,9 +17,9 @@ import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; import org.hibernate.validator.internal.engine.ConstraintViolationImpl; -import org.hibernate.validator.internal.engine.ValueContext; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext; +import org.hibernate.validator.internal.engine.valuecontext.ValueContext; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContext.java index f13e148f17..29792a23bf 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContext.java @@ -15,7 +15,7 @@ import javax.validation.metadata.ConstraintDescriptor; import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; -import org.hibernate.validator.internal.engine.ValueContext; +import org.hibernate.validator.internal.engine.valuecontext.ValueContext; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/BeanValueContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/BeanValueContext.java new file mode 100644 index 0000000000..ced53a7403 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/BeanValueContext.java @@ -0,0 +1,31 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.valuecontext; + +import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; +import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; + +/** + * @author Marko Bekhta + */ +public class BeanValueContext extends ValueContext { + + /** + * The metadata of the current bean. + */ + private final BeanMetaData currentBeanMetaData; + + BeanValueContext(ExecutableParameterNameProvider parameterNameProvider, T currentBean, BeanMetaData currentBeanMetaData, PathImpl propertyPath) { + super( parameterNameProvider, currentBean, currentBeanMetaData, propertyPath ); + this.currentBeanMetaData = currentBeanMetaData; + } + + public final BeanMetaData getCurrentBeanMetaData() { + return currentBeanMetaData; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValueContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/ValueContext.java similarity index 69% rename from engine/src/main/java/org/hibernate/validator/internal/engine/ValueContext.java rename to engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/ValueContext.java index a2e38b4a5f..b70df17703 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValueContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/ValueContext.java @@ -4,7 +4,7 @@ * License: Apache License, Version 2.0 * See the license.txt file in the root directory or . */ -package org.hibernate.validator.internal.engine; +package org.hibernate.validator.internal.engine.valuecontext; import java.lang.reflect.TypeVariable; @@ -13,8 +13,6 @@ import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.engine.valueextraction.AnnotatedObject; import org.hibernate.validator.internal.engine.valueextraction.ArrayElement; -import org.hibernate.validator.internal.metadata.BeanMetaDataManager; -import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.facets.Cascadable; import org.hibernate.validator.internal.metadata.facets.Validatable; import org.hibernate.validator.internal.metadata.location.ConstraintLocation; @@ -39,11 +37,6 @@ public class ValueContext { */ private final T currentBean; - /** - * The metadata of the current bean. - */ - private final BeanMetaData currentBeanMetaData; - /** * The current property path we are validating. */ @@ -66,36 +59,9 @@ public class ValueContext { */ private ConstraintLocationKind constraintLocationKind; - public static ValueContext getLocalExecutionContext(BeanMetaDataManager beanMetaDataManager, - ExecutableParameterNameProvider parameterNameProvider, T value, Validatable validatable, PathImpl propertyPath) { - @SuppressWarnings("unchecked") - Class rootBeanType = (Class) value.getClass(); - return new ValueContext<>( parameterNameProvider, value, beanMetaDataManager.getBeanMetaData( rootBeanType ), validatable, propertyPath ); - } - - @SuppressWarnings("unchecked") - public static ValueContext getLocalExecutionContext(ExecutableParameterNameProvider parameterNameProvider, T value, - BeanMetaData currentBeanMetaData, PathImpl propertyPath) { - Class rootBeanType = (Class) value.getClass(); - return new ValueContext<>( parameterNameProvider, value, (BeanMetaData) currentBeanMetaData, currentBeanMetaData, propertyPath ); - } - - public static ValueContext getLocalExecutionContext(BeanMetaDataManager beanMetaDataManager, - ExecutableParameterNameProvider parameterNameProvider, Class rootBeanType, Validatable validatable, PathImpl propertyPath) { - BeanMetaData rootBeanMetaData = rootBeanType != null ? beanMetaDataManager.getBeanMetaData( rootBeanType ) : null; - return new ValueContext<>( parameterNameProvider, null, rootBeanMetaData, validatable, propertyPath ); - } - - @SuppressWarnings("unchecked") - public static ValueContext getLocalExecutionContext(ExecutableParameterNameProvider parameterNameProvider, - BeanMetaData currentBeanMetaData, PathImpl propertyPath) { - return new ValueContext<>( parameterNameProvider, null, (BeanMetaData) currentBeanMetaData, currentBeanMetaData, propertyPath ); - } - - private ValueContext(ExecutableParameterNameProvider parameterNameProvider, T currentBean, BeanMetaData currentBeanMetaData, Validatable validatable, PathImpl propertyPath) { + ValueContext(ExecutableParameterNameProvider parameterNameProvider, T currentBean, Validatable validatable, PathImpl propertyPath) { this.parameterNameProvider = parameterNameProvider; this.currentBean = currentBean; - this.currentBeanMetaData = currentBeanMetaData; this.currentValidatable = validatable; this.propertyPath = propertyPath; } @@ -112,10 +78,6 @@ public final T getCurrentBean() { return currentBean; } - public final BeanMetaData getCurrentBeanMetaData() { - return currentBeanMetaData; - } - public Validatable getCurrentValidatable() { return currentValidatable; } @@ -202,8 +164,8 @@ public final ValueState getCurrentValueState() { } public final void resetValueState(ValueState valueState) { - this.propertyPath = valueState.propertyPath; - this.currentValue = valueState.currentValue; + this.propertyPath = valueState.getPropertyPath(); + this.currentValue = valueState.getCurrentValue(); } @Override @@ -230,9 +192,17 @@ public static class ValueState { private final V currentValue; - private ValueState(PathImpl propertyPath, V currentValue) { + ValueState(PathImpl propertyPath, V currentValue) { this.propertyPath = propertyPath; this.currentValue = currentValue; } + + public PathImpl getPropertyPath() { + return propertyPath; + } + + public V getCurrentValue() { + return currentValue; + } } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/ValueContexts.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/ValueContexts.java new file mode 100644 index 0000000000..de4cd0f39a --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valuecontext/ValueContexts.java @@ -0,0 +1,50 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.valuecontext; + +import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; +import org.hibernate.validator.internal.metadata.facets.Validatable; +import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; + +/** + * @author Marko Bekhta + */ +public final class ValueContexts { + + private ValueContexts() { + } + + /** + * Creates a value context for validating an executable. Can be applied to both parameter and + * return value validation. Does not require a bean metadata information. + */ + public static ValueContext getLocalExecutionContextForExecutable( + ExecutableParameterNameProvider parameterNameProvider, + T value, + Validatable validatable, + PathImpl propertyPath) { + return new ValueContext<>( parameterNameProvider, value, validatable, propertyPath ); + } + + @SuppressWarnings("unchecked") + public static BeanValueContext getLocalExecutionContextForBean( + ExecutableParameterNameProvider parameterNameProvider, + T value, + BeanMetaData currentBeanMetaData, + PathImpl propertyPath) { + return new BeanValueContext<>( parameterNameProvider, value, (BeanMetaData) currentBeanMetaData, propertyPath ); + } + + @SuppressWarnings("unchecked") + public static BeanValueContext getLocalExecutionContextForValueValidation( + ExecutableParameterNameProvider parameterNameProvider, + BeanMetaData currentBeanMetaData, + PathImpl propertyPath) { + return new BeanValueContext<>( parameterNameProvider, null, (BeanMetaData) currentBeanMetaData, propertyPath ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java index 44e9577167..d551e2c54a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java @@ -15,10 +15,11 @@ import javax.validation.valueextraction.ValueExtractor; -import org.hibernate.validator.internal.engine.ValueContext; +import org.hibernate.validator.internal.engine.valuecontext.ValueContext; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; import org.hibernate.validator.internal.engine.validationcontext.ValidationContext; +import org.hibernate.validator.internal.engine.valuecontext.BeanValueContext; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorDescriptor; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorHelper; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; @@ -218,7 +219,7 @@ public void keyedValue(String nodeName, Object key, Object value) { } private void doValidate(Object value, String nodeName) { - ValueContext.ValueState originalValueState = valueContext.getCurrentValueState(); + BeanValueContext.ValueState originalValueState = valueContext.getCurrentValueState(); Class containerClass = currentValueExtractionPathNode.getContainerClass(); if ( containerClass != null ) { From 5a893bde8f3c700e079f29118d2588cc84109922 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Sun, 16 Dec 2018 19:14:37 +0100 Subject: [PATCH 159/393] HV-1681 Perform cascading validation on return value only if it is marked for cascading --- .../hibernate/validator/internal/engine/ValidatorImpl.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index ba531590eb..fc3a01de43 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -1011,7 +1011,9 @@ private void validateReturnValueInContext(ExecutableValidationContext ValueContext cascadingValueContext = null; - if ( value != null ) { + boolean isCascadingRequired = value != null && executableMetaData.isCascading(); + + if ( isCascadingRequired ) { cascadingValueContext = ValueContexts.getLocalExecutionContextForExecutable( validatorScopedContext.getParameterNameProvider(), value, @@ -1042,7 +1044,7 @@ private void validateReturnValueInContext(ExecutableValidationContext return; } - if ( value != null ) { + if ( isCascadingRequired ) { cascadingValueContext.setCurrentGroup( group.getDefiningClass() ); validateCascadedConstraints( validationContext, cascadingValueContext ); From c16b4b7639db988c4f48c2a69cc751e835a10470 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Tue, 18 Dec 2018 23:29:26 +0100 Subject: [PATCH 160/393] HV-1681 Change where the null check on metadata is performed --- .../ValidationContextBuilder.java | 21 ------------------- .../PredefinedScopeBeanMetaDataManager.java | 11 +++++++++- .../PredefinedScopeValidatorFactoryTest.java | 18 ++++++++++++++++ 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java index ea3c00bf61..0d54a34358 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java @@ -6,7 +6,6 @@ */ package org.hibernate.validator.internal.engine.validationcontext; -import java.lang.invoke.MethodHandles; import java.lang.reflect.Executable; import javax.validation.ConstraintValidatorFactory; @@ -17,8 +16,6 @@ import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; -import org.hibernate.validator.internal.util.logging.Log; -import org.hibernate.validator.internal.util.logging.LoggerFactory; /** * Builder for creating {@link AbstractValidationContext}s suited for the different kinds of validation. @@ -28,8 +25,6 @@ */ public class ValidationContextBuilder { - private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - private final BeanMetaDataManager beanMetaDataManager; private final ConstraintValidatorManager constraintValidatorManager; private final ConstraintValidatorFactory constraintValidatorFactory; @@ -57,8 +52,6 @@ public BaseBeanValidationContext forValidate(T rootBean) { Class rootBeanClass = (Class) rootBean.getClass(); BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); - checkRootBeanMetaData( rootBeanClass, rootBeanMetaData ); - return new BeanValidationContext<>( constraintValidatorManager, constraintValidatorFactory, @@ -76,8 +69,6 @@ public BaseBeanValidationContext forValidateProperty(T rootBean, PathImpl Class rootBeanClass = (Class) rootBean.getClass(); BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); - checkRootBeanMetaData( rootBeanClass, rootBeanMetaData ); - return new PropertyValidationContext<>( constraintValidatorManager, constraintValidatorFactory, @@ -94,8 +85,6 @@ public BaseBeanValidationContext forValidateProperty(T rootBean, PathImpl public BaseBeanValidationContext forValidateValue(Class rootBeanClass, PathImpl propertyPath) { BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); - checkRootBeanMetaData( rootBeanClass, rootBeanMetaData ); - return new PropertyValidationContext<>( constraintValidatorManager, constraintValidatorFactory, @@ -117,8 +106,6 @@ public ExecutableValidationContext forValidateParameters( Class rootBeanClass = rootBean != null ? (Class) rootBean.getClass() : (Class) executable.getDeclaringClass(); BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); - checkRootBeanMetaData( rootBeanClass, rootBeanMetaData ); - return new ParameterExecutableValidationContext<>( constraintValidatorManager, constraintValidatorFactory, @@ -142,8 +129,6 @@ public ExecutableValidationContext forValidateReturnValue( Class rootBeanClass = rootBean != null ? (Class) rootBean.getClass() : (Class) executable.getDeclaringClass(); BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); - checkRootBeanMetaData( rootBeanClass, rootBeanMetaData ); - return new ReturnValueExecutableValidationContext<>( constraintValidatorManager, constraintValidatorFactory, @@ -158,10 +143,4 @@ public ExecutableValidationContext forValidateReturnValue( executableReturnValue ); } - - private void checkRootBeanMetaData(Class rootBeanClass, BeanMetaData rootBeanMetaData) { - if ( rootBeanMetaData == null ) { - throw LOG.uninitializedBeanMetaData( rootBeanClass ); - } - } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java index 319951ff28..87998ae899 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java @@ -8,6 +8,7 @@ import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; +import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -30,9 +31,13 @@ import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; public class PredefinedScopeBeanMetaDataManager implements BeanMetaDataManager { + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + /** * Used to cache the constraint meta data for validated entities */ @@ -84,7 +89,11 @@ public PredefinedScopeBeanMetaDataManager(ConstraintCreationContext constraintCr @SuppressWarnings("unchecked") @Override public BeanMetaData getBeanMetaData(Class beanClass) { - return (BeanMetaData) beanMetaDataMap.get( beanClass.getName() ); + BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataMap.get( beanClass.getName() ); + if ( beanMetaData == null ) { + throw LOG.uninitializedBeanMetaData( beanClass ); + } + return beanMetaData; } @Override diff --git a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java index 0b368644f3..4e270fd60e 100644 --- a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java @@ -165,6 +165,12 @@ public void testUnavailableInitializedLocale() { } } + @TestForIssue(jiraKey = "HV-1681") + @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000249:.*") + public void testValidOnUnknownBean() { + getValidator().validate( new AnotherBean() ); + } + @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000250:.*") public void testUninitializedLocale() { Locale defaultLocale = Locale.getDefault(); @@ -186,6 +192,7 @@ public void testUninitializedLocale() { private static Validator getValidator() { Set> beanMetaDataToInitialize = new HashSet<>(); beanMetaDataToInitialize.add( Bean.class ); + beanMetaDataToInitialize.add( AnotherBean.class ); ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) .configure() @@ -240,6 +247,17 @@ public void setEmail(@Email String email) { } } + private static class AnotherBean { + + @Valid + private final UnknownBean bean; + + + private AnotherBean() { + bean = new UnknownBean(); + } + } + private static class UnknownBean { public UnknownBean() { From 47740ac0f45aef8d3f6a4ab75954938a0525ecea Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 18 Dec 2018 15:29:33 +0100 Subject: [PATCH 161/393] HV-1682 Introduce BeanMetaDataClassNormalizer in predefined scope The idea is to be able to normalize the class and get the parent in the case of a generated proxy. --- ...dScopeHibernateValidatorConfiguration.java | 5 +++ .../PredefinedScopeConfigurationImpl.java | 13 ++++++ .../PredefinedScopeValidatorFactoryImpl.java | 2 + .../ValidatorFactoryConfigurationHelper.java | 10 +++++ .../DefaultBeanMetaDataClassNormalizer.java | 24 ++++++++++ .../PredefinedScopeBeanMetaDataManager.java | 27 ++++++----- .../metadata/BeanMetaDataClassNormalizer.java | 39 ++++++++++++++++ .../PredefinedScopeValidatorFactoryTest.java | 45 +++++++++++++++++++ 8 files changed, 154 insertions(+), 11 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/metadata/DefaultBeanMetaDataClassNormalizer.java create mode 100644 engine/src/main/java/org/hibernate/validator/metadata/BeanMetaDataClassNormalizer.java diff --git a/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java index 72a9d9809a..ff8a7ac33d 100644 --- a/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java @@ -9,6 +9,8 @@ import java.util.Locale; import java.util.Set; +import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; + /** * Extension of {@link HibernateValidatorConfiguration} with additional methods dedicated to defining the predefined * scope of bean validation e.g. validated classes, constraint validators... @@ -25,4 +27,7 @@ public interface PredefinedScopeHibernateValidatorConfiguration extends BaseHibe @Incubating PredefinedScopeHibernateValidatorConfiguration initializeLocales(Set locales); + + @Incubating + PredefinedScopeHibernateValidatorConfiguration beanMetaDataClassNormalizer(BeanMetaDataClassNormalizer beanMetaDataClassNormalizer); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java index 248f311c31..8d8b53a986 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java @@ -15,6 +15,7 @@ import org.hibernate.validator.PredefinedScopeHibernateValidatorConfiguration; import org.hibernate.validator.internal.util.CollectionHelper; +import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; /** * @author Guillaume Smet @@ -24,6 +25,8 @@ public class PredefinedScopeConfigurationImpl extends AbstractConfigurationImpl< private Set> beanClassesToInitialize; + private BeanMetaDataClassNormalizer beanMetaDataClassNormalizer; + public PredefinedScopeConfigurationImpl(BootstrapState state) { super( state ); } @@ -47,4 +50,14 @@ public PredefinedScopeHibernateValidatorConfiguration initializeLocales(Set constraintMappings, ConstraintHelper constraintHelper) { Set> definedConstraints = newHashSet(); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/DefaultBeanMetaDataClassNormalizer.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/DefaultBeanMetaDataClassNormalizer.java new file mode 100644 index 0000000000..a40a987786 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/DefaultBeanMetaDataClassNormalizer.java @@ -0,0 +1,24 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.metadata; + +import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; + +/** + * The default implementation of {@link BeanMetaDataClassNormalizer}. + *

+ * Simply returns the provided class. + * + * @author Guillaume Smet + */ +public class DefaultBeanMetaDataClassNormalizer implements BeanMetaDataClassNormalizer { + + @Override + public Class normalize(Class beanClass) { + return beanClass; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java index 87998ae899..4751ebc4a4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java @@ -31,17 +31,21 @@ import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper; +import org.hibernate.validator.internal.util.classhierarchy.Filters; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; public class PredefinedScopeBeanMetaDataManager implements BeanMetaDataManager { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + private final BeanMetaDataClassNormalizer beanMetaDataClassNormalizer; + /** * Used to cache the constraint meta data for validated entities */ - private final Map> beanMetaDataMap; + private final Map, BeanMetaData> beanMetaDataMap; public PredefinedScopeBeanMetaDataManager(ConstraintCreationContext constraintCreationContext, ExecutableHelper executableHelper, @@ -50,6 +54,7 @@ public PredefinedScopeBeanMetaDataManager(ConstraintCreationContext constraintCr ValidationOrderGenerator validationOrderGenerator, List optionalMetaDataProviders, MethodValidationConfiguration methodValidationConfiguration, + BeanMetaDataClassNormalizer beanMetaDataClassNormalizer, Set> beanClassesToInitialize) { AnnotationProcessingOptions annotationProcessingOptions = getAnnotationProcessingOptionsFromNonDefaultProviders( optionalMetaDataProviders ); AnnotationMetaDataProvider defaultProvider = new AnnotationMetaDataProvider( @@ -66,30 +71,30 @@ public PredefinedScopeBeanMetaDataManager(ConstraintCreationContext constraintCr metaDataProviders.add( defaultProvider ); metaDataProviders.addAll( optionalMetaDataProviders ); - Map> tmpBeanMetadataMap = new HashMap<>(); + Map, BeanMetaData> tmpBeanMetadataMap = new HashMap<>(); for ( Class validatedClass : beanClassesToInitialize ) { - BeanMetaData beanMetaData = createBeanMetaData( constraintCreationContext, executableHelper, parameterNameProvider, - javaBeanHelper, validationOrderGenerator, optionalMetaDataProviders, methodValidationConfiguration, - metaDataProviders, validatedClass ); - - tmpBeanMetadataMap.put( validatedClass.getName(), beanMetaData ); + @SuppressWarnings("unchecked") + List> classHierarchy = (List>) (Object) ClassHierarchyHelper.getHierarchy( validatedClass, Filters.excludeInterfaces() ); - for ( Class parentClass : beanMetaData.getClassHierarchy() ) { - tmpBeanMetadataMap.put( parentClass.getName(), + // note that the hierarchy also contains the initial class + for ( Class hierarchyElement : classHierarchy ) { + tmpBeanMetadataMap.put( beanMetaDataClassNormalizer.normalize( hierarchyElement ), createBeanMetaData( constraintCreationContext, executableHelper, parameterNameProvider, javaBeanHelper, validationOrderGenerator, optionalMetaDataProviders, methodValidationConfiguration, - metaDataProviders, parentClass ) ); + metaDataProviders, hierarchyElement ) ); } } this.beanMetaDataMap = CollectionHelper.toImmutableMap( tmpBeanMetadataMap ); + + this.beanMetaDataClassNormalizer = beanMetaDataClassNormalizer; } @SuppressWarnings("unchecked") @Override public BeanMetaData getBeanMetaData(Class beanClass) { - BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataMap.get( beanClass.getName() ); + BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataMap.get( beanMetaDataClassNormalizer.normalize( beanClass ) ); if ( beanMetaData == null ) { throw LOG.uninitializedBeanMetaData( beanClass ); } diff --git a/engine/src/main/java/org/hibernate/validator/metadata/BeanMetaDataClassNormalizer.java b/engine/src/main/java/org/hibernate/validator/metadata/BeanMetaDataClassNormalizer.java new file mode 100644 index 0000000000..e5d50b005f --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/metadata/BeanMetaDataClassNormalizer.java @@ -0,0 +1,39 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.metadata; + +import org.hibernate.validator.Incubating; + +/** + * Define how the validated class is normalized before being used as the key to get the bean metadata. + *

+ * In the case of the predefined scope validator factory, we have to register all the classes that will ever be + * validated. To validate method calls, frameworks usually generate proxies to intercept the calls. Such proxies might + * be hard to register in the predefined scope validator factory as they are generated code. + *

+ * This contract allows to normalize the class before obtaining the metadata from the + * {@code PredefinedScopeBeanMetaDataManager} so that we only have to register the original bean class and not the proxy + * class. + *

+ * Apart from avoiding the need to register the class, it also avoids generating unnecessary metadata for the proxy + * classes. + * + * @author Guillaume Smet + * @since 6.1 + */ +@Incubating +public interface BeanMetaDataClassNormalizer { + + /** + * Normalizes the provided class as the key used to get the bean metadata from the + * {@code PredefinedScopeBeanMetaDataManager}. + * + * @param beanClass the original bean class + * @return the normalized class + */ + Class normalize(Class beanClass); +} diff --git a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java index 4e270fd60e..624e9bc1d4 100644 --- a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java @@ -26,6 +26,7 @@ import javax.validation.constraints.NotNull; import org.hibernate.validator.PredefinedScopeHibernateValidator; +import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; import org.hibernate.validator.testutil.TestForIssue; import org.testng.annotations.Test; @@ -189,6 +190,32 @@ public void testUninitializedLocale() { } } + @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000249:.*") + public void testBeanMetaDataClassNormalizerNoNormalizer() { + Validator validator = getValidator(); + + validator.validate( new BeanProxy() ); + } + + @Test + public void testBeanMetaDataClassNormalizer() { + Set> beanMetaDataToInitialize = new HashSet<>(); + beanMetaDataToInitialize.add( Bean.class ); + + ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) + .configure() + .initializeBeanMetaData( beanMetaDataToInitialize ) + .initializeLocales( Collections.singleton( Locale.ENGLISH ) ) + .beanMetaDataClassNormalizer( new MyProxyInterfaceBeanMetaDataClassNormalizer() ) + .buildValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + + Set> violations = validator.validate( new BeanProxy() ); + assertThat( violations ).containsOnlyViolations( + violationOf( NotNull.class ).withProperty( "property" ) ); + } + private static Validator getValidator() { Set> beanMetaDataToInitialize = new HashSet<>(); beanMetaDataToInitialize.add( Bean.class ); @@ -276,4 +303,22 @@ public String getMethod() { public void setMethod(String parameter) { } } + + private interface MyProxyInterface { + } + + private static class MyProxyInterfaceBeanMetaDataClassNormalizer implements BeanMetaDataClassNormalizer { + + @Override + public Class normalize(Class beanClass) { + if ( MyProxyInterface.class.isAssignableFrom( beanClass ) ) { + return beanClass.getSuperclass(); + } + + return beanClass; + } + } + + private static class BeanProxy extends Bean implements MyProxyInterface { + } } From 3c32dd91b6cc94e8d74cd110ade255e05d7aa739 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Wed, 19 Dec 2018 19:38:36 +0000 Subject: [PATCH 162/393] [Jenkins release job] README.md updated by release build 6.1.0.Alpha2 --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3e5ff4849f..0f018cf434 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hibernate Validator -*Version: 6.1.0.Alpha1 - 11-12-2018* +*Version: 6.1.0.Alpha2 - 19-12-2018* ## What is it? @@ -35,7 +35,7 @@ Logging will delegate any log requests to that provider. org.hibernate.validator hibernate-validator - 6.1.0.Alpha1 + 6.1.0.Alpha2 You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. @@ -54,7 +54,7 @@ extension by adding the following dependency: org.hibernate.validator hibernate-validator-cdi - 6.1.0.Alpha1 + 6.1.0.Alpha2 * _hibernate-validator-annotation-processor-<version>.jar_ is an optional jar which can be integrated with your build From d285681f869365ec059962e7d40515f027dde0d2 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Wed, 19 Dec 2018 19:38:36 +0000 Subject: [PATCH 163/393] [Jenkins release job] changelog.txt updated by release build 6.1.0.Alpha2 --- changelog.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/changelog.txt b/changelog.txt index e7fb5a30db..8ad3b75d7d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,18 @@ Hibernate Validator Changelog ============================= +6.1.0.Alpha2 (19-12-2018) +------------------------- + +** Bug + * HV-1681 - engine - PredefinedScopeValidatorFactory and @Valid on unregistered bean throws a NPE + +** Improvement + * HV-1651 - translations - Contribute additional language translations from OpenLiberty + +** New Feature + * HV-1682 - engine - Provide a way to normalize the class before getting the bean metadata + 6.1.0.Alpha1 (11-12-2018) ------------------------- From c0633446a8d9de119c6936f177fe760e8deb2154 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Wed, 19 Dec 2018 19:38:42 +0000 Subject: [PATCH 164/393] [Jenkins release job] Preparing release 6.1.0.Alpha2 --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 6b70540803..dcd6d973c0 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 021058c8f5..b95d626e9f 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index 64d7dc2320..70244a704f 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index a60c2e907e..4702a9222b 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 76e5181564..172ba96f23 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index 5fd0209f0b..e9bfa0360d 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 7e78f49241..ac44af49f4 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index b9eacc9ca4..b166637b70 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 55c15d1c8c..caa4af5b49 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 28ce4576ea..fae3db5130 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 1b9ec9f304..b8e50c5486 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index fc4f7e3a85..a1257fd82b 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index 09262ee135..0cc9d11d3c 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 ../pom.xml diff --git a/pom.xml b/pom.xml index 077d502e5d..ea870daa23 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 3f99228d35..b296b03119 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index acc9a54560..9838f59591 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index d793ee6b6e..3fc2b01827 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index c2eba20d47..22d51c7a38 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 6516654b3f..e6613e7b68 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 4b01b88584..d9e833ae89 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 3b0766e5c7..a063e4035b 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha2 hibernate-validator-test-utils From 7cd60569c51ffe8327b341b5d2514e0c85c38117 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Wed, 19 Dec 2018 19:41:58 +0000 Subject: [PATCH 165/393] [Jenkins release job] Preparing next development iteration --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index dcd6d973c0..6b70540803 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index b95d626e9f..021058c8f5 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index 70244a704f..64d7dc2320 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index 4702a9222b..a60c2e907e 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 172ba96f23..76e5181564 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index e9bfa0360d..5fd0209f0b 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index ac44af49f4..7e78f49241 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index b166637b70..b9eacc9ca4 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index caa4af5b49..55c15d1c8c 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index fae3db5130..28ce4576ea 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index b8e50c5486..1b9ec9f304 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index a1257fd82b..fc4f7e3a85 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index 0cc9d11d3c..09262ee135 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index ea870daa23..077d502e5d 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index b296b03119..3f99228d35 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index 9838f59591..acc9a54560 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index 3fc2b01827..d793ee6b6e 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index 22d51c7a38..c2eba20d47 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index e6613e7b68..6516654b3f 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index d9e833ae89..4b01b88584 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index a063e4035b..3b0766e5c7 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha2 + 6.1.0-SNAPSHOT hibernate-validator-test-utils From b74e65cd1d601f33cbd69b48eb8112be6c1650a1 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Fri, 21 Dec 2018 16:25:12 +0100 Subject: [PATCH 166/393] HV-1683 Update the version of javadoc plugin --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 077d502e5d..ce4f1a45e6 100644 --- a/pom.xml +++ b/pom.xml @@ -218,7 +218,7 @@ 0.11.0 3.0.2 1.3.0 - 3.0.0 + 3.0.1 3.0 2.5.3 3.0.2 From fe44f61669494a261085bc966b94ea02e09050fb Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Fri, 21 Dec 2018 16:26:44 +0100 Subject: [PATCH 167/393] HV-1683 Various minor javadoc updates --- .../ap/internal/checks/GroupSequenceProviderCheck.java | 2 +- .../hibernate/validator/internal/engine/ValidatorImpl.java | 2 +- .../validator/internal/metadata/core/MetaConstraint.java | 2 +- .../metadata/provider/AnnotationMetaDataProvider.java | 5 +++-- .../metadata/provider/ProgrammaticMetaDataProvider.java | 2 +- .../validator/test/cfg/ConfigurationFilePropertiesTest.java | 2 ++ .../serialization/CustomConstraintSerializableTest.java | 5 ++--- ...nalTypeAnnotationConstraintUsingValidatePropertyTest.java | 2 +- .../engine/valueextraction/UnwrapValidatedValueTest.java | 2 +- .../util/privilegedactions/GetAnnotationsParameterTest.java | 2 +- 10 files changed, 14 insertions(+), 12 deletions(-) diff --git a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/checks/GroupSequenceProviderCheck.java b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/checks/GroupSequenceProviderCheck.java index 9a420a18f5..bfd0b0170f 100644 --- a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/checks/GroupSequenceProviderCheck.java +++ b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/checks/GroupSequenceProviderCheck.java @@ -182,7 +182,7 @@ public Boolean visitExecutableAsConstructor(ExecutableElement constructorElement * * @param typeMirror The {@code TypeMirror} instance. * - * @return The generic type or {@code null} if the given type doesn't implement the {@link org.hibernate.validator.group.DefaultGroupSequenceProvider} interface. + * @return The generic type or {@code null} if the given type doesn't implement the {@link org.hibernate.validator.spi.group.DefaultGroupSequenceProvider} interface. */ private TypeMirror retrieveGenericProviderType(TypeMirror typeMirror) { return typeMirror.accept( diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index fc3a01de43..cf1b55f726 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -102,7 +102,7 @@ public class ValidatorImpl implements Validator, ExecutableValidator { /** * {@link TraversableResolver} as passed to the constructor of this instance. - * Never use it directly, always use {@link #getCachingTraversableResolver()} to retrieved the single threaded caching wrapper. + * Never use it directly, always use {@link TraversableResolvers#wrapWithCachingForSingleValidation(TraversableResolver, boolean)} to retrieved the single threaded caching wrapper. */ private final TraversableResolver traversableResolver; diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java index d551e2c54a..9a4cafcbdb 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java @@ -66,7 +66,7 @@ public class MetaConstraint { /** * @param constraintDescriptor The constraint descriptor for this constraint * @param location meta data about constraint placement - * @param valueExtractorDescriptors the potential {@link ValueExtractor}s used to extract the value to validate + * @param valueExtractionPath the potential {@link ValueExtractor}s used to extract the value to validate * @param validatedValueType the type of the validated element */ MetaConstraint(ConstraintValidatorManager constraintValidatorManager, ConstraintDescriptorImpl constraintDescriptor, diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java index 7d5c3b4ffb..17b38c2fb7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java @@ -59,7 +59,7 @@ import org.hibernate.validator.internal.metadata.raw.ConstrainedType; import org.hibernate.validator.internal.properties.Callable; import org.hibernate.validator.internal.properties.Constrainable; -import org.hibernate.validator.internal.properties.Property; +import org.hibernate.validator.internal.properties.Getter; import org.hibernate.validator.internal.properties.javabean.JavaBeanAnnotatedConstrainable; import org.hibernate.validator.internal.properties.javabean.JavaBeanAnnotatedElement; import org.hibernate.validator.internal.properties.javabean.JavaBeanExecutable; @@ -817,7 +817,8 @@ private CascadingMetaDataBuilder getCascadingMetaData(JavaBeanAnnotatedElement a * The location of a type argument before it is really considered a constraint location. *

* It avoids initializing a constraint location if we did not find any constraints. This is especially useful in - * a Java 9 environment as {@link ConstraintLocation#forProperty(Property)} tries to make the {@code Member} accessible + * a Java 9 environment as {@link ConstraintLocation#forField(org.hibernate.validator.internal.properties.Field)} + * or {@link ConstraintLocation#forGetter(Getter)} tries to make the {@code Member} accessible * which might not be possible (for instance for {@code java.util} classes). */ private interface TypeArgumentLocation { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/ProgrammaticMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/ProgrammaticMetaDataProvider.java index 6a98e446ea..3d3d8828e7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/ProgrammaticMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/ProgrammaticMetaDataProvider.java @@ -84,7 +84,7 @@ private static Map> createBeanConfigurations(Set{@code * true * true * true * true + * } * * The Maven build runs this test in a separate execution of surefire, which adds the * path to the required file onto its classpath. diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/serialization/CustomConstraintSerializableTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/serialization/CustomConstraintSerializableTest.java index ab775e2242..12318193c7 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/serialization/CustomConstraintSerializableTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/serialization/CustomConstraintSerializableTest.java @@ -22,10 +22,9 @@ * simple custom Email validation constraint taken from this blog gives a validation result that is not Serializable with * Hibernate Validator 4.0.2.GA with underlying cause that - *

+ *

* {@code org.hibernate.validator.internal.util.annotationfactory.AnnotationProxy} - *

- *

+ *

* Note that Hibernate Validator does not guarantee at all that a * {@link ConstraintViolation} is Serializable because an entity need not be * Serializable, but otherwise there should not be much of a problem (right?). diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/valueextraction/OptionalTypeAnnotationConstraintUsingValidatePropertyTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/valueextraction/OptionalTypeAnnotationConstraintUsingValidatePropertyTest.java index 6f38f0ab48..c0b999a1a1 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/valueextraction/OptionalTypeAnnotationConstraintUsingValidatePropertyTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/valueextraction/OptionalTypeAnnotationConstraintUsingValidatePropertyTest.java @@ -41,7 +41,7 @@ import org.testng.annotations.Test; /** - * Test combination of {@link Optional} and {@link UnwrapValidatedValue} on fields using validate property. + * Test combination of {@link Optional} and {@link Unwrapping.Unwrap} on fields using validate property. * * @author Davide D'Alto */ diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/valueextraction/UnwrapValidatedValueTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/valueextraction/UnwrapValidatedValueTest.java index 9320954b44..38580e385d 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/valueextraction/UnwrapValidatedValueTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/valueextraction/UnwrapValidatedValueTest.java @@ -39,7 +39,7 @@ import org.testng.annotations.Test; /** - * Test for unwrapping validated values via {@link org.hibernate.validator.valuehandling.UnwrapValidatedValue}. + * Test for unwrapping validated values via {@link Unwrapping.Unwrap}. * * @author Gunnar Morling */ diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/util/privilegedactions/GetAnnotationsParameterTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/util/privilegedactions/GetAnnotationsParameterTest.java index 1f679862c4..2e001f6d4e 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/util/privilegedactions/GetAnnotationsParameterTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/util/privilegedactions/GetAnnotationsParameterTest.java @@ -21,7 +21,7 @@ import org.testng.annotations.Test; /** - * Unit test for {@link GetAnnotationsParameter}. + * Unit test for {@link GetAnnotationAttribute}. * * @author Gunnar Morling * From 7e18684fcc372fe62ca2bba8c1fdcfa503b2618b Mon Sep 17 00:00:00 2001 From: gulcher Date: Thu, 3 Jan 2019 16:25:41 +0100 Subject: [PATCH 168/393] HV-1686 Fix a couple of typos in the Dutch translation German 'sein' -> Dutch 'zijn' --- .../org/hibernate/validator/ValidationMessages_nl.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties index 4007586ebb..526f3cfb62 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties @@ -41,5 +41,5 @@ org.hibernate.validator.constraints.ScriptAssert.message = scriptexpr org.hibernate.validator.constraints.UniqueElements.message = mag geen duplicaten bevatten org.hibernate.validator.constraints.URL.message = moet een geldige URL zijn -org.hibernate.validator.constraints.time.DurationMax.message = moet korter${inclusive == true ? ' of gelijk' : ' dan'}${days == 0 ? '' : days == 1 ? ' 1 dag' : ' ' += days += ' dagen'}${hours == 0 ? '' : hours == 1 ? ' 1 uur' : ' ' += hours += ' uren'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minuut' : ' ' += minutes += ' Minuten'}${seconds == 0 ? '' : seconds == 1 ? ' 1 seconde' : ' ' += seconds += ' seconden'}${millis == 0 ? '' : millis == 1 ? ' 1 milliseconde' : ' ' += millis += ' milliseconden'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanoseconde' : ' ' += nanos += ' nanoseconden'} sein -org.hibernate.validator.constraints.time.DurationMin.message = moet langer${inclusive == true ? ' of gelijk' : ' dan'}${days == 0 ? '' : days == 1 ? ' 1 dag' : ' ' += days += ' dagen'}${hours == 0 ? '' : hours == 1 ? ' 1 uur' : ' ' += hours += ' uren'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minuut' : ' ' += minutes += ' minuten'}${seconds == 0 ? '' : seconds == 1 ? ' 1 seconde' : ' ' += seconds += ' seconden'}${millis == 0 ? '' : millis == 1 ? ' 1 milliseconde' : ' ' += millis += ' milliseconden'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanoseconde' : ' ' += nanos += ' nanoseconden'} sein +org.hibernate.validator.constraints.time.DurationMax.message = moet korter${inclusive == true ? ' of gelijk' : ' dan'}${days == 0 ? '' : days == 1 ? ' 1 dag' : ' ' += days += ' dagen'}${hours == 0 ? '' : hours == 1 ? ' 1 uur' : ' ' += hours += ' uren'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minuut' : ' ' += minutes += ' Minuten'}${seconds == 0 ? '' : seconds == 1 ? ' 1 seconde' : ' ' += seconds += ' seconden'}${millis == 0 ? '' : millis == 1 ? ' 1 milliseconde' : ' ' += millis += ' milliseconden'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanoseconde' : ' ' += nanos += ' nanoseconden'} zijn +org.hibernate.validator.constraints.time.DurationMin.message = moet langer${inclusive == true ? ' of gelijk' : ' dan'}${days == 0 ? '' : days == 1 ? ' 1 dag' : ' ' += days += ' dagen'}${hours == 0 ? '' : hours == 1 ? ' 1 uur' : ' ' += hours += ' uren'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minuut' : ' ' += minutes += ' minuten'}${seconds == 0 ? '' : seconds == 1 ? ' 1 seconde' : ' ' += seconds += ' seconden'}${millis == 0 ? '' : millis == 1 ? ' 1 milliseconde' : ' ' += millis += ' milliseconden'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanoseconde' : ' ' += nanos += ' nanoseconden'} zijn From 59372ef6b92138b0c6a347ea16cd655576715252 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 4 Jan 2019 11:52:18 +0100 Subject: [PATCH 169/393] HV-1684 Fix value extraction logic to avoid stack overflows So as Gunnar discovered it, the issue is only triggered with constraints on Maps as otherwise CollectionHelper#toImmutableSet() avoids the issue when there is only one element. Maps have 2 value extractors. --- .../ValueExtractorResolver.java | 73 ++++++++++--------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorResolver.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorResolver.java index afaa2e247a..3b0b931a84 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorResolver.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorResolver.java @@ -303,26 +303,27 @@ private Set getRuntimeCompliantValueExtractors(Class valueExtractorDescriptors = possibleValueExtractorsByRuntimeType.get( runtimeType ); - if ( valueExtractorDescriptors == null ) { - //otherwise we just look for maximally specific extractors for the runtime type - Set possibleValueExtractors = potentialValueExtractorDescriptors - .stream() - .filter( e -> TypeHelper.isAssignable( e.getContainerType(), runtimeType ) ) - .collect( Collectors.toSet() ); - - valueExtractorDescriptors = getMaximallySpecificValueExtractors( possibleValueExtractors ); + + if ( valueExtractorDescriptors != null ) { + return valueExtractorDescriptors; } + Set possibleValueExtractors = potentialValueExtractorDescriptors + .stream() + .filter( e -> TypeHelper.isAssignable( e.getContainerType(), runtimeType ) ) + .collect( Collectors.toSet() ); + + valueExtractorDescriptors = getMaximallySpecificValueExtractors( possibleValueExtractors ); + if ( valueExtractorDescriptors.isEmpty() ) { nonContainerTypes.put( runtimeType, NON_CONTAINER_VALUE ); - } - else { - Set extractorDescriptorsToCache = CollectionHelper.toImmutableSet( valueExtractorDescriptors ); - possibleValueExtractorsByRuntimeType.put( runtimeType, extractorDescriptorsToCache ); - return extractorDescriptorsToCache; + return Collections.emptySet(); } - return valueExtractorDescriptors; + Set valueExtractorDescriptorsToCache = CollectionHelper.toImmutableSet( valueExtractorDescriptors ); + Set cachedValueExtractorDescriptors = possibleValueExtractorsByRuntimeType.putIfAbsent( runtimeType, + valueExtractorDescriptorsToCache ); + return cachedValueExtractorDescriptors != null ? cachedValueExtractorDescriptors : valueExtractorDescriptorsToCache; } private Set getRuntimeAndContainerElementCompliantValueExtractorsFromPossibleCandidates(Type declaredType, @@ -334,32 +335,34 @@ private Set getRuntimeAndContainerElementCompliantValu ValueExtractorCacheKey cacheKey = new ValueExtractorCacheKey( runtimeType, typeParameter ); Set valueExtractorDescriptors = possibleValueExtractorsByRuntimeTypeAndTypeParameter.get( cacheKey ); - if ( valueExtractorDescriptors == null ) { - boolean isInternal = TypeVariables.isInternal( typeParameter ); - Class erasedDeclaredType = TypeHelper.getErasedReferenceType( declaredType ); - Set possibleValueExtractors = valueExtractorCandidates - .stream() - .filter( e -> TypeHelper.isAssignable( e.getContainerType(), runtimeType ) ) - .filter( extractorDescriptor -> - checkValueExtractorTypeCompatibility( - typeParameter, isInternal, erasedDeclaredType, extractorDescriptor - ) - ).collect( Collectors.toSet() ); + if ( valueExtractorDescriptors != null ) { + return valueExtractorDescriptors; + } + + boolean isInternal = TypeVariables.isInternal( typeParameter ); + Class erasedDeclaredType = TypeHelper.getErasedReferenceType( declaredType ); - valueExtractorDescriptors = getMaximallySpecificValueExtractors( possibleValueExtractors ); + Set possibleValueExtractors = valueExtractorCandidates + .stream() + .filter( e -> TypeHelper.isAssignable( e.getContainerType(), runtimeType ) ) + .filter( extractorDescriptor -> + checkValueExtractorTypeCompatibility( + typeParameter, isInternal, erasedDeclaredType, extractorDescriptor + ) + ).collect( Collectors.toSet() ); - if ( valueExtractorDescriptors.isEmpty() ) { - nonContainerTypes.put( runtimeType, NON_CONTAINER_VALUE ); - } - else { - Set extractorDescriptorsToCache = CollectionHelper.toImmutableSet( valueExtractorDescriptors ); - possibleValueExtractorsByRuntimeTypeAndTypeParameter.put( cacheKey, extractorDescriptorsToCache ); - return extractorDescriptorsToCache; - } + valueExtractorDescriptors = getMaximallySpecificValueExtractors( possibleValueExtractors ); + + if ( valueExtractorDescriptors.isEmpty() ) { + nonContainerTypes.put( runtimeType, NON_CONTAINER_VALUE ); + return Collections.emptySet(); } - return valueExtractorDescriptors; + Set valueExtractorDescriptorsToCache = CollectionHelper.toImmutableSet( valueExtractorDescriptors ); + Set cachedValueExtractorDescriptors = possibleValueExtractorsByRuntimeTypeAndTypeParameter.putIfAbsent( cacheKey, + valueExtractorDescriptorsToCache ); + return cachedValueExtractorDescriptors != null ? cachedValueExtractorDescriptors : valueExtractorDescriptorsToCache; } private boolean checkValueExtractorTypeCompatibility(TypeVariable typeParameter, boolean isInternal, Class erasedDeclaredType, From 5d056be276af7a1a7105f9cb7e56e1f475abf031 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 4 Jan 2019 12:41:51 +0100 Subject: [PATCH 170/393] HV-1684 Fix lookup that was testing the value instead of the key We used to have a non concurrent set and switched to a CHM but we were still using contains() which was incorrect. Switching to a Set to avoid this issue and have a clear contract. --- .../engine/valueextraction/ValueExtractorResolver.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorResolver.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorResolver.java index 3b0b931a84..4285b34da2 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorResolver.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorResolver.java @@ -47,8 +47,6 @@ public class ValueExtractorResolver { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - private static final Object NON_CONTAINER_VALUE = new Object(); - @Immutable private final Set registeredValueExtractors; @@ -56,7 +54,7 @@ public class ValueExtractorResolver { private final ConcurrentHashMap, Set> possibleValueExtractorsByRuntimeType = new ConcurrentHashMap<>(); - private final ConcurrentHashMap, Object> nonContainerTypes = new ConcurrentHashMap<>(); + private final Set> nonContainerTypes = Collections.newSetFromMap( new ConcurrentHashMap<>() ); ValueExtractorResolver(Set valueExtractors) { this.registeredValueExtractors = CollectionHelper.toImmutableSet( valueExtractors ); @@ -316,7 +314,7 @@ private Set getRuntimeCompliantValueExtractors(Class getRuntimeAndContainerElementCompliantValu valueExtractorDescriptors = getMaximallySpecificValueExtractors( possibleValueExtractors ); if ( valueExtractorDescriptors.isEmpty() ) { - nonContainerTypes.put( runtimeType, NON_CONTAINER_VALUE ); + nonContainerTypes.add( runtimeType ); return Collections.emptySet(); } From 8e82fda9ac3d683d11c42a65793f753b5fc81450 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 4 Jan 2019 12:46:15 +0100 Subject: [PATCH 171/393] HV-1685 Upgrade the supported WildFly versions to 15.0.0 and 14.0.1 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ce4f1a45e6..17605de5b7 100644 --- a/pom.xml +++ b/pom.xml @@ -125,9 +125,9 @@ 2.1.0.Final - 14.0.1.Final + 15.0.0.Final - 13.0.0.Final + 14.0.1.Final ${version.wildfly} From 4d5e3270727b1734c72a80d55c6be9881757c52c Mon Sep 17 00:00:00 2001 From: sjaakd Date: Sat, 12 Jan 2019 13:53:33 +0100 Subject: [PATCH 172/393] =?UTF-8?q?HV-1657=20Make=20the=20=E2=80=9Cpropert?= =?UTF-8?q?yPath=E2=80=9D=20available=20via=20the=20HibernateMessageInterp?= =?UTF-8?q?olatorContext?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../engine/MessageInterpolatorContext.java | 19 +- .../AbstractValidationContext.java | 3 + .../HibernateMessageInterpolatorContext.java | 8 + ...ssionLanguageMessageInterpolationTest.java | 20 +- .../MessageInterpolatorContextTest.java | 240 ++++++++++++++++-- ...ResourceBundleMessageInterpolatorTest.java | 4 +- 6 files changed, 255 insertions(+), 39 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/MessageInterpolatorContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/MessageInterpolatorContext.java index 2c951be52b..df9f9c4b79 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/MessageInterpolatorContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/MessageInterpolatorContext.java @@ -11,6 +11,7 @@ import java.lang.invoke.MethodHandles; import java.util.Map; +import javax.validation.Path; import javax.validation.metadata.ConstraintDescriptor; import org.hibernate.validator.internal.util.logging.Log; @@ -33,19 +34,22 @@ public class MessageInterpolatorContext implements HibernateMessageInterpolatorC private final ConstraintDescriptor constraintDescriptor; private final Object validatedValue; private final Class rootBeanType; + private final Path propertyPath; @Immutable private final Map messageParameters; @Immutable private final Map expressionVariables; public MessageInterpolatorContext(ConstraintDescriptor constraintDescriptor, - Object validatedValue, - Class rootBeanType, - Map messageParameters, - Map expressionVariables) { + Object validatedValue, + Class rootBeanType, + Path propertyPath, + Map messageParameters, + Map expressionVariables) { this.constraintDescriptor = constraintDescriptor; this.validatedValue = validatedValue; this.rootBeanType = rootBeanType; + this.propertyPath = propertyPath; this.messageParameters = toImmutableMap( messageParameters ); this.expressionVariables = toImmutableMap( expressionVariables ); } @@ -75,6 +79,11 @@ public Map getExpressionVariables() { return expressionVariables; } + @Override + public Path getPropertyPath() { + return propertyPath; + } + @Override public T unwrap(Class type) { //allow unwrapping into public super types @@ -122,6 +131,8 @@ public String toString() { sb.append( "MessageInterpolatorContext" ); sb.append( "{constraintDescriptor=" ).append( constraintDescriptor ); sb.append( ", validatedValue=" ).append( validatedValue ); + sb.append( ", rootBeanType=" ).append( rootBeanType.getName() ); + sb.append( ", propertyPath=" ).append( propertyPath ); sb.append( ", messageParameters=" ).append( messageParameters ); sb.append( ", expressionVariables=" ).append( expressionVariables ); sb.append( '}' ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java index c782d8fca3..7b5a1faf2e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java @@ -228,6 +228,7 @@ public void addConstraintFailure( messageTemplate, valueContext.getCurrentValidatedValue(), descriptor, + constraintViolationCreationContext.getPath(), constraintViolationCreationContext.getMessageParameters(), constraintViolationCreationContext.getExpressionVariables() ); @@ -293,12 +294,14 @@ private String interpolate( String messageTemplate, Object validatedValue, ConstraintDescriptor descriptor, + Path path, Map messageParameters, Map expressionVariables) { MessageInterpolatorContext context = new MessageInterpolatorContext( descriptor, validatedValue, getRootBeanClass(), + path, messageParameters, expressionVariables ); diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/HibernateMessageInterpolatorContext.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/HibernateMessageInterpolatorContext.java index b216ff5161..c1640cc24c 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/HibernateMessageInterpolatorContext.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/HibernateMessageInterpolatorContext.java @@ -9,6 +9,7 @@ import java.util.Map; import javax.validation.MessageInterpolator; +import javax.validation.Path; /** * Extension to {@code MessageInterpolator.Context} which provides functionality @@ -40,4 +41,11 @@ public interface HibernateMessageInterpolatorContext extends MessageInterpolator * @since 5.4.1 */ Map getExpressionVariables(); + + /** + * @return the path to the validated constraint starting from the root bean + * + * @since 6.1 + */ + Path getPropertyPath(); } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java index c869c51c9b..b80ccd14f1 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java @@ -67,9 +67,9 @@ public void testExpressionLanguageGraphNavigation() { notNullDescriptor, user, null, + null, Collections.emptyMap(), - Collections.emptyMap() - ); + Collections.emptyMap() ); String expected = "18"; String actual = interpolatorUnderTest.interpolate( "${validatedValue.age}", context ); @@ -82,9 +82,9 @@ public void testUnknownPropertyInExpressionLanguageGraphNavigation() { notNullDescriptor, new User(), null, + null, Collections.emptyMap(), - Collections.emptyMap() - ); + Collections.emptyMap() ); String expected = "${validatedValue.foo}"; String actual = interpolatorUnderTest.interpolate( "${validatedValue.foo}", context ); @@ -172,9 +172,9 @@ public void testLocaleBasedFormatting() { notNullDescriptor, 42.00000d, null, + null, Collections.emptyMap(), - Collections.emptyMap() - ); + Collections.emptyMap() ); // german locale String expected = "42,00"; @@ -232,9 +232,9 @@ public void testCallingWrongFormatterMethod() { notNullDescriptor, 42.00000d, null, + null, Collections.emptyMap(), - Collections.emptyMap() - ); + Collections.emptyMap() ); String expected = "${formatter.foo('%1$.2f', validatedValue)}"; String actual = interpolatorUnderTest.interpolate( @@ -308,8 +308,8 @@ private MessageInterpolatorContext createMessageInterpolatorContext(ConstraintDe descriptor, null, null, + null, Collections.emptyMap(), - Collections.emptyMap() - ); + Collections.emptyMap() ); } } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/MessageInterpolatorContextTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/MessageInterpolatorContextTest.java index 8635bc1eda..c989b6b3ad 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/MessageInterpolatorContextTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/MessageInterpolatorContextTest.java @@ -7,35 +7,46 @@ package org.hibernate.validator.test.internal.engine.messageinterpolation; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.verify; -import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; -import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; -import static org.testng.Assert.assertSame; -import static org.testng.Assert.assertTrue; - -import java.util.Collections; -import java.util.Set; +import org.hibernate.validator.internal.engine.MessageInterpolatorContext; +import org.hibernate.validator.messageinterpolation.HibernateMessageInterpolatorContext; +import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; +import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; +import org.hibernate.validator.testutil.TestForIssue; +import org.hibernate.validator.testutils.ValidatorUtil; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; import javax.validation.Configuration; import javax.validation.ConstraintViolation; import javax.validation.MessageInterpolator; import javax.validation.MessageInterpolator.Context; +import javax.validation.Path; +import javax.validation.Valid; import javax.validation.ValidationException; import javax.validation.Validator; import javax.validation.constraints.Size; import javax.validation.metadata.BeanDescriptor; import javax.validation.metadata.ConstraintDescriptor; import javax.validation.metadata.PropertyDescriptor; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.ResourceBundle; +import java.util.Set; -import org.hibernate.validator.internal.engine.MessageInterpolatorContext; -import org.hibernate.validator.messageinterpolation.HibernateMessageInterpolatorContext; -import org.hibernate.validator.testutil.TestForIssue; -import org.hibernate.validator.testutils.ValidatorUtil; - -import org.testng.annotations.Test; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; +import static org.hibernate.validator.testutils.ValidatorUtil.getConfiguration; +import static org.testng.Assert.assertSame; +import static org.testng.Assert.assertTrue; /** * @author Hardy Ferentschik @@ -44,6 +55,16 @@ public class MessageInterpolatorContextTest { private static final String MESSAGE = "{foo}"; + Validator validator; + + @BeforeTest + public void setUp() { + validator = getConfiguration() + .messageInterpolator( new PathResourceBundleMessageInterpolator( new TestResourceBundleLocator() ) ) + .buildValidatorFactory() + .getValidator(); + } + @Test @TestForIssue(jiraKey = "HV-333") public void testContextWithRightDescriptorAndValueAndRootBeanClassIsPassedToMessageInterpolator() { @@ -69,9 +90,9 @@ public void testContextWithRightDescriptorAndValueAndRootBeanClassIsPassedToMess constraintDescriptors.iterator().next(), validatedValue, TestBean.class, + null, Collections.emptyMap(), - Collections.emptyMap() - ) + Collections.emptyMap() ) ) ) .andReturn( "invalid" ); @@ -88,13 +109,13 @@ public void testContextWithRightDescriptorAndValueAndRootBeanClassIsPassedToMess @Test(expectedExceptions = ValidationException.class) public void testUnwrapToImplementationCausesValidationException() { - Context context = new MessageInterpolatorContext( null, null, null, Collections.emptyMap(), Collections.emptyMap() ); + Context context = new MessageInterpolatorContext( null, null, null, null, Collections.emptyMap(), Collections.emptyMap() ); context.unwrap( MessageInterpolatorContext.class ); } @Test public void testUnwrapToInterfaceTypesSucceeds() { - Context context = new MessageInterpolatorContext( null, null, null, Collections.emptyMap(), Collections.emptyMap() ); + Context context = new MessageInterpolatorContext( null, null, null, null, Collections.emptyMap(), Collections.emptyMap() ); MessageInterpolator.Context asMessageInterpolatorContext = context.unwrap( MessageInterpolator.Context.class ); assertSame( asMessageInterpolatorContext, context ); @@ -115,13 +136,46 @@ public void testGetRootBeanType() { null, null, rootBeanType, + null, Collections.emptyMap(), - Collections.emptyMap() - ); + Collections.emptyMap() ); assertSame( context.unwrap( HibernateMessageInterpolatorContext.class ).getRootBeanType(), rootBeanType ); } + @Test + @TestForIssue(jiraKey = "HV-1657") + public void testGetPropertyPath() { + Path pathMock = createMock( Path.class ); + MessageInterpolator.Context context = new MessageInterpolatorContext( + null, + null, + null, + pathMock, + Collections.emptyMap(), + Collections.emptyMap() ); + + assertSame( context.unwrap( HibernateMessageInterpolatorContext.class ).getPropertyPath(), pathMock ); + } + + @Test + @TestForIssue(jiraKey = "HV-1657") + public void testUsageOfPathInInterpolation() { + Employee employee = createEmployee( "farTooLongStreet", "workPlaza" ); + Set> constraintViolations = validator.validate( employee ); + assertThat( constraintViolations ).containsOnlyViolations( + violationOf( Size.class ) + .withMessage( "Employee Street should be smaller than 15" ) + ); + + employee = createEmployee( "mySquare", "farTooLongStreet" ); + constraintViolations = validator.validate( employee ); + assertThat( constraintViolations ).containsOnlyViolations( + violationOf( Size.class ) + .withMessage( "Company Street should be smaller than 15" ) + ); + } + private static class TestBean { @Size(min = 10, message = MESSAGE) private final String test; @@ -130,4 +184,144 @@ public TestBean(String test) { this.test = test; } } + + /** + * Interpolator demonstrator for {@link MessageInterpolatorContextTest#testUsageOfPathInInterpolation} + */ + public class PathResourceBundleMessageInterpolator extends ResourceBundleMessageInterpolator { + + public PathResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator) { + super( userResourceBundleLocator ); + } + + @Override + public String interpolate(String message, Context context) { + String newMessage = super.interpolate( message, context ); + newMessage = newMessage.replace( "#path#", "{" + pathToString( context ) + "}" ); + return super.interpolate( newMessage, context ); + } + + private String pathToString(Context context) { + HibernateMessageInterpolatorContext hContext = context.unwrap( HibernateMessageInterpolatorContext.class ); + StringBuilder baseNodeBuilder = new StringBuilder( hContext.getRootBeanType().getSimpleName() ); + for ( Path.Node node : hContext.getPropertyPath() ) { + if ( node.getName() != null ) { + baseNodeBuilder.append( "." ).append( node.getName() ); + } + } + return baseNodeBuilder.toString(); + } + + } + + /** + * creating a test employee with 2 properties of the same type (same annotation). + * + * @param employeeStreet + * @param employerStreet + * @return + */ + public static Employee createEmployee(String employeeStreet, String employerStreet) { + Employee employee = new Employee(); + employee.address = new Address(); + employee.address.street = employeeStreet; + employee.employer = new Employer(); + employee.employer.address = new Address(); + employee.employer.address.street = employerStreet; + return employee; + } + + /** + * Test bean for {@link MessageInterpolatorContextTest#testUsageOfPathInInterpolation} + */ + public static class Address { + + @Size(max = 15) + private String street; + + } + + /** + * Test bean for {@link MessageInterpolatorContextTest#testUsageOfPathInInterpolation} + */ + public static class Employee { + + @Valid + private Address address; + + @Valid + private Employer employer; + } + + /** + * Test bean for {@link MessageInterpolatorContextTest#testUsageOfPathInInterpolation} + */ + public static class Employer { + + @Valid + private Address address; + } + + /** + * A dummy locator for {@link MessageInterpolatorContextTest#testUsageOfPathInInterpolation} + */ + private static class TestResourceBundleLocator implements ResourceBundleLocator { + + private final ResourceBundle resourceBundle; + + public TestResourceBundleLocator() { + this( new TestResourceBundle() ); + } + + public TestResourceBundleLocator(ResourceBundle bundle) { + resourceBundle = bundle; + } + + @Override + public ResourceBundle getResourceBundle(Locale locale) { + return resourceBundle; + } + } + + /** + * A dummy resource bundle for {@link MessageInterpolatorContextTest#testUsageOfPathInInterpolation} + */ + private static class TestResourceBundle extends ResourceBundle implements Enumeration { + private final Map testResources; + Iterator iter; + + public TestResourceBundle() { + testResources = new HashMap(); + // add some test messages + testResources.put( "Employee.address.street", "Employee Street" ); + testResources.put( "Employee.employer.address.street", "Company Street" ); + testResources.put( "javax.validation.constraints.Size.message", "#path# should be smaller than {max}" ); + iter = testResources.keySet().iterator(); + } + + @Override + public Object handleGetObject(String key) { + return testResources.get( key ); + } + + @Override + public Enumeration getKeys() { + return this; + } + + @Override + public boolean hasMoreElements() { + return iter.hasNext(); + } + + @Override + public String nextElement() { + if ( hasMoreElements() ) { + return iter.next(); + } + else { + throw new NoSuchElementException(); + } + } + } } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java index 29bdf5ff3a..5636bafda4 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java @@ -279,9 +279,9 @@ private MessageInterpolatorContext createMessageInterpolatorContext(ConstraintDe descriptor, null, null, + null, Collections.emptyMap(), - Collections.emptyMap() - ); + Collections.emptyMap() ); } private void runInterpolation(boolean cachingEnabled) { From 807a53d9820e81e60dd0e28cec2b3817ec4ff671 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Sun, 17 Feb 2019 17:15:53 +0100 Subject: [PATCH 173/393] HV-1692 Change when beans are marked as processed - in case of redefined group sequences only the last group was marked as processed while all other groups were ignored. Marking bean as processed in the loop allows to catch all the groups in the sequence --- .../internal/engine/ValidatorImpl.java | 6 +- .../sequence/SequenceOnObjectsWithCycles.java | 64 +++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/groups/sequence/SequenceOnObjectsWithCycles.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index cf1b55f726..8628740103 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -452,6 +452,9 @@ private void validateConstraintsForDefaultGroup(BaseBeanValidationContext validationSuccessful = validateConstraintsForSingleDefaultGroupElement( validationContext, valueContext, validatedInterfaces, clazz, metaConstraints, defaultSequenceMember ); } + + validationContext.markCurrentBeanAsProcessed( valueContext ); + if ( !validationSuccessful ) { break; } @@ -463,10 +466,9 @@ private void validateConstraintsForDefaultGroup(BaseBeanValidationContext Set> metaConstraints = hostingBeanMetaData.getDirectMetaConstraints(); validateConstraintsForSingleDefaultGroupElement( validationContext, valueContext, validatedInterfaces, clazz, metaConstraints, Group.DEFAULT_GROUP ); + validationContext.markCurrentBeanAsProcessed( valueContext ); } - validationContext.markCurrentBeanAsProcessed( valueContext ); - // all constraints in the hierarchy has been validated, stop validation. if ( defaultGroupSequenceIsRedefined ) { break; diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/groups/sequence/SequenceOnObjectsWithCycles.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/groups/sequence/SequenceOnObjectsWithCycles.java new file mode 100644 index 0000000000..97e8439ee4 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/groups/sequence/SequenceOnObjectsWithCycles.java @@ -0,0 +1,64 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.engine.groups.sequence; + +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.GroupSequence; +import javax.validation.Valid; +import javax.validation.Validator; + +import org.hibernate.validator.testutil.TestForIssue; +import org.hibernate.validator.testutils.ValidatorUtil; + +import org.testng.Assert; +import org.testng.annotations.Test; + +@TestForIssue(jiraKey = "HV-1692") +public class SequenceOnObjectsWithCycles { + + @Test + public void groupSequenceOfGroupSequences() { + Validator validator = ValidatorUtil.getValidator(); + + YourAnnotatedBean yourEntity1 = new YourAnnotatedBean(); + AnotherBean anotherBean = new AnotherBean(); + anotherBean.setYourAnnotatedBean( yourEntity1 ); + yourEntity1.setBean( anotherBean ); + + Set> constraintViolations = validator.validate( yourEntity1 ); + Assert.assertEquals( 0, constraintViolations.size() ); + + } + + @GroupSequence({ AnotherBean.class, Magic.class }) + public class AnotherBean { + + @Valid + private YourAnnotatedBean yourAnnotatedBean; + + + public void setYourAnnotatedBean(YourAnnotatedBean yourAnnotatedBean) { + this.yourAnnotatedBean = yourAnnotatedBean; + } + } + + @GroupSequence({ YourAnnotatedBean.class, Magic.class }) + public class YourAnnotatedBean { + + @Valid + private AnotherBean bean; + + public void setBean(AnotherBean bean) { + this.bean = bean; + } + } + + public interface Magic { + } +} From 61ba7e8e19a9111262416d98c375f574d0cff8d2 Mon Sep 17 00:00:00 2001 From: asutosh936 Date: Sat, 16 Feb 2019 15:26:57 -0600 Subject: [PATCH 174/393] HV-1689 Log an error when a service cannot be loaded We used to ignore entirely the exception but it can be a legitimate error. Unfortunately, we don't have enough information about why this was ignored in the first place, otherwise we could have tried to use a finer grained approach. --- .../hibernate/validator/internal/util/logging/Log.java | 6 ++++++ .../privilegedactions/GetInstancesFromServiceLoader.java | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index c1043b0cc3..1af9e5347b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -7,6 +7,7 @@ package org.hibernate.validator.internal.util.logging; import static org.jboss.logging.Logger.Level.DEBUG; +import static org.jboss.logging.Logger.Level.ERROR; import static org.jboss.logging.Logger.Level.INFO; import static org.jboss.logging.Logger.Level.WARN; @@ -21,6 +22,7 @@ import java.util.Collection; import java.util.List; import java.util.Locale; +import java.util.ServiceConfigurationError; import java.util.Set; import java.util.regex.PatternSyntaxException; @@ -881,4 +883,8 @@ ConstraintDefinitionException getConstraintValidatorDefinitionConstraintMismatch @Message(id = 250, value = "Uninitialized locale: %s. Please register your locale as a locale to initialize when initializing your ValidatorFactory.") ValidationException uninitializedLocale(Locale locale); + + @LogMessage(level = ERROR) + @Message(id = 251, value = "An error occurred while loading an instance of service %s.") + void unableToLoadInstanceOfService(String serviceName, @Cause ServiceConfigurationError e); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetInstancesFromServiceLoader.java b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetInstancesFromServiceLoader.java index 3a61292f4b..c0f7a509ce 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetInstancesFromServiceLoader.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetInstancesFromServiceLoader.java @@ -6,6 +6,10 @@ */ package org.hibernate.validator.internal.util.privilegedactions; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; + +import java.lang.invoke.MethodHandles; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Iterator; @@ -22,6 +26,8 @@ public class GetInstancesFromServiceLoader implements PrivilegedAction clazz; + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + private GetInstancesFromServiceLoader(ClassLoader primaryClassLoader, Class clazz) { this.primaryClassLoader = primaryClassLoader; this.clazz = clazz; @@ -57,6 +63,8 @@ private List loadInstances(ClassLoader classloader) { // ignore, because it can happen when multiple // services are present and some of them are not class loader // compatible with our API. + // log an error still as it can hide a legitimate issue (see HV-1689) + LOG.unableToLoadInstanceOfService( loader.getClass().getName(), e ); } } return instances; From 609157a037a941211e4f471efb653f39490a357d Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Sun, 17 Feb 2019 21:13:05 +0100 Subject: [PATCH 175/393] Update copyright.txt --- copyright.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/copyright.txt b/copyright.txt index afa62094ab..b6afa3d003 100644 --- a/copyright.txt +++ b/copyright.txt @@ -3,6 +3,7 @@ Ahmed Al Hafoudh Alaa Nassef Andrey Derevyanko Andrey Rodionov +Asutosh Pandya Benson Margulies Brent Douglas Carlos Vara @@ -57,6 +58,7 @@ Sebastian Bayerl Shahram Goodarzi Shane Bryzak Shelly McGowan +Sjaak Derksen Steve Ebersole Strong Liu Tadhg Pearson From 84fd7327010b5652c41482dca65539f98cc42220 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Sat, 5 Jan 2019 12:31:30 +0100 Subject: [PATCH 176/393] HV-1687 Reduce bootstrap log verbosity --- .../validator/internal/util/logging/Log.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 1af9e5347b..4107e2502b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -91,27 +91,27 @@ public interface Log extends BasicLogger { @Message(id = 1, value = "Hibernate Validator %s") void version(String version); - @LogMessage(level = INFO) + @LogMessage(level = DEBUG) @Message(id = 2, value = "Ignoring XML configuration.") void ignoringXmlConfiguration(); - @LogMessage(level = INFO) + @LogMessage(level = DEBUG) @Message(id = 3, value = "Using %s as constraint validator factory.") void usingConstraintValidatorFactory(@FormatWith(ClassObjectFormatter.class) Class constraintValidatorFactoryClass); - @LogMessage(level = INFO) + @LogMessage(level = DEBUG) @Message(id = 4, value = "Using %s as message interpolator.") void usingMessageInterpolator(@FormatWith(ClassObjectFormatter.class) Class messageInterpolatorClass); - @LogMessage(level = INFO) + @LogMessage(level = DEBUG) @Message(id = 5, value = "Using %s as traversable resolver.") void usingTraversableResolver(@FormatWith(ClassObjectFormatter.class) Class traversableResolverClass); - @LogMessage(level = INFO) + @LogMessage(level = DEBUG) @Message(id = 6, value = "Using %s as validation provider.") void usingValidationProvider(@FormatWith(ClassObjectFormatter.class) Class> validationProviderClass); - @LogMessage(level = INFO) + @LogMessage(level = DEBUG) @Message(id = 7, value = "%s found. Parsing XML based configuration.") void parsingXMLFile(String fileName); @@ -434,7 +434,7 @@ ValidationException getAnnotationDoesNotContainAParameterException(@FormatWith(C ClassCastException getUnableToNarrowNodeTypeException(@FormatWith(ClassObjectFormatter.class) Class actualDescriptorType, ElementKind kind, @FormatWith(ClassObjectFormatter.class) Class expectedDescriptorType); - @LogMessage(level = INFO) + @LogMessage(level = DEBUG) @Message(id = 119, value = "Using %s as parameter name provider.") void usingParameterNameProvider(@FormatWith(ClassObjectFormatter.class) Class parameterNameProviderClass); @@ -703,7 +703,7 @@ ConstraintDeclarationException getInconsistentValueUnwrappingConfigurationBetwee @Message(id = 198, value = "No suitable value extractor found for type %1$s.") ConstraintDeclarationException getNoValueExtractorFoundForUnwrapException(Type type); - @LogMessage(level = INFO) + @LogMessage(level = DEBUG) @Message(id = 200, value = "Using %s as clock provider.") void usingClockProvider(@FormatWith(ClassObjectFormatter.class) Class clockProviderClass); @@ -725,7 +725,7 @@ ConstraintDeclarationException getInconsistentValueUnwrappingConfigurationBetwee @Message(id = 206, value = "Unable to instantiate value extractor class %s.") ValidationException getUnableToInstantiateValueExtractorClassException(String valueExtractorClassName, @Cause ValidationException e); - @LogMessage(level = INFO) + @LogMessage(level = DEBUG) @Message(id = 207, value = "Adding value extractor %s.") void addingValueExtractor(@FormatWith(ClassObjectFormatter.class) Class> valueExtractorClass); @@ -811,7 +811,7 @@ ConstraintDeclarationException getNoValueExtractorFoundForTypeException(@FormatW @Message(id = 229, value = "Unable to cast %1$s to %2$s.") ClassCastException getUnableToCastException(Object object, @FormatWith(ClassObjectFormatter.class) Class clazz); - @LogMessage(level = INFO) + @LogMessage(level = DEBUG) @Message(id = 230, value = "Using %s as script evaluator factory.") void usingScriptEvaluatorFactory(@FormatWith(ClassObjectFormatter.class) Class scriptEvaluatorFactoryClass); @@ -838,7 +838,7 @@ ConstraintDeclarationException getNoValueExtractorFoundForTypeException(@FormatW ValidationException getUnableToAccessMethodException(Lookup lookup, @FormatWith(ClassObjectFormatter.class) Class clazz, String methodName, @FormatWith(ObjectArrayFormatter.class) Object[] parameterTypes, @Cause Throwable e); - @LogMessage(level = INFO) + @LogMessage(level = DEBUG) @Message(id = 238, value = "Temporal validation tolerance set to %1$s.") void logTemporalValidationTolerance(@FormatWith(DurationFormatter.class) Duration tolerance); @@ -868,7 +868,7 @@ ConstraintDefinitionException getConstraintValidatorDefinitionConstraintMismatch @Message(id = 245, value = "Allowed constraint element types are FIELD and GETTER, but instead received %1$s.") AssertionError getUnsupportedConstraintElementType(ConstrainedElement.ConstrainedElementKind kind); - @LogMessage(level = INFO) + @LogMessage(level = DEBUG) @Message(id = 246, value = "Using %s as getter property selection strategy.") void usingGetterPropertySelectionStrategy(@FormatWith(ClassObjectFormatter.class) Class getterPropertySelectionStrategyClass); From 571ab96b9ea2b32c2597f0765f59da28f5c029d9 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Sun, 17 Feb 2019 21:20:52 +0100 Subject: [PATCH 177/393] HV-1691 Rename PathImpl#getPathWithoutLeafNode to createCopyWithoutLeafNode And make it static to be more consistent with createCopy(). --- .../validator/internal/engine/ValidatorImpl.java | 4 ++-- .../ConstraintValidatorContextImpl.java | 2 +- .../CrossParameterConstraintValidatorContextImpl.java | 2 +- .../validator/internal/engine/path/PathImpl.java | 9 +++++---- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index 8628740103..39b366ea65 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -1277,7 +1277,7 @@ private boolean isReachable(BaseBeanValidationContext validationContext, Obje return true; } - Path pathToObject = path.getPathWithoutLeafNode(); + Path pathToObject = PathImpl.createCopyWithoutLeafNode( path ); try { return validationContext.getTraversableResolver().isReachable( traversableObject, @@ -1314,7 +1314,7 @@ private boolean isCascadeRequired(BaseBeanValidationContext validationContext return false; } - Path pathToObject = path.getPathWithoutLeafNode(); + Path pathToObject = PathImpl.createCopyWithoutLeafNode( path ); try { return validationContext.getTraversableResolver().isCascadable( traversableObject, diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java index e9d51baaf7..8af5369371 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java @@ -247,7 +247,7 @@ public ContainerElementNodeBuilderCustomizableContext addContainerElementNode(St */ private void dropLeafNodeIfRequired() { if ( propertyPath.getLeafNode().getKind() == ElementKind.BEAN ) { - propertyPath = propertyPath.getPathWithoutLeafNode(); + propertyPath = PathImpl.createCopyWithoutLeafNode( propertyPath ); } } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/CrossParameterConstraintValidatorContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/CrossParameterConstraintValidatorContextImpl.java index fe84ec24b2..2ac491a84d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/CrossParameterConstraintValidatorContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/CrossParameterConstraintValidatorContextImpl.java @@ -70,7 +70,7 @@ public NodeBuilderDefinedContext addParameterNode(int index) { } private void dropLeafNode() { - propertyPath = propertyPath.getPathWithoutLeafNode(); + propertyPath = PathImpl.createCopyWithoutLeafNode( propertyPath ); } } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/path/PathImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/path/PathImpl.java index 0a7bd6bb8c..d83a9e8f7e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/path/PathImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/path/PathImpl.java @@ -105,12 +105,13 @@ public static PathImpl createCopy(PathImpl path) { return new PathImpl( path ); } - public boolean isRootPath() { - return nodeList.size() == 1 && nodeList.get( 0 ).getName() == null; + public static PathImpl createCopyWithoutLeafNode(PathImpl path) { + return new PathImpl( path.nodeList.subList( 0, path.nodeList.size() - 1 ) ); } - public PathImpl getPathWithoutLeafNode() { - return new PathImpl( nodeList.subList( 0, nodeList.size() - 1 ) ); + + public boolean isRootPath() { + return nodeList.size() == 1 && nodeList.get( 0 ).getName() == null; } public NodeImpl addPropertyNode(String nodeName) { From 37cc66409ac9349c087d90749455744c913b25af Mon Sep 17 00:00:00 2001 From: Jenkins Date: Mon, 18 Feb 2019 11:25:47 +0000 Subject: [PATCH 178/393] [Jenkins release job] README.md updated by release build 6.1.0.Alpha3 --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0f018cf434..f98e0fc64b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hibernate Validator -*Version: 6.1.0.Alpha2 - 19-12-2018* +*Version: 6.1.0.Alpha3 - 18-02-2019* ## What is it? @@ -35,7 +35,7 @@ Logging will delegate any log requests to that provider. org.hibernate.validator hibernate-validator - 6.1.0.Alpha2 + 6.1.0.Alpha3 You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. @@ -54,7 +54,7 @@ extension by adding the following dependency: org.hibernate.validator hibernate-validator-cdi - 6.1.0.Alpha2 + 6.1.0.Alpha3 * _hibernate-validator-annotation-processor-<version>.jar_ is an optional jar which can be integrated with your build From 6ec95c6f198fea187e058739487a4d2168450736 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Mon, 18 Feb 2019 11:25:48 +0000 Subject: [PATCH 179/393] [Jenkins release job] changelog.txt updated by release build 6.1.0.Alpha3 --- changelog.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/changelog.txt b/changelog.txt index 8ad3b75d7d..08c8188939 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,26 @@ Hibernate Validator Changelog ============================= +6.1.0.Alpha3 (18-02-2019) +------------------------- + +** Bug + * HV-1692 - engine - Custom group sequence might cause StackOverflowError on objects with cycles + * HV-1684 - validators - StackOverflowError with Hibernate Validator 6.0.13.Final + +** Improvement + * HV-1691 - engine - IndexOutOfBoundsException in PathImpl + * HV-1689 - engine - In GetInstancesFromServiceLoader, do not hide ServiceConfigurationError + * HV-1687 - engine - Reduce bootstrap log verbosity + * HV-1686 - translations - Fix a few typos in the Dutch translation + * HV-1683 - build - Upgrade javadoc plugin + +** New Feature + * HV-1657 - engine - Make the “propertyPath†available via the “HibernateMessageInterpolatorContext†+ +** Task + * HV-1685 - integration - Upgrade the WildFly versions we generate patches for to 14.0.1.Final and 15.0.0.Final + 6.1.0.Alpha2 (19-12-2018) ------------------------- From 764ae927404dfa494247c25eb94b1d1735011d00 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Mon, 18 Feb 2019 11:25:53 +0000 Subject: [PATCH 180/393] [Jenkins release job] Preparing release 6.1.0.Alpha3 --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 6b70540803..161d988038 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 021058c8f5..2a5e71d5cd 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index 64d7dc2320..50f48ca58e 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index a60c2e907e..5c2515625d 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 76e5181564..039bbdd21f 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index 5fd0209f0b..ecdde96cb9 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 7e78f49241..551b4eb605 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index b9eacc9ca4..e9aed1cadd 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 55c15d1c8c..ff3ea9e0ec 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 28ce4576ea..1d96ee677e 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 1b9ec9f304..becdfe859a 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index fc4f7e3a85..afc92a3395 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index 09262ee135..29b7003501 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 ../pom.xml diff --git a/pom.xml b/pom.xml index 17605de5b7..0def58dac4 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 3f99228d35..58359e6a67 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index acc9a54560..e8372534c8 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index d793ee6b6e..ff2bce4be7 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index c2eba20d47..7948ec8f33 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 6516654b3f..04d596e731 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 4b01b88584..82f6eae120 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 3b0766e5c7..6d6f5712a5 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha3 hibernate-validator-test-utils From 1d857d4b4d7d5c5b210caad4d2140908ccc4cdcd Mon Sep 17 00:00:00 2001 From: Jenkins Date: Mon, 18 Feb 2019 11:28:51 +0000 Subject: [PATCH 181/393] [Jenkins release job] Preparing next development iteration --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 161d988038..6b70540803 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 2a5e71d5cd..021058c8f5 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index 50f48ca58e..64d7dc2320 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index 5c2515625d..a60c2e907e 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 039bbdd21f..76e5181564 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index ecdde96cb9..5fd0209f0b 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 551b4eb605..7e78f49241 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index e9aed1cadd..b9eacc9ca4 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index ff3ea9e0ec..55c15d1c8c 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 1d96ee677e..28ce4576ea 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index becdfe859a..1b9ec9f304 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index afc92a3395..fc4f7e3a85 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index 29b7003501..09262ee135 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 0def58dac4..17605de5b7 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 58359e6a67..3f99228d35 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index e8372534c8..acc9a54560 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index ff2bce4be7..d793ee6b6e 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index 7948ec8f33..c2eba20d47 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 04d596e731..6516654b3f 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 82f6eae120..4b01b88584 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 6d6f5712a5..3b0766e5c7 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha3 + 6.1.0-SNAPSHOT hibernate-validator-test-utils From d59d2e7fe56edf33a755f65552a9f148a9342c62 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 18 Feb 2019 19:37:02 +0100 Subject: [PATCH 182/393] HV-1693 Ensure compatibility with JDK 12 It's not perfect at all and I had to disable a few modules but that's the best we can do for now. --- distribution/pom.xml | 9 +++++++++ pom.xml | 15 +++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/distribution/pom.xml b/distribution/pom.xml index a60c2e907e..480f2c2cb6 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -210,6 +210,15 @@ -html5 + + jdk12+ + + [12,) + + + -html5 -source 8 + + jdk11+ diff --git a/pom.xml b/pom.xml index 17605de5b7..d1ae04061e 100644 --- a/pom.xml +++ b/pom.xml @@ -86,12 +86,10 @@ test-utils build-config engine - cdi modules tck-runner annotation-processor performance - integration @@ -1212,6 +1210,7 @@ + jdk10- @@ -1221,6 +1220,18 @@ osgi + + + jdk11- + + (,12) + + + + cdi + integration + + jdk11+ From 3c5248c45e2f884cbeb8dbd1bcab1b77a59ff267 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 18 Feb 2019 19:37:42 +0100 Subject: [PATCH 183/393] HV-1693 Simplify failsafe configuration of the WildFly integration tests --- integration/pom.xml | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/integration/pom.xml b/integration/pom.xml index 7e78f49241..85364bd54c 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -157,6 +157,7 @@ wildfly-current-integration-test integration-test + verify @@ -165,17 +166,6 @@ target/failsafe-reports/failsafe-summary-wildfly-current.xml - - verify - - verify - - - - target/failsafe-reports/failsafe-summary-wildfly-current.xml - - - @@ -321,6 +311,7 @@ wildfly-secondary-integration-test integration-test + verify @@ -329,18 +320,6 @@ target/failsafe-reports/failsafe-summary-wildfly-secondary.xml - - verify - - verify - - - - target/failsafe-reports/failsafe-summary-wildfly-current.xml - target/failsafe-reports/failsafe-summary-wildfly-secondary.xml - - - From 3f7b519cf96984ec77ecb1c7af1d0f4e43749bd3 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 21 Feb 2019 12:03:28 +0100 Subject: [PATCH 184/393] HV-1694 Add a benchmarck for unconstrained beans and update benchmarks --- performance/README.md | 6 +- performance/pom.xml | 4 +- .../SimpleComposingConstraintValidation.java | 0 .../UnconstrainedBeanValidation.java | 122 ++++++++++++++++++ 4 files changed, 127 insertions(+), 5 deletions(-) rename performance/src/main/{java => java-bv2}/org/hibernate/validator/performance/simple/SimpleComposingConstraintValidation.java (100%) create mode 100644 performance/src/main/java/org/hibernate/validator/performance/unconstrained/UnconstrainedBeanValidation.java diff --git a/performance/README.md b/performance/README.md index 27fbf0b9ca..01e63dc38b 100644 --- a/performance/README.md +++ b/performance/README.md @@ -11,9 +11,9 @@ To allow performance testing of different Hibernate Validator versions there are Choosing a profile executes the tests against the specified Hibernate Validator or BVal version, respectively. The defined profiles are: -* hv-current (Hibernate Validator 6.0.0-SNAPSHOT) -* hv-6.0 (Hibernate Validator 6.0.5.Final) -* hv-5.4 (Hibernate Validator 5.4.1.Final) +* hv-current (Hibernate Validator 6.1.0-SNAPSHOT) +* hv-6.0 (Hibernate Validator 6.0.15.Final) +* hv-5.4 (Hibernate Validator 5.4.3.Final) * hv-5.3 (Hibernate Validator 5.3.4.Final) * hv-5.2 (Hibernate Validator 5.2.4.Final) * hv-5.1 (Hibernate Validator 5.1.3.Final) diff --git a/performance/pom.xml b/performance/pom.xml index 09262ee135..7c11eca2fd 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -203,7 +203,7 @@ Hibernate Validator - 6.0.10.Final + 6.0.15.Final @@ -245,7 +245,7 @@ 1.1.0.Final Hibernate Validator - 5.4.2.Final + 5.4.3.Final diff --git a/performance/src/main/java/org/hibernate/validator/performance/simple/SimpleComposingConstraintValidation.java b/performance/src/main/java-bv2/org/hibernate/validator/performance/simple/SimpleComposingConstraintValidation.java similarity index 100% rename from performance/src/main/java/org/hibernate/validator/performance/simple/SimpleComposingConstraintValidation.java rename to performance/src/main/java-bv2/org/hibernate/validator/performance/simple/SimpleComposingConstraintValidation.java diff --git a/performance/src/main/java/org/hibernate/validator/performance/unconstrained/UnconstrainedBeanValidation.java b/performance/src/main/java/org/hibernate/validator/performance/unconstrained/UnconstrainedBeanValidation.java new file mode 100644 index 0000000000..25c3b20636 --- /dev/null +++ b/performance/src/main/java/org/hibernate/validator/performance/unconstrained/UnconstrainedBeanValidation.java @@ -0,0 +1,122 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.performance.unconstrained; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Random; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Threads; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +/** + * @author Guillaume Smet + */ +public class UnconstrainedBeanValidation { + + private static final String[] names = { + null, + "Jacob", + "Isabella", + "Ethan", + "Sophia", + "Michael", + "Emma", + "Jayden", + "Olivia", + "William" + }; + + @State(Scope.Benchmark) + public static class ValidationState { + public volatile Validator validator; + public volatile Random random; + + { + ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + validator = factory.getValidator(); + random = new Random(); + } + + } + + @Benchmark + @BenchmarkMode(Mode.Throughput) + @OutputTimeUnit(TimeUnit.MILLISECONDS) + @Fork(value = 1) + @Threads(50) + @Warmup(iterations = 10) + @Measurement(iterations = 20) + public void testUnconstrainedBeanValidation(ValidationState state, Blackhole bh) { + DriverSetup driverSetup = new DriverSetup( state ); + Set> violations = state.validator.validate( driverSetup.getDriver() ); + assertThat( violations ).hasSize( 0 ); + bh.consume( violations ); + } + + public class Driver { + + private String name; + + private int age; + + private boolean hasDrivingLicense; + + public Driver(String name, int age, boolean hasDrivingLicense) { + this.name = name; + this.age = age; + this.hasDrivingLicense = hasDrivingLicense; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append( "Driver" ); + sb.append( "{name='" ).append( name ).append( '\'' ); + sb.append( ", age=" ).append( age ); + sb.append( ", hasDrivingLicense=" ).append( hasDrivingLicense ); + sb.append( '}' ); + return sb.toString(); + } + } + + private class DriverSetup { + + private Driver driver; + + public DriverSetup(ValidationState state) { + String name = names[state.random.nextInt( 10 )]; + + int randomAge = state.random.nextInt( 100 ); + + int rand = state.random.nextInt( 2 ); + boolean hasLicense = rand == 1; + + driver = new Driver( name, randomAge, hasLicense ); + } + + public Driver getDriver() { + return driver; + } + } +} From 3c165a801b9362bb9a9d17b18102cdb8d2a0d2cd Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 21 Feb 2019 13:05:56 +0100 Subject: [PATCH 185/393] HV-1694 Reduce the memory allocations of the benchmarks It generates too much noise, in particular when testing unconstrained beans. --- .../performance/simple/SimpleValidation.java | 44 ++++++++++++------- .../UnconstrainedBeanValidation.java | 27 +++++++----- 2 files changed, 43 insertions(+), 28 deletions(-) diff --git a/performance/src/main/java/org/hibernate/validator/performance/simple/SimpleValidation.java b/performance/src/main/java/org/hibernate/validator/performance/simple/SimpleValidation.java index 98671afb86..ebdc9e4940 100644 --- a/performance/src/main/java/org/hibernate/validator/performance/simple/SimpleValidation.java +++ b/performance/src/main/java/org/hibernate/validator/performance/simple/SimpleValidation.java @@ -6,8 +6,6 @@ */ package org.hibernate.validator.performance.simple; -import static org.assertj.core.api.Assertions.assertThat; - import java.util.Random; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -54,13 +52,22 @@ public class SimpleValidation { public static class ValidationState { public volatile Validator validator; public volatile Random random; + public volatile Driver[] drivers; { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator(); random = new Random(); + + drivers = new Driver[100]; + for ( int i = 0; i < 100; i++ ) { + drivers[i] = new DriverSetup( random ).getDriver(); + } } + public Driver nextDriver() { + return drivers[random.nextInt( 100 )]; + } } @Benchmark @@ -71,13 +78,13 @@ public static class ValidationState { @Warmup(iterations = 10) @Measurement(iterations = 20) public void testSimpleBeanValidation(ValidationState state, Blackhole bh) { - DriverSetup driverSetup = new DriverSetup( state ); - Set> violations = state.validator.validate( driverSetup.getDriver() ); - assertThat( violations ).hasSize( driverSetup.getExpectedViolationCount() ); + Driver driver = state.nextDriver(); + Set> violations = state.validator.validate( driver ); + assert driver.getExpectedViolationCount() == violations.size(); bh.consume( violations ); } - public class Driver { + public static class Driver { @NotNull private String name; @@ -87,10 +94,17 @@ public class Driver { @AssertTrue private boolean hasDrivingLicense; - public Driver(String name, int age, boolean hasDrivingLicense) { + private int expectedViolationCount; + + public Driver(String name, int age, boolean hasDrivingLicense, int expectedViolationCount) { this.name = name; this.age = age; this.hasDrivingLicense = hasDrivingLicense; + this.expectedViolationCount = expectedViolationCount; + } + + public int getExpectedViolationCount() { + return expectedViolationCount; } @Override @@ -105,34 +119,30 @@ public String toString() { } } - private class DriverSetup { + private static class DriverSetup { private int expectedViolationCount; private Driver driver; - public DriverSetup(ValidationState state) { + public DriverSetup(Random random) { expectedViolationCount = 0; - String name = names[state.random.nextInt( 10 )]; + String name = names[random.nextInt( 10 )]; if ( name == null ) { expectedViolationCount++; } - int randomAge = state.random.nextInt( 100 ); + int randomAge = random.nextInt( 100 ); if ( randomAge < 18 ) { expectedViolationCount++; } - int rand = state.random.nextInt( 2 ); + int rand = random.nextInt( 2 ); boolean hasLicense = rand == 1; if ( !hasLicense ) { expectedViolationCount++; } - driver = new Driver( name, randomAge, hasLicense ); - } - - public int getExpectedViolationCount() { - return expectedViolationCount; + driver = new Driver( name, randomAge, hasLicense, expectedViolationCount ); } public Driver getDriver() { diff --git a/performance/src/main/java/org/hibernate/validator/performance/unconstrained/UnconstrainedBeanValidation.java b/performance/src/main/java/org/hibernate/validator/performance/unconstrained/UnconstrainedBeanValidation.java index 25c3b20636..d6a315abf5 100644 --- a/performance/src/main/java/org/hibernate/validator/performance/unconstrained/UnconstrainedBeanValidation.java +++ b/performance/src/main/java/org/hibernate/validator/performance/unconstrained/UnconstrainedBeanValidation.java @@ -6,8 +6,6 @@ */ package org.hibernate.validator.performance.unconstrained; -import static org.assertj.core.api.Assertions.assertThat; - import java.util.Random; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -51,13 +49,22 @@ public class UnconstrainedBeanValidation { public static class ValidationState { public volatile Validator validator; public volatile Random random; + private volatile Driver[] drivers; { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator(); random = new Random(); + + drivers = new Driver[100]; + for ( int i = 0; i < 100; i++ ) { + drivers[i] = new DriverSetup( random ).getDriver(); + } } + public Driver nextDriver() { + return drivers[random.nextInt( 100 )]; + } } @Benchmark @@ -68,13 +75,11 @@ public static class ValidationState { @Warmup(iterations = 10) @Measurement(iterations = 20) public void testUnconstrainedBeanValidation(ValidationState state, Blackhole bh) { - DriverSetup driverSetup = new DriverSetup( state ); - Set> violations = state.validator.validate( driverSetup.getDriver() ); - assertThat( violations ).hasSize( 0 ); + Set> violations = state.validator.validate( state.nextDriver() ); bh.consume( violations ); } - public class Driver { + public static class Driver { private String name; @@ -100,16 +105,16 @@ public String toString() { } } - private class DriverSetup { + private static class DriverSetup { private Driver driver; - public DriverSetup(ValidationState state) { - String name = names[state.random.nextInt( 10 )]; + public DriverSetup(Random random) { + String name = names[random.nextInt( 10 )]; - int randomAge = state.random.nextInt( 100 ); + int randomAge = random.nextInt( 100 ); - int rand = state.random.nextInt( 2 ); + int rand = random.nextInt( 2 ); boolean hasLicense = rand == 1; driver = new Driver( name, randomAge, hasLicense ); From c7f372cef06ce7cae2f3c7a3e359cc961c8001f1 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 21 Feb 2019 15:57:48 +0100 Subject: [PATCH 186/393] HV-1694 Add a benchmark entry for 6.1 This way we can compare current to latest released 6.1 --- performance/pom.xml | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/performance/pom.xml b/performance/pom.xml index 7c11eca2fd..272ffbee1b 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -193,6 +193,47 @@ + + hv-6.1 + + + validator + hv-6.1 + + + + Hibernate Validator + 6.1.0.Alpha3 + + + + javax.validation + validation-api + + + ${project.groupId} + hibernate-validator + ${beanvalidation-impl.version} + + + org.glassfish + javax.el + + + log4j + log4j + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + + hv-6.0 From 9464463fea15c247e7e3c072fe430fe497bc9b95 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 21 Feb 2019 12:03:54 +0100 Subject: [PATCH 187/393] HV-1694 Reduce memory allocation for unconstrained beans --- .../internal/engine/ValidatorImpl.java | 44 +++++++++++++++---- .../ValidationContextBuilder.java | 32 +++----------- 2 files changed, 42 insertions(+), 34 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index 39b366ea65..db0d980f4d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -151,7 +151,15 @@ public final Set> validate(T object, Class... grou Contracts.assertNotNull( object, MESSAGES.validatedObjectMustNotBeNull() ); sanityCheckGroups( groups ); - BaseBeanValidationContext validationContext = getValidationContextBuilder().forValidate( object ); + @SuppressWarnings("unchecked") + Class rootBeanClass = (Class) object.getClass(); + BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); + + if ( !rootBeanMetaData.hasConstraints() ) { + return Collections.emptySet(); + } + + BaseBeanValidationContext validationContext = getValidationContextBuilder().forValidate( rootBeanClass, rootBeanMetaData, object ); if ( !validationContext.getRootBeanMetaData().hasConstraints() ) { return Collections.emptySet(); @@ -174,13 +182,18 @@ public final Set> validateProperty(T object, String p sanityCheckPropertyPath( propertyName ); sanityCheckGroups( groups ); - PathImpl propertyPath = PathImpl.createPathFromString( propertyName ); - BaseBeanValidationContext validationContext = getValidationContextBuilder().forValidateProperty( object, propertyPath ); + @SuppressWarnings("unchecked") + Class rootBeanClass = (Class) object.getClass(); + BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); - if ( !validationContext.getRootBeanMetaData().hasConstraints() ) { + if ( !rootBeanMetaData.hasConstraints() ) { return Collections.emptySet(); } + PathImpl propertyPath = PathImpl.createPathFromString( propertyName ); + BaseBeanValidationContext validationContext = getValidationContextBuilder().forValidateProperty( rootBeanClass, rootBeanMetaData, object, + propertyPath ); + BeanValueContext valueContext = getValueContextForPropertyValidation( validationContext, propertyPath ); if ( valueContext.getCurrentBean() == null ) { @@ -198,13 +211,15 @@ public final Set> validateValue(Class beanType, St sanityCheckPropertyPath( propertyName ); sanityCheckGroups( groups ); - PathImpl propertyPath = PathImpl.createPathFromString( propertyName ); - BaseBeanValidationContext validationContext = getValidationContextBuilder().forValidateValue( beanType, propertyPath ); + BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( beanType ); - if ( !validationContext.getRootBeanMetaData().hasConstraints() ) { + if ( !rootBeanMetaData.hasConstraints() ) { return Collections.emptySet(); } + PathImpl propertyPath = PathImpl.createPathFromString( propertyName ); + BaseBeanValidationContext validationContext = getValidationContextBuilder().forValidateValue( beanType, rootBeanMetaData, propertyPath ); + ValidationOrder validationOrder = determineGroupValidationOrder( groups ); return validateValueInContext( @@ -251,7 +266,13 @@ public Set> validateReturnValue(T object, Method meth private Set> validateParameters(T object, Executable executable, Object[] parameterValues, Class... groups) { sanityCheckGroups( groups ); + @SuppressWarnings("unchecked") + Class rootBeanClass = object != null ? (Class) object.getClass() : (Class) executable.getDeclaringClass(); + BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); + ExecutableValidationContext validationContext = getValidationContextBuilder().forValidateParameters( + rootBeanClass, + rootBeanMetaData, object, executable, parameterValues @@ -271,7 +292,14 @@ private Set> validateParameters(T object, Executable private Set> validateReturnValue(T object, Executable executable, Object returnValue, Class... groups) { sanityCheckGroups( groups ); + @SuppressWarnings("unchecked") + Class rootBeanClass = object != null ? (Class) object.getClass() : (Class) executable.getDeclaringClass(); + BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); + + ExecutableValidationContext validationContext = getValidationContextBuilder().forValidateReturnValue( + rootBeanClass, + rootBeanMetaData, object, executable, returnValue @@ -312,13 +340,11 @@ public ExecutableValidator forExecutables() { private ValidationContextBuilder getValidationContextBuilder() { return new ValidationContextBuilder( - beanMetaDataManager, constraintValidatorManager, constraintValidatorFactory, validatorScopedContext, TraversableResolvers.wrapWithCachingForSingleValidation( traversableResolver, validatorScopedContext.isTraversableResolverResultCacheEnabled() ), constraintValidatorInitializationContext - ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java index 0d54a34358..1d1d388d30 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidationContextBuilder.java @@ -14,7 +14,6 @@ import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorInitializationContext; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; import org.hibernate.validator.internal.engine.path.PathImpl; -import org.hibernate.validator.internal.metadata.BeanMetaDataManager; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; /** @@ -25,7 +24,6 @@ */ public class ValidationContextBuilder { - private final BeanMetaDataManager beanMetaDataManager; private final ConstraintValidatorManager constraintValidatorManager; private final ConstraintValidatorFactory constraintValidatorFactory; private final TraversableResolver traversableResolver; @@ -33,13 +31,11 @@ public class ValidationContextBuilder { private final ValidatorScopedContext validatorScopedContext; public ValidationContextBuilder( - BeanMetaDataManager beanMetaDataManager, ConstraintValidatorManager constraintValidatorManager, ConstraintValidatorFactory constraintValidatorFactory, ValidatorScopedContext validatorScopedContext, TraversableResolver traversableResolver, HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext) { - this.beanMetaDataManager = beanMetaDataManager; this.constraintValidatorManager = constraintValidatorManager; this.constraintValidatorFactory = constraintValidatorFactory; this.traversableResolver = traversableResolver; @@ -47,11 +43,7 @@ public ValidationContextBuilder( this.validatorScopedContext = validatorScopedContext; } - public BaseBeanValidationContext forValidate(T rootBean) { - @SuppressWarnings("unchecked") - Class rootBeanClass = (Class) rootBean.getClass(); - BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); - + public BaseBeanValidationContext forValidate(Class rootBeanClass, BeanMetaData rootBeanMetaData, T rootBean) { return new BeanValidationContext<>( constraintValidatorManager, constraintValidatorFactory, @@ -64,11 +56,7 @@ public BaseBeanValidationContext forValidate(T rootBean) { ); } - public BaseBeanValidationContext forValidateProperty(T rootBean, PathImpl propertyPath) { - @SuppressWarnings("unchecked") - Class rootBeanClass = (Class) rootBean.getClass(); - BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); - + public BaseBeanValidationContext forValidateProperty(Class rootBeanClass, BeanMetaData rootBeanMetaData, T rootBean, PathImpl propertyPath) { return new PropertyValidationContext<>( constraintValidatorManager, constraintValidatorFactory, @@ -82,9 +70,7 @@ public BaseBeanValidationContext forValidateProperty(T rootBean, PathImpl ); } - public BaseBeanValidationContext forValidateValue(Class rootBeanClass, PathImpl propertyPath) { - BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); - + public BaseBeanValidationContext forValidateValue(Class rootBeanClass, BeanMetaData rootBeanMetaData, PathImpl propertyPath) { return new PropertyValidationContext<>( constraintValidatorManager, constraintValidatorFactory, @@ -99,13 +85,11 @@ public BaseBeanValidationContext forValidateValue(Class rootBeanClass, } public ExecutableValidationContext forValidateParameters( + Class rootBeanClass, + BeanMetaData rootBeanMetaData, T rootBean, Executable executable, Object[] executableParameters) { - @SuppressWarnings("unchecked") - Class rootBeanClass = rootBean != null ? (Class) rootBean.getClass() : (Class) executable.getDeclaringClass(); - BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); - return new ParameterExecutableValidationContext<>( constraintValidatorManager, constraintValidatorFactory, @@ -122,13 +106,11 @@ public ExecutableValidationContext forValidateParameters( } public ExecutableValidationContext forValidateReturnValue( + Class rootBeanClass, + BeanMetaData rootBeanMetaData, T rootBean, Executable executable, Object executableReturnValue) { - @SuppressWarnings("unchecked") - Class rootBeanClass = rootBean != null ? (Class) rootBean.getClass() : (Class) executable.getDeclaringClass(); - BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); - return new ReturnValueExecutableValidationContext<>( constraintValidatorManager, constraintValidatorFactory, From 115d72e78d242caa50b3799931b620e001ab5d58 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 21 Feb 2019 13:06:56 +0100 Subject: [PATCH 188/393] HV-1695 Avoid creating an empty map for group conversions --- .../metadata/provider/AnnotationMetaDataProvider.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java index 17b38c2fb7..bae009a3f7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java @@ -551,6 +551,10 @@ private Map, Class> getGroupConversions(AnnotatedType annotatedType) } private Map, Class> getGroupConversions(ConvertGroup groupConversion, ConvertGroup.List groupConversionList) { + if ( groupConversion == null && ( groupConversionList == null || groupConversionList.value().length == 0 ) ) { + return Collections.emptyMap(); + } + Map, Class> groupConversions = newHashMap(); if ( groupConversion != null ) { From 57dda4383c3409daadca5931b57cc02f3a06d4dd Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 21 Feb 2019 13:54:29 +0100 Subject: [PATCH 189/393] HV-1696 Avoid using computeIfAbsent every time in BeanMetaDataManagerImpl It significantly reduces memory allocation as it avoids the creation of a lambda instance. --- .../metadata/BeanMetaDataManagerImpl.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java index 1b6876ee02..722d92aa2f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java @@ -146,8 +146,20 @@ public BeanMetaDataManagerImpl(ConstraintCreationContext constraintCreationConte public BeanMetaData getBeanMetaData(Class beanClass) { Contracts.assertNotNull( beanClass, MESSAGES.beanTypeCannotBeNull() ); - BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataCache.computeIfAbsent( beanClass, - bc -> createBeanMetaData( bc ) ); + // First, let's do a simple lookup as it's the default case + BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataCache.get( beanClass ); + + if ( beanMetaData != null ) { + return beanMetaData; + } + + beanMetaData = createBeanMetaData( beanClass ); + BeanMetaData previousBeanMetaData = (BeanMetaData) beanMetaDataCache.putIfAbsent( beanClass, beanMetaData ); + + // we return the previous value if not null + if ( previousBeanMetaData != null ) { + return previousBeanMetaData; + } return beanMetaData; } From 22fd3d5fa1387022d63ad6bfc6457c4bffdccf78 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 21 Feb 2019 15:58:23 +0100 Subject: [PATCH 190/393] HV-1697 Reduce memory allocation in ValidationContexts --- .../internal/engine/ValidatorImpl.java | 19 ++-- .../AbstractValidationContext.java | 104 ++++++++++++------ .../internal/util/stereotypes/Lazy.java | 23 ++++ 3 files changed, 101 insertions(+), 45 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/util/stereotypes/Lazy.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index db0d980f4d..48005de326 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -161,10 +161,6 @@ public final Set> validate(T object, Class... grou BaseBeanValidationContext validationContext = getValidationContextBuilder().forValidate( rootBeanClass, rootBeanMetaData, object ); - if ( !validationContext.getRootBeanMetaData().hasConstraints() ) { - return Collections.emptySet(); - } - ValidationOrder validationOrder = determineGroupValidationOrder( groups ); BeanValueContext valueContext = ValueContexts.getLocalExecutionContextForBean( validatorScopedContext.getParameterNameProvider(), @@ -270,6 +266,10 @@ private Set> validateParameters(T object, Executable Class rootBeanClass = object != null ? (Class) object.getClass() : (Class) executable.getDeclaringClass(); BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); + if ( !rootBeanMetaData.hasConstraints() ) { + return Collections.emptySet(); + } + ExecutableValidationContext validationContext = getValidationContextBuilder().forValidateParameters( rootBeanClass, rootBeanMetaData, @@ -278,10 +278,6 @@ private Set> validateParameters(T object, Executable parameterValues ); - if ( !validationContext.getRootBeanMetaData().hasConstraints() ) { - return Collections.emptySet(); - } - ValidationOrder validationOrder = determineGroupValidationOrder( groups ); validateParametersInContext( validationContext, parameterValues, validationOrder ); @@ -296,6 +292,9 @@ private Set> validateReturnValue(T object, Executable Class rootBeanClass = object != null ? (Class) object.getClass() : (Class) executable.getDeclaringClass(); BeanMetaData rootBeanMetaData = beanMetaDataManager.getBeanMetaData( rootBeanClass ); + if ( !rootBeanMetaData.hasConstraints() ) { + return Collections.emptySet(); + } ExecutableValidationContext validationContext = getValidationContextBuilder().forValidateReturnValue( rootBeanClass, @@ -305,10 +304,6 @@ private Set> validateReturnValue(T object, Executable returnValue ); - if ( !validationContext.getRootBeanMetaData().hasConstraints() ) { - return Collections.emptySet(); - } - ValidationOrder validationOrder = determineGroupValidationOrder( groups ); validateReturnValueInContext( validationContext, object, returnValue, validationOrder ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java index 7b5a1faf2e..870f0b2ad7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java @@ -6,9 +6,8 @@ */ package org.hibernate.validator.internal.engine.validationcontext; -import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; - import java.lang.invoke.MethodHandles; +import java.util.Collections; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.Iterator; @@ -35,6 +34,7 @@ import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.internal.util.stereotypes.Lazy; /** * Context object keeping track of all required data for a validation call. @@ -73,49 +73,53 @@ abstract class AbstractValidationContext implements BaseBeanValidationContext private final BeanMetaData rootBeanMetaData; /** - * The set of already processed meta constraints per bean - path ({@link BeanPathMetaConstraintProcessedUnit}). + * The constraint factory which should be used in this context. */ - private final Set processedPathUnits; + private final ConstraintValidatorFactory constraintValidatorFactory; /** - * The set of already processed groups per bean ({@link BeanGroupProcessedUnit}). + * Context containing all {@link Validator} level helpers and configuration properties. */ - private final Set processedGroupUnits; + protected final ValidatorScopedContext validatorScopedContext; /** - * Maps an object to a list of paths in which it has been validated. The objects are the bean instances. + * Allows a JPA provider to decide whether a property should be validated. */ - private final Map> processedPathsPerBean; + private final TraversableResolver traversableResolver; /** - * Contains all failing constraints so far. + * The constraint validator initialization context. */ - private final Set> failingConstraintViolations; + private final HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext; /** - * The constraint factory which should be used in this context. + * Indicates if the tracking of already validated bean should be disabled. */ - private final ConstraintValidatorFactory constraintValidatorFactory; + private final boolean disableAlreadyValidatedBeanTracking; /** - * Context containing all {@link Validator} level helpers and configuration properties. + * The set of already processed meta constraints per bean - path ({@link BeanPathMetaConstraintProcessedUnit}). */ - protected final ValidatorScopedContext validatorScopedContext; + @Lazy + private Set processedPathUnits; /** - * Allows a JPA provider to decide whether a property should be validated. + * The set of already processed groups per bean ({@link BeanGroupProcessedUnit}). */ - private final TraversableResolver traversableResolver; + @Lazy + private Set processedGroupUnits; /** - * The constraint validator initialization context. + * Maps an object to a list of paths in which it has been validated. The objects are the bean instances. */ - private final HibernateConstraintValidatorInitializationContext constraintValidatorInitializationContext; + @Lazy + private Map> processedPathsPerBean; /** - * Indicates if the tracking of already validated bean should be disabled. + * Contains all failing constraints so far. */ - private final boolean disableAlreadyValidatedBeanTracking; + @Lazy + private Set> failingConstraintViolations; protected AbstractValidationContext( ConstraintValidatorManager constraintValidatorManager, @@ -138,11 +142,6 @@ protected AbstractValidationContext( this.rootBeanClass = rootBeanClass; this.rootBeanMetaData = rootBeanMetaData; - this.processedGroupUnits = new HashSet<>(); - this.processedPathUnits = new HashSet<>(); - this.processedPathsPerBean = new IdentityHashMap<>(); - this.failingConstraintViolations = newHashSet(); - this.disableAlreadyValidatedBeanTracking = disableAlreadyValidatedBeanTracking; } @@ -214,6 +213,10 @@ public void markCurrentBeanAsProcessed(ValueContext valueContext) { @Override public Set> getFailingConstraints() { + if ( failingConstraintViolations == null ) { + return Collections.emptySet(); + } + return failingConstraintViolations; } @@ -235,7 +238,7 @@ public void addConstraintFailure( // at this point we make a copy of the path to avoid side effects Path path = PathImpl.createCopy( constraintViolationCreationContext.getPath() ); - this.failingConstraintViolations.add( + getInitializedFailingConstraintViolations().add( createConstraintViolation( messageTemplate, interpolatedMessage, @@ -263,7 +266,7 @@ public boolean hasMetaConstraintBeenProcessed(Object bean, Path path, MetaConstr return false; } - return processedPathUnits.contains( new BeanPathMetaConstraintProcessedUnit( bean, path, metaConstraint ) ); + return getInitializedProcessedPathUnits().contains( new BeanPathMetaConstraintProcessedUnit( bean, path, metaConstraint ) ); } @Override @@ -274,7 +277,7 @@ public void markConstraintProcessed(Object bean, Path path, MetaConstraint me return; } - processedPathUnits.add( new BeanPathMetaConstraintProcessedUnit( bean, path, metaConstraint ) ); + getInitializedProcessedPathUnits().add( new BeanPathMetaConstraintProcessedUnit( bean, path, metaConstraint ) ); } @Override @@ -321,7 +324,7 @@ private String interpolate( } private boolean isAlreadyValidatedForPath(Object value, PathImpl path) { - Set pathSet = processedPathsPerBean.get( value ); + Set pathSet = getInitializedProcessedPathsPerBean().get( value ); if ( pathSet == null ) { return false; } @@ -352,17 +355,52 @@ private boolean isSubPathOf(Path p1, Path p2) { } private boolean isAlreadyValidatedForCurrentGroup(Object value, Class group) { - return processedGroupUnits.contains( new BeanGroupProcessedUnit( value, group ) ); + return getInitializedProcessedGroupUnits().contains( new BeanGroupProcessedUnit( value, group ) ); } private void markCurrentBeanAsProcessedForCurrentPath(Object bean, PathImpl path) { // HV-1031 The path object is mutated as we traverse the object tree, hence copy it before saving it - processedPathsPerBean.computeIfAbsent( bean, b -> new HashSet<>() ) - .add( PathImpl.createCopy( path ) ); + Map> processedPathsPerBean = getInitializedProcessedPathsPerBean(); + + Set processedPaths = processedPathsPerBean.get( bean ); + if ( processedPaths == null ) { + processedPaths = new HashSet<>(); + processedPathsPerBean.put( bean, processedPaths ); + } + + processedPaths.add( PathImpl.createCopy( path ) ); } private void markCurrentBeanAsProcessedForCurrentGroup(Object bean, Class group) { - processedGroupUnits.add( new BeanGroupProcessedUnit( bean, group ) ); + getInitializedProcessedGroupUnits().add( new BeanGroupProcessedUnit( bean, group ) ); + } + + private Set getInitializedProcessedPathUnits() { + if ( processedPathUnits == null ) { + processedPathUnits = new HashSet<>(); + } + return processedPathUnits; + } + + private Set getInitializedProcessedGroupUnits() { + if ( processedGroupUnits == null ) { + processedGroupUnits = new HashSet<>(); + } + return processedGroupUnits; + } + + private Map> getInitializedProcessedPathsPerBean() { + if ( processedPathsPerBean == null ) { + processedPathsPerBean = new IdentityHashMap<>(); + } + return processedPathsPerBean; + } + + private Set> getInitializedFailingConstraintViolations() { + if ( failingConstraintViolations == null ) { + failingConstraintViolations = new HashSet<>(); + } + return failingConstraintViolations; } private static final class BeanPathMetaConstraintProcessedUnit { diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/stereotypes/Lazy.java b/engine/src/main/java/org/hibernate/validator/internal/util/stereotypes/Lazy.java new file mode 100644 index 0000000000..63f90de397 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/util/stereotypes/Lazy.java @@ -0,0 +1,23 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.util.stereotypes; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Documents that the value assigned to the annotated field is lazily initialized and shouldn't be accessed directly but + * via a getter. + * + * @author Guillaume Smet + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.FIELD) +public @interface Lazy { +} From 077827f42b9df1dce46070ae7b34aaa1d025a058 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 27 Feb 2019 16:57:31 +0100 Subject: [PATCH 191/393] HV-1694 Fix our benchmarks following a discussion with Luis Barreiro --- .../validator/performance/simple/SimpleValidation.java | 8 ++++---- .../unconstrained/UnconstrainedBeanValidation.java | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/performance/src/main/java/org/hibernate/validator/performance/simple/SimpleValidation.java b/performance/src/main/java/org/hibernate/validator/performance/simple/SimpleValidation.java index ebdc9e4940..740318cdd4 100644 --- a/performance/src/main/java/org/hibernate/validator/performance/simple/SimpleValidation.java +++ b/performance/src/main/java/org/hibernate/validator/performance/simple/SimpleValidation.java @@ -6,8 +6,8 @@ */ package org.hibernate.validator.performance.simple; -import java.util.Random; import java.util.Set; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import javax.validation.ConstraintViolation; @@ -51,13 +51,13 @@ public class SimpleValidation { @State(Scope.Benchmark) public static class ValidationState { public volatile Validator validator; - public volatile Random random; + public volatile ThreadLocalRandom random; public volatile Driver[] drivers; { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator(); - random = new Random(); + random = ThreadLocalRandom.current(); drivers = new Driver[100]; for ( int i = 0; i < 100; i++ ) { @@ -123,7 +123,7 @@ private static class DriverSetup { private int expectedViolationCount; private Driver driver; - public DriverSetup(Random random) { + public DriverSetup(ThreadLocalRandom random) { expectedViolationCount = 0; String name = names[random.nextInt( 10 )]; diff --git a/performance/src/main/java/org/hibernate/validator/performance/unconstrained/UnconstrainedBeanValidation.java b/performance/src/main/java/org/hibernate/validator/performance/unconstrained/UnconstrainedBeanValidation.java index d6a315abf5..70f8c4c804 100644 --- a/performance/src/main/java/org/hibernate/validator/performance/unconstrained/UnconstrainedBeanValidation.java +++ b/performance/src/main/java/org/hibernate/validator/performance/unconstrained/UnconstrainedBeanValidation.java @@ -6,8 +6,8 @@ */ package org.hibernate.validator.performance.unconstrained; -import java.util.Random; import java.util.Set; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import javax.validation.ConstraintViolation; @@ -48,13 +48,13 @@ public class UnconstrainedBeanValidation { @State(Scope.Benchmark) public static class ValidationState { public volatile Validator validator; - public volatile Random random; + public volatile ThreadLocalRandom random; private volatile Driver[] drivers; { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator(); - random = new Random(); + random = ThreadLocalRandom.current(); drivers = new Driver[100]; for ( int i = 0; i < 100; i++ ) { @@ -109,7 +109,7 @@ private static class DriverSetup { private Driver driver; - public DriverSetup(Random random) { + public DriverSetup(ThreadLocalRandom random) { String name = names[random.nextInt( 10 )]; int randomAge = random.nextInt( 100 ); From 2c60f6ba86e7efda9465b1a090b3ef4a8de1955f Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Fri, 1 Mar 2019 09:44:35 +0100 Subject: [PATCH 192/393] HV-1699 Change how numbers are compared in Max/Min validators - for Min/Max `Number` validators check if actual numbers are not with floating point (float,double) and if they are direct them to correct number comparator helper method - for big numbers (BigDecimal, BigInteger) check in number comparator helper before converting to long. If actual numbers are from a 'Big*' classes direct the call to corresponding overloaded versions of the method so that no data will be lost - Compare floating point numbers using `Double#compare()` --- .../number/bound/MaxValidatorForNumber.java | 4 +++- .../number/bound/MinValidatorForNumber.java | 4 +++- .../number/bound/NumberComparatorHelper.java | 23 ++++++++++++++++--- .../bv/BaseMinMaxValidatorForNumberTest.java | 1 + .../bv/MaxValidatorForNumberTest.java | 22 ++++++++++++++++++ 5 files changed, 49 insertions(+), 5 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForNumber.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForNumber.java index 6d37014fae..63faf7e075 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForNumber.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForNumber.java @@ -6,6 +6,8 @@ */ package org.hibernate.validator.internal.constraintvalidators.bv.number.bound; +import org.hibernate.validator.internal.constraintvalidators.bv.number.InfinityNumberComparatorHelper; + /** * Check that the number being validated is less than or equal to the maximum * value specified. @@ -16,6 +18,6 @@ public class MaxValidatorForNumber extends AbstractMaxValidator { @Override protected int compare(Number number) { - return NumberComparatorHelper.compare( number, maxValue ); + return NumberComparatorHelper.compare( number, maxValue, InfinityNumberComparatorHelper.GREATER_THAN ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForNumber.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForNumber.java index 7b2974df76..cd56e942af 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForNumber.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForNumber.java @@ -6,6 +6,8 @@ */ package org.hibernate.validator.internal.constraintvalidators.bv.number.bound; +import org.hibernate.validator.internal.constraintvalidators.bv.number.InfinityNumberComparatorHelper; + /** * Check that the number being validated is greater than or equal to the minimum * value specified. @@ -16,6 +18,6 @@ public class MinValidatorForNumber extends AbstractMinValidator { @Override protected int compare(Number number) { - return NumberComparatorHelper.compare( number, minValue ); + return NumberComparatorHelper.compare( number, minValue, InfinityNumberComparatorHelper.LESS_THAN ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/NumberComparatorHelper.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/NumberComparatorHelper.java index c70256ff95..65ad5a0c1d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/NumberComparatorHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/NumberComparatorHelper.java @@ -32,7 +32,24 @@ public static int compare(Long number, long value) { return number.compareTo( value ); } - public static int compare(Number number, long value) { + public static int compare(Number number, long value, OptionalInt treatNanAs) { + // In case of comparing numbers before we compare them as two longs: + // 1. We need to check for floating point number as it should be treated differently in such case: + if ( number instanceof Double ) { + return compare( (Double) number, value, treatNanAs ); + } + if ( number instanceof Float ) { + return compare( (Float) number, value, treatNanAs ); + } + + // 2. We need to check for big numbers so that we don't lose data when converting them to long: + if ( number instanceof BigDecimal ) { + return compare( (BigDecimal) number, value ); + } + if ( number instanceof BigInteger ) { + return compare( (BigInteger) number, value ); + } + return Long.compare( number.longValue(), value ); } @@ -41,7 +58,7 @@ public static int compare(Double number, long value, OptionalInt treatNanAs) { if ( infinity.isPresent() ) { return infinity.getAsInt(); } - return Long.compare( number.longValue(), value ); + return Double.compare( number, value ); } public static int compare(Float number, long value, OptionalInt treatNanAs) { @@ -49,6 +66,6 @@ public static int compare(Float number, long value, OptionalInt treatNanAs) { if ( infinity.isPresent() ) { return infinity.getAsInt(); } - return Long.compare( number.longValue(), value ); + return Float.compare( number, value ); } } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/BaseMinMaxValidatorForNumberTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/BaseMinMaxValidatorForNumberTest.java index 90f25798fa..aa09b05933 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/BaseMinMaxValidatorForNumberTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/BaseMinMaxValidatorForNumberTest.java @@ -98,6 +98,7 @@ protected void testValidatorDouble(ConstraintValidator constraint, bo assertTrue( constraint.isValid( null, null ) ); assertEquals( constraint.isValid( 14.99, null ), isMax ); + assertEquals( constraint.isValid( 15.001, null ), !isMax ); assertEquals( constraint.isValid( -14.99, null ), isMax ); assertEquals( constraint.isValid( -1560000000D, null ), isMax ); assertEquals( constraint.isValid( Double.NEGATIVE_INFINITY, null ), isMax ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MaxValidatorForNumberTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MaxValidatorForNumberTest.java index d75b087855..cf718aabc6 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MaxValidatorForNumberTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MaxValidatorForNumberTest.java @@ -6,6 +6,11 @@ */ package org.hibernate.validator.test.internal.constraintvalidators.bv; +import static org.testng.Assert.assertFalse; + +import java.math.BigDecimal; +import java.math.BigInteger; + import javax.validation.constraints.DecimalMax; import javax.validation.constraints.Max; @@ -79,6 +84,23 @@ public void testIsValidDecimalMaxExclusive() { } + @Test + @TestForIssue(jiraKey = "HV-1699") + public void testIsValidNumberForFloatingPointOrBigNumbersStoredAsNumber() { + ConstraintAnnotationDescriptor.Builder descriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( Max.class ); + descriptorBuilder.setAttribute( "value", 1L ); + Max m = descriptorBuilder.build().getAnnotation(); + MaxValidatorForNumber validator = new MaxValidatorForNumber(); + validator.initialize( m ); + + assertFalse( validator.isValid( 1.01, null ) ); + assertFalse( validator.isValid( 1.01F, null ) ); + assertFalse( validator.isValid( new BigDecimal( "1.01" ), null ) ); + assertFalse( validator.isValid( new BigInteger( "2" ), null ) ); + assertFalse( validator.isValid( Double.POSITIVE_INFINITY, null ) ); + assertFalse( validator.isValid( Float.POSITIVE_INFINITY, null ) ); + } + private void testDecimalMax(DecimalMax m, boolean inclusive) { AbstractDecimalMaxValidator constraint = new DecimalMaxValidatorForNumber(); constraint.initialize( m ); From 09f9be99ffb5613aec3370acbabd193a416b49d6 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 28 Feb 2019 01:11:50 +0100 Subject: [PATCH 193/393] HV-1693 Don't build the WildFly modules with JDK 12 The cdi jar is not available so we can't build the modules. --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index d1ae04061e..1cea3b5844 100644 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,6 @@ test-utils build-config engine - modules tck-runner annotation-processor performance @@ -1220,7 +1219,7 @@ osgi - + jdk11- @@ -1229,6 +1228,7 @@ cdi + modules integration From 7d7b4fa6c24e6a1391d49c7079808a8273fa0dd0 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 28 Feb 2019 01:24:59 +0100 Subject: [PATCH 194/393] HV-1693 Fix the dependencies of the tck-runner module --- tck-runner/pom.xml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 4b01b88584..469ad132ed 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -38,10 +38,6 @@ ${project.groupId} hibernate-validator - - ${project.groupId} - hibernate-validator-cdi - org.glassfish javax.el @@ -236,6 +232,13 @@ wildfly-arquillian-container-managed test + + ${project.groupId} + hibernate-validator-modules + ${project.version} + wildfly-${version.wildfly.tck}-patch + zip + From f57d466ed2e4b919868941444963c4f5cfea0a9d Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 28 Feb 2019 01:26:18 +0100 Subject: [PATCH 195/393] HV-1693 Don't build the documentation and distribution with JDK 12 We don't build the CDI extension with JDK 12 so we can't build the documentation and distribution. --- pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pom.xml b/pom.xml index 1cea3b5844..dfcce5de29 100644 --- a/pom.xml +++ b/pom.xml @@ -1111,6 +1111,8 @@ disableDocumentationBuild !true + + (,12) documentation @@ -1123,6 +1125,8 @@ disableDistributionBuild !true + + (,12) distribution From 6a0aa4059ea7fd3c003f00743990fface36b33db Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Fri, 1 Mar 2019 23:49:57 +0100 Subject: [PATCH 196/393] HV-1700 Remove ValueExtractor service file as not needed - as the value extractors and tests for it from this file was moved to BVTCK the file became redundant and can be removed to prevent tests from logging messages about troubles with missing VE --- .../services/javax.validation.valueextraction.ValueExtractor | 1 - 1 file changed, 1 deletion(-) delete mode 100644 engine/src/test/resources/META-INF/services/javax.validation.valueextraction.ValueExtractor diff --git a/engine/src/test/resources/META-INF/services/javax.validation.valueextraction.ValueExtractor b/engine/src/test/resources/META-INF/services/javax.validation.valueextraction.ValueExtractor deleted file mode 100644 index 78eaaae0e1..0000000000 --- a/engine/src/test/resources/META-INF/services/javax.validation.valueextraction.ValueExtractor +++ /dev/null @@ -1 +0,0 @@ -org.hibernate.validator.test.internal.engine.cascaded.GuavaOptionalValueExtractor From 8dc67c44e5ceb7e7435c09c3e5e956fe508bcfa4 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Sun, 3 Mar 2019 16:31:22 +0100 Subject: [PATCH 197/393] HV-1701 Add integer type specific min/max validators - Add specific validators for min/max constraints and byte/short/integer types as the existing common number one makes additional actions that can be omitted in this case. --- .../bv/number/bound/MaxValidatorForByte.java | 21 +++++++++ .../number/bound/MaxValidatorForInteger.java | 21 +++++++++ .../bv/number/bound/MaxValidatorForShort.java | 21 +++++++++ .../bv/number/bound/MinValidatorForByte.java | 21 +++++++++ .../number/bound/MinValidatorForInteger.java | 21 +++++++++ .../bv/number/bound/MinValidatorForShort.java | 21 +++++++++ .../number/bound/NumberComparatorHelper.java | 16 +++++-- .../metadata/core/ConstraintHelper.java | 15 +++++++ .../bv/BaseMinMaxValidatorForNumberTest.java | 45 +++++++++++++++++++ .../bv/MaxValidatorForNumberTest.java | 15 +++++++ .../bv/MinValidatorForNumberTest.java | 15 +++++++ .../ConstraintValidatorCachingTest.java | 4 +- 12 files changed, 230 insertions(+), 6 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForByte.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForInteger.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForShort.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForByte.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForInteger.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForShort.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForByte.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForByte.java new file mode 100644 index 0000000000..e7b0b67fc8 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForByte.java @@ -0,0 +1,21 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.bound; + +/** + * Check that the number being validated is less than or equal to the maximum + * value specified. + * + * @author Marko Bekhta + */ +public class MaxValidatorForByte extends AbstractMaxValidator { + + @Override + protected int compare(Byte number) { + return NumberComparatorHelper.compare( number.longValue(), maxValue ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForInteger.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForInteger.java new file mode 100644 index 0000000000..dbd70f977e --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForInteger.java @@ -0,0 +1,21 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.bound; + +/** + * Check that the number being validated is less than or equal to the maximum + * value specified. + * + * @author Marko Bekhta + */ +public class MaxValidatorForInteger extends AbstractMaxValidator { + + @Override + protected int compare(Integer number) { + return NumberComparatorHelper.compare( number.longValue(), maxValue ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForShort.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForShort.java new file mode 100644 index 0000000000..352c24bfea --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForShort.java @@ -0,0 +1,21 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.bound; + +/** + * Check that the number being validated is less than or equal to the maximum + * value specified. + * + * @author Marko Bekhta + */ +public class MaxValidatorForShort extends AbstractMaxValidator { + + @Override + protected int compare(Short number) { + return NumberComparatorHelper.compare( number.longValue(), maxValue ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForByte.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForByte.java new file mode 100644 index 0000000000..58542ffb41 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForByte.java @@ -0,0 +1,21 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.bound; + +/** + * Check that the number being validated is greater than or equal to the minimum + * value specified. + * + * @author Marko Bekhta + */ +public class MinValidatorForByte extends AbstractMinValidator { + + @Override + protected int compare(Byte number) { + return NumberComparatorHelper.compare( number.longValue(), minValue ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForInteger.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForInteger.java new file mode 100644 index 0000000000..61e5b8e36f --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForInteger.java @@ -0,0 +1,21 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.bound; + +/** + * Check that the number being validated is greater than or equal to the minimum + * value specified. + * + * @author Marko Bekhta + */ +public class MinValidatorForInteger extends AbstractMinValidator { + + @Override + protected int compare(Integer number) { + return NumberComparatorHelper.compare( number.longValue(), minValue ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForShort.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForShort.java new file mode 100644 index 0000000000..52bd2415cb --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForShort.java @@ -0,0 +1,21 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.bound; + +/** + * Check that the number being validated is greater than or equal to the minimum + * value specified. + * + * @author Marko Bekhta + */ +public class MinValidatorForShort extends AbstractMinValidator { + + @Override + protected int compare(Short number) { + return NumberComparatorHelper.compare( number.longValue(), minValue ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/NumberComparatorHelper.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/NumberComparatorHelper.java index 65ad5a0c1d..36a9c19320 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/NumberComparatorHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/NumberComparatorHelper.java @@ -33,8 +33,9 @@ public static int compare(Long number, long value) { } public static int compare(Number number, long value, OptionalInt treatNanAs) { - // In case of comparing numbers before we compare them as two longs: - // 1. We need to check for floating point number as it should be treated differently in such case: + // In case of comparing numbers we need to check for special cases: + // 1. Floating point numbers should consider nan/infinity as values hence they should + // be directed to corresponding overloaded methods: if ( number instanceof Double ) { return compare( (Double) number, value, treatNanAs ); } @@ -42,7 +43,7 @@ public static int compare(Number number, long value, OptionalInt treatNanAs) { return compare( (Float) number, value, treatNanAs ); } - // 2. We need to check for big numbers so that we don't lose data when converting them to long: + // 2. For big numbers we don't want to lose any data so we just cast them and call corresponding methods: if ( number instanceof BigDecimal ) { return compare( (BigDecimal) number, value ); } @@ -50,7 +51,14 @@ public static int compare(Number number, long value, OptionalInt treatNanAs) { return compare( (BigInteger) number, value ); } - return Long.compare( number.longValue(), value ); + // 3. For any integer types we convert them to long as we would do that anyway + // when comparing with a long value. And use corresponding method for longs: + if ( number instanceof Byte || number instanceof Integer || number instanceof Long || number instanceof Short ) { + return compare( number.longValue(), value ); + } + + // 4. As a fallback we convert the number to double: + return compare( number.doubleValue(), value, treatNanAs ); } public static int compare(Double number, long value, OptionalInt treatNanAs) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java index d7502ee3de..a191f25638 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java @@ -115,16 +115,22 @@ import org.hibernate.validator.internal.constraintvalidators.bv.notempty.NotEmptyValidatorForMap; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForBigInteger; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForByte; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForDouble; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForFloat; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForLong; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForNumber; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForShort; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForBigInteger; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForByte; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForDouble; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForFloat; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForLong; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForNumber; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForShort; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForBigInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForDouble; @@ -427,20 +433,26 @@ public ConstraintHelper() { putConstraints( tmpConstraints, Max.class, Arrays.asList( MaxValidatorForBigDecimal.class, MaxValidatorForBigInteger.class, + MaxValidatorForByte.class, MaxValidatorForDouble.class, MaxValidatorForFloat.class, + MaxValidatorForInteger.class, MaxValidatorForLong.class, MaxValidatorForNumber.class, + MaxValidatorForShort.class, MaxValidatorForCharSequence.class, MaxValidatorForMonetaryAmount.class ) ); putConstraints( tmpConstraints, Min.class, Arrays.asList( MinValidatorForBigDecimal.class, MinValidatorForBigInteger.class, + MinValidatorForByte.class, MinValidatorForDouble.class, MinValidatorForFloat.class, + MinValidatorForInteger.class, MinValidatorForLong.class, MinValidatorForNumber.class, + MinValidatorForShort.class, MinValidatorForCharSequence.class, MinValidatorForMonetaryAmount.class ) ); @@ -458,10 +470,13 @@ public ConstraintHelper() { putConstraints( tmpConstraints, Min.class, Arrays.asList( MinValidatorForBigDecimal.class, MinValidatorForBigInteger.class, + MinValidatorForByte.class, MinValidatorForDouble.class, MinValidatorForFloat.class, + MinValidatorForInteger.class, MinValidatorForLong.class, MinValidatorForNumber.class, + MinValidatorForShort.class, MinValidatorForCharSequence.class ) ); } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/BaseMinMaxValidatorForNumberTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/BaseMinMaxValidatorForNumberTest.java index aa09b05933..e619c44d42 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/BaseMinMaxValidatorForNumberTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/BaseMinMaxValidatorForNumberTest.java @@ -75,6 +75,51 @@ protected void testValidatorBigInteger(ConstraintValidator constr assertEquals( constraint.isValid( BigInteger.valueOf( 1560000000 ), null ), !isMax ); } + protected void testValidatorByte(ConstraintValidator constraint, boolean inclusive, boolean isMax) { + if ( inclusive ) { + assertTrue( constraint.isValid( (byte) 15, null ) ); + } + else { + assertFalse( constraint.isValid( (byte) 15, null ) ); + } + + assertTrue( constraint.isValid( null, null ) ); + assertEquals( constraint.isValid( (byte) 14, null ), isMax ); + assertEquals( constraint.isValid( (byte) 16, null ), !isMax ); + assertEquals( constraint.isValid( Byte.MIN_VALUE, null ), isMax ); + assertEquals( constraint.isValid( Byte.MAX_VALUE, null ), !isMax ); + } + + protected void testValidatorShort(ConstraintValidator constraint, boolean inclusive, boolean isMax) { + if ( inclusive ) { + assertTrue( constraint.isValid( (short) 15, null ) ); + } + else { + assertFalse( constraint.isValid( (short) 15, null ) ); + } + + assertTrue( constraint.isValid( null, null ) ); + assertEquals( constraint.isValid( (short) 14, null ), isMax ); + assertEquals( constraint.isValid( (short) 16, null ), !isMax ); + assertEquals( constraint.isValid( Short.MIN_VALUE, null ), isMax ); + assertEquals( constraint.isValid( Short.MAX_VALUE, null ), !isMax ); + } + + protected void testValidatorInteger(ConstraintValidator constraint, boolean inclusive, boolean isMax) { + if ( inclusive ) { + assertTrue( constraint.isValid( 15, null ) ); + } + else { + assertFalse( constraint.isValid( 15, null ) ); + } + + assertTrue( constraint.isValid( null, null ) ); + assertEquals( constraint.isValid( 14, null ), isMax ); + assertEquals( constraint.isValid( 16, null ), !isMax ); + assertEquals( constraint.isValid( Integer.MIN_VALUE, null ), isMax ); + assertEquals( constraint.isValid( Integer.MAX_VALUE, null ), !isMax ); + } + protected void testValidatorLong(ConstraintValidator constraint, boolean inclusive, boolean isMax) { if ( inclusive ) { assertTrue( constraint.isValid( 15L, null ) ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MaxValidatorForNumberTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MaxValidatorForNumberTest.java index cf718aabc6..71ed569aa9 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MaxValidatorForNumberTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MaxValidatorForNumberTest.java @@ -17,10 +17,13 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.AbstractMaxValidator; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForBigInteger; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForByte; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForDouble; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForFloat; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForLong; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForNumber; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForShort; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.AbstractDecimalMaxValidator; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForBigInteger; @@ -140,6 +143,18 @@ private void testMax(Max m, boolean inclusive) { constraint.initialize( m ); testValidatorBigInteger( constraint, inclusive, true ); + constraint = new MaxValidatorForByte(); + constraint.initialize( m ); + testValidatorByte( constraint, inclusive, true ); + + constraint = new MaxValidatorForShort(); + constraint.initialize( m ); + testValidatorShort( constraint, inclusive, true ); + + constraint = new MaxValidatorForInteger(); + constraint.initialize( m ); + testValidatorInteger( constraint, inclusive, true ); + constraint = new MaxValidatorForLong(); constraint.initialize( m ); testValidatorLong( constraint, inclusive, true ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MinValidatorForNumberTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MinValidatorForNumberTest.java index 5482548957..d642796cb9 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MinValidatorForNumberTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MinValidatorForNumberTest.java @@ -12,10 +12,13 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.AbstractMinValidator; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForBigInteger; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForByte; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForDouble; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForFloat; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForLong; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForNumber; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForShort; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.AbstractDecimalMinValidator; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForBigInteger; @@ -118,6 +121,18 @@ private void testMin(Min m, boolean inclusive) { constraint.initialize( m ); testValidatorBigInteger( constraint, inclusive, false ); + constraint = new MinValidatorForByte(); + constraint.initialize( m ); + testValidatorByte( constraint, inclusive, false ); + + constraint = new MinValidatorForShort(); + constraint.initialize( m ); + testValidatorShort( constraint, inclusive, false ); + + constraint = new MinValidatorForInteger(); + constraint.initialize( m ); + testValidatorInteger( constraint, inclusive, false ); + constraint = new MinValidatorForLong(); constraint.initialize( m ); testValidatorLong( constraint, inclusive, false ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/ConstraintValidatorCachingTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/ConstraintValidatorCachingTest.java index f9cbdbb3b3..a983610039 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/ConstraintValidatorCachingTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/ConstraintValidatorCachingTest.java @@ -41,7 +41,7 @@ import javax.validation.constraints.Size; import org.hibernate.validator.internal.constraintvalidators.bv.NotNullValidator; -import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForNumber; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForInteger; import org.hibernate.validator.internal.constraintvalidators.bv.size.SizeValidatorForCollection; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorFactoryImpl; import org.hibernate.validator.testutil.TestForIssue; @@ -78,7 +78,7 @@ public void testConstraintValidatorInstancesAreCached() { constraintValidatorFactory.assertSize( 3 ); constraintValidatorFactory.assertKeyExists( SizeValidatorForCollection.class ); - constraintValidatorFactory.assertKeyExists( MinValidatorForNumber.class ); + constraintValidatorFactory.assertKeyExists( MinValidatorForInteger.class ); constraintValidatorFactory.assertKeyExists( NotNullValidator.class ); // getting a new validator from the same factory should have the same instances cached From c92d43cbe34bb4fb1321657acf2b1f5382899f69 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Sun, 3 Mar 2019 17:13:20 +0100 Subject: [PATCH 198/393] HV-1701 Add integer type specific DecimalMin/DecimalMax validators - Make checks in Number validator for DecimalMin/DecimalMax to check for double/float to capture infinity situation correctly. Also direct a check of Big* types to corresponding methods - Add specific validators for DecimalMin/DecimalMax constraints and byte/short/integer types as the existing common number one makes additional actions that can be omitted in this case. --- .../decimal/DecimalMaxValidatorForByte.java | 21 ++++++++++++++ .../DecimalMaxValidatorForInteger.java | 21 ++++++++++++++ .../decimal/DecimalMaxValidatorForNumber.java | 7 +++-- .../decimal/DecimalMaxValidatorForShort.java | 21 ++++++++++++++ .../decimal/DecimalMinValidatorForByte.java | 21 ++++++++++++++ .../DecimalMinValidatorForInteger.java | 21 ++++++++++++++ .../decimal/DecimalMinValidatorForNumber.java | 7 +++-- .../decimal/DecimalMinValidatorForShort.java | 21 ++++++++++++++ .../DecimalNumberComparatorHelper.java | 29 +++++++++++++++++-- .../metadata/core/ConstraintHelper.java | 18 ++++++++++++ .../bv/MaxValidatorForNumberTest.java | 26 +++++++++++++++++ .../bv/MinValidatorForNumberTest.java | 15 ++++++++++ 12 files changed, 222 insertions(+), 6 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForByte.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForInteger.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForShort.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForByte.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForInteger.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForShort.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForByte.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForByte.java new file mode 100644 index 0000000000..08c98d28e5 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForByte.java @@ -0,0 +1,21 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal; + +/** + * Check that the number being validated is less than or equal to the maximum + * value specified. + * + * @author Marko Bekhta + */ +public class DecimalMaxValidatorForByte extends AbstractDecimalMaxValidator { + + @Override + protected int compare(Byte number) { + return DecimalNumberComparatorHelper.compare( number.longValue(), maxValue ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForInteger.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForInteger.java new file mode 100644 index 0000000000..7377be0a93 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForInteger.java @@ -0,0 +1,21 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal; + +/** + * Check that the number being validated is less than or equal to the maximum + * value specified. + * + * @author Marko Bekhta + */ +public class DecimalMaxValidatorForInteger extends AbstractDecimalMaxValidator { + + @Override + protected int compare(Integer number) { + return DecimalNumberComparatorHelper.compare( number.longValue(), maxValue ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForNumber.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForNumber.java index 1d26c614e3..5290001508 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForNumber.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForNumber.java @@ -6,6 +6,8 @@ */ package org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal; +import org.hibernate.validator.internal.constraintvalidators.bv.number.InfinityNumberComparatorHelper; + /** * Check that the number being validated is less than or equal to the maximum * value specified. @@ -14,7 +16,8 @@ */ public class DecimalMaxValidatorForNumber extends AbstractDecimalMaxValidator { - @Override protected int compare(Number number) { - return DecimalNumberComparatorHelper.compare( number, maxValue ); + @Override + protected int compare(Number number) { + return DecimalNumberComparatorHelper.compare( number, maxValue, InfinityNumberComparatorHelper.GREATER_THAN ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForShort.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForShort.java new file mode 100644 index 0000000000..d858041208 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForShort.java @@ -0,0 +1,21 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal; + +/** + * Check that the number being validated is less than or equal to the maximum + * value specified. + * + * @author Marko Bekhta + */ +public class DecimalMaxValidatorForShort extends AbstractDecimalMaxValidator { + + @Override + protected int compare(Short number) { + return DecimalNumberComparatorHelper.compare( number.longValue(), maxValue ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForByte.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForByte.java new file mode 100644 index 0000000000..aab9e90a93 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForByte.java @@ -0,0 +1,21 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal; + +/** + * Check that the number being validated is greater than or equal to the minimum + * value specified. + * + * @author Marko Bekhta + */ +public class DecimalMinValidatorForByte extends AbstractDecimalMinValidator { + + @Override + protected int compare(Byte number) { + return DecimalNumberComparatorHelper.compare( number.longValue(), minValue ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForInteger.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForInteger.java new file mode 100644 index 0000000000..ca52640ae1 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForInteger.java @@ -0,0 +1,21 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal; + +/** + * Check that the number being validated is greater than or equal to the minimum + * value specified. + * + * @author Marko Bekhta + */ +public class DecimalMinValidatorForInteger extends AbstractDecimalMinValidator { + + @Override + protected int compare(Integer number) { + return DecimalNumberComparatorHelper.compare( number.longValue(), minValue ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForNumber.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForNumber.java index 571a7c8f24..ee40ebfbb0 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForNumber.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForNumber.java @@ -6,6 +6,8 @@ */ package org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal; +import org.hibernate.validator.internal.constraintvalidators.bv.number.InfinityNumberComparatorHelper; + /** * Check that the number being validated is greater than or equal to the minimum * value specified. @@ -14,7 +16,8 @@ */ public class DecimalMinValidatorForNumber extends AbstractDecimalMinValidator { - @Override protected int compare(Number number) { - return DecimalNumberComparatorHelper.compare( number, minValue ); + @Override + protected int compare(Number number) { + return DecimalNumberComparatorHelper.compare( number, minValue, InfinityNumberComparatorHelper.LESS_THAN ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForShort.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForShort.java new file mode 100644 index 0000000000..398928ea53 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForShort.java @@ -0,0 +1,21 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal; + +/** + * Check that the number being validated is greater than or equal to the minimum + * value specified. + * + * @author Marko Bekhta + */ +public class DecimalMinValidatorForShort extends AbstractDecimalMinValidator { + + @Override + protected int compare(Short number) { + return DecimalNumberComparatorHelper.compare( number.longValue(), minValue ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalNumberComparatorHelper.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalNumberComparatorHelper.java index 1b9cb3b150..c5fa1d2b76 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalNumberComparatorHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalNumberComparatorHelper.java @@ -32,8 +32,33 @@ public static int compare(Long number, BigDecimal value) { return BigDecimal.valueOf( number ).compareTo( value ); } - public static int compare(Number number, BigDecimal value) { - return BigDecimal.valueOf( number.doubleValue() ).compareTo( value ); + public static int compare(Number number, BigDecimal value, OptionalInt treatNanAs) { + // In case of comparing numbers we need to check for special cases: + // 1. Floating point numbers should consider nan/infinity as values hence they should + // be directed to corresponding overloaded methods: + if ( number instanceof Double ) { + return compare( (Double) number, value, treatNanAs ); + } + if ( number instanceof Float ) { + return compare( (Float) number, value, treatNanAs ); + } + + // 2. For big numbers we don't want to lose any data so we just cast them and call corresponding methods: + if ( number instanceof BigDecimal ) { + return compare( (BigDecimal) number, value ); + } + if ( number instanceof BigInteger ) { + return compare( (BigInteger) number, value ); + } + + // 3. For any integer types we convert them to long as we would do that anyway + // to create a BigDecimal instance. And use corresponding method for longs: + if ( number instanceof Byte || number instanceof Integer || number instanceof Long || number instanceof Short ) { + return compare( number.longValue(), value ); + } + + // 4. As a fallback we convert the number to double: + return compare( number.doubleValue(), value, treatNanAs ); } public static int compare(Double number, BigDecimal value, OptionalInt treatNanAs) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java index a191f25638..965d2c7737 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java @@ -133,16 +133,22 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForShort; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForBigInteger; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForByte; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForDouble; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForFloat; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForLong; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForNumber; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForShort; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForBigInteger; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForByte; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForDouble; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForFloat; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForLong; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForNumber; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForShort; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeOrZeroValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeOrZeroValidatorForBigInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeOrZeroValidatorForByte; @@ -337,20 +343,26 @@ public ConstraintHelper() { putConstraints( tmpConstraints, DecimalMax.class, Arrays.asList( DecimalMaxValidatorForBigDecimal.class, DecimalMaxValidatorForBigInteger.class, + DecimalMaxValidatorForByte.class, DecimalMaxValidatorForDouble.class, DecimalMaxValidatorForFloat.class, DecimalMaxValidatorForLong.class, + DecimalMaxValidatorForInteger.class, DecimalMaxValidatorForNumber.class, + DecimalMaxValidatorForShort.class, DecimalMaxValidatorForCharSequence.class, DecimalMaxValidatorForMonetaryAmount.class ) ); putConstraints( tmpConstraints, DecimalMin.class, Arrays.asList( DecimalMinValidatorForBigDecimal.class, DecimalMinValidatorForBigInteger.class, + DecimalMinValidatorForByte.class, DecimalMinValidatorForDouble.class, DecimalMinValidatorForFloat.class, DecimalMinValidatorForLong.class, + DecimalMinValidatorForInteger.class, DecimalMinValidatorForNumber.class, + DecimalMinValidatorForShort.class, DecimalMinValidatorForCharSequence.class, DecimalMinValidatorForMonetaryAmount.class ) ); @@ -359,19 +371,25 @@ public ConstraintHelper() { putConstraints( tmpConstraints, DecimalMax.class, Arrays.asList( DecimalMaxValidatorForBigDecimal.class, DecimalMaxValidatorForBigInteger.class, + DecimalMaxValidatorForByte.class, DecimalMaxValidatorForDouble.class, DecimalMaxValidatorForFloat.class, DecimalMaxValidatorForLong.class, + DecimalMaxValidatorForInteger.class, DecimalMaxValidatorForNumber.class, + DecimalMaxValidatorForShort.class, DecimalMaxValidatorForCharSequence.class ) ); putConstraints( tmpConstraints, DecimalMin.class, Arrays.asList( DecimalMinValidatorForBigDecimal.class, DecimalMinValidatorForBigInteger.class, + DecimalMinValidatorForByte.class, DecimalMinValidatorForDouble.class, DecimalMinValidatorForFloat.class, DecimalMinValidatorForLong.class, + DecimalMinValidatorForInteger.class, DecimalMinValidatorForNumber.class, + DecimalMinValidatorForShort.class, DecimalMinValidatorForCharSequence.class ) ); } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MaxValidatorForNumberTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MaxValidatorForNumberTest.java index 71ed569aa9..9b980e54d8 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MaxValidatorForNumberTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MaxValidatorForNumberTest.java @@ -27,10 +27,13 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.AbstractDecimalMaxValidator; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForBigInteger; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForByte; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForDouble; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForFloat; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForLong; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForNumber; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForShort; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.testutil.TestForIssue; import org.testng.annotations.Test; @@ -63,6 +66,17 @@ public void testIsValidDecimalMax() { testDecimalMax( m, true ); } + @Test + public void testIsValidDecimalMax1() { + ConstraintAnnotationDescriptor.Builder descriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( DecimalMax.class ); + descriptorBuilder.setAttribute( "value", Integer.toString( Integer.MAX_VALUE - 1 ) ); + DecimalMax m = descriptorBuilder.build().getAnnotation(); + + DecimalMaxValidatorForNumber constraint = new DecimalMaxValidatorForNumber(); + constraint.initialize( m ); + assertFalse( constraint.isValid( Double.POSITIVE_INFINITY, null ) ); + } + @Test(expectedExceptions = IllegalArgumentException.class) public void testInitializeDecimalMaxWithInvalidValue() { ConstraintAnnotationDescriptor.Builder descriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( DecimalMax.class ); @@ -117,6 +131,18 @@ private void testDecimalMax(DecimalMax m, boolean inclusive) { constraint.initialize( m ); testValidatorBigInteger( constraint, inclusive, true ); + constraint = new DecimalMaxValidatorForByte(); + constraint.initialize( m ); + testValidatorByte( constraint, inclusive, true ); + + constraint = new DecimalMaxValidatorForShort(); + constraint.initialize( m ); + testValidatorShort( constraint, inclusive, true ); + + constraint = new DecimalMaxValidatorForInteger(); + constraint.initialize( m ); + testValidatorInteger( constraint, inclusive, true ); + constraint = new DecimalMaxValidatorForLong(); constraint.initialize( m ); testValidatorLong( constraint, inclusive, true ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MinValidatorForNumberTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MinValidatorForNumberTest.java index d642796cb9..a7170ca079 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MinValidatorForNumberTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MinValidatorForNumberTest.java @@ -22,10 +22,13 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.AbstractDecimalMinValidator; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForBigInteger; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForByte; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForDouble; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForFloat; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForLong; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForNumber; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForShort; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.testutil.TestForIssue; import org.testng.annotations.Test; @@ -95,6 +98,18 @@ private void testDecimalMin(DecimalMin m, boolean inclusive) { constraint.initialize( m ); testValidatorBigInteger( constraint, inclusive, false ); + constraint = new DecimalMinValidatorForByte(); + constraint.initialize( m ); + testValidatorByte( constraint, inclusive, false ); + + constraint = new DecimalMinValidatorForShort(); + constraint.initialize( m ); + testValidatorShort( constraint, inclusive, false ); + + constraint = new DecimalMinValidatorForInteger(); + constraint.initialize( m ); + testValidatorInteger( constraint, inclusive, false ); + constraint = new DecimalMinValidatorForLong(); constraint.initialize( m ); testValidatorLong( constraint, inclusive, false ); From 3c80b5a3f95307618c5d305c0b27b4954b8e6366 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Mon, 4 Mar 2019 13:38:33 +0100 Subject: [PATCH 199/393] HV-1701 Add a couple more test cases - for number test add more number types to cover the logic of `compare(Number...)` and all ifs in it - For DecimalM?? constraints added a case with decimal fraction in constraint value. "integer" values should be already covered. --- .../bv/BaseMinMaxValidatorForNumberTest.java | 13 ++++++++ .../bv/MaxValidatorForNumberTest.java | 29 +++++++++++++++++ .../bv/MinValidatorForNumberTest.java | 32 +++++++++++++++++++ 3 files changed, 74 insertions(+) diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/BaseMinMaxValidatorForNumberTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/BaseMinMaxValidatorForNumberTest.java index e619c44d42..db61ffb393 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/BaseMinMaxValidatorForNumberTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/BaseMinMaxValidatorForNumberTest.java @@ -13,6 +13,7 @@ import java.lang.annotation.Annotation; import java.math.BigDecimal; import java.math.BigInteger; + import javax.validation.ConstraintValidator; /** @@ -39,6 +40,18 @@ protected void testNumberValidator(ConstraintValidator descriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( DecimalMax.class ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MinValidatorForNumberTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MinValidatorForNumberTest.java index a7170ca079..2b1e742649 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MinValidatorForNumberTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MinValidatorForNumberTest.java @@ -6,6 +6,14 @@ */ package org.hibernate.validator.test.internal.constraintvalidators.bv; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertNoViolations; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; +import static org.hibernate.validator.testutils.ValidatorUtil.getValidator; + +import java.math.BigDecimal; + +import javax.validation.Validator; import javax.validation.constraints.DecimalMin; import javax.validation.constraints.Min; @@ -31,6 +39,7 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForShort; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.testutil.TestForIssue; + import org.testng.annotations.Test; /** @@ -61,6 +70,29 @@ public void testIsValidDecimalMinValidator() { testDecimalMin( m, true ); } + @Test + public void testIsValidDecimalMinWithDecimalFractionInConstraint() { + class Foo { + @DecimalMin("15.0001") + private final Number num; + + Foo(final Number num) { + this.num = num; + } + } + + Validator validator = getValidator(); + + assertThat( validator.validate( new Foo( 15 ) ) ).containsOnlyViolations( violationOf( DecimalMin.class ) ); + assertNoViolations( validator.validate( new Foo( 16 ) ) ); + + assertThat( validator.validate( new Foo( 15.00001 ) ) ).containsOnlyViolations( violationOf( DecimalMin.class ) ); + assertNoViolations( validator.validate( new Foo( 15.01 ) ) ); + + assertThat( validator.validate( new Foo( BigDecimal.valueOf( 15.00001 ) ) ) ).containsOnlyViolations( violationOf( DecimalMin.class ) ); + assertNoViolations( validator.validate( new Foo( BigDecimal.valueOf( 15.01 ) ) ) ); + } + @Test(expectedExceptions = IllegalArgumentException.class) public void testInitializeDecimalMinWithInvalidValue() { ConstraintAnnotationDescriptor.Builder descriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( DecimalMin.class ); From c071839a70923ad6d3ab321e7c4fd59e8931d44b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Mon, 11 Mar 2019 09:06:58 +0100 Subject: [PATCH 200/393] HV-1702 Upgrade to maven-checkstyle-plugin 3.0.0 --- build-config/src/main/resources/checkstyle.xml | 3 ++- pom.xml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build-config/src/main/resources/checkstyle.xml b/build-config/src/main/resources/checkstyle.xml index dbe0bfd190..df0f8a3a0f 100644 --- a/build-config/src/main/resources/checkstyle.xml +++ b/build-config/src/main/resources/checkstyle.xml @@ -10,8 +10,9 @@ + + - diff --git a/pom.xml b/pom.xml index dfcce5de29..b644e6c761 100644 --- a/pom.xml +++ b/pom.xml @@ -201,7 +201,7 @@ 3.1.0 3.0.0 3.5.0 - 2.17 + 3.0.0 3.0.0 3.7.0 0.0.6 From f8d35df4c728919a448988ce6e5de3538a7f0f9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Mon, 11 Mar 2019 09:07:27 +0100 Subject: [PATCH 201/393] HV-1702 Upgrade to checkstyle 8.18 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b644e6c761..d9d17597e3 100644 --- a/pom.xml +++ b/pom.xml @@ -184,7 +184,7 @@ overridden by a CI job of the Checkstyle project so that they can check for regressions. Which is obviously good for us, too. --> - 8.1 + 8.18 From 33983deeeeffc285504c40dfdf75730b31e61a84 Mon Sep 17 00:00:00 2001 From: Martin Simka Date: Tue, 19 Mar 2019 16:26:07 +0100 Subject: [PATCH 202/393] HV-1704 Use a file URI also valid for Windows --- modules/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/pom.xml b/modules/pom.xml index b9eacc9ca4..6ca85e82c6 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -127,7 +127,7 @@ - + ${wildfly-main.patched.target-dir} @@ -143,7 +143,7 @@ - + ${wildfly-secondary.patched.target-dir} From 6afd1c2470e30104d5ae482c4744251e2c2e32b2 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 20 Mar 2019 16:25:22 +0100 Subject: [PATCH 203/393] HV-1705 Upgrade WildFly to 16.0.0.Final --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index d9d17597e3..f5d03aa7fb 100644 --- a/pom.xml +++ b/pom.xml @@ -122,9 +122,9 @@ 2.1.0.Final - 15.0.0.Final + 16.0.0.Final - 14.0.1.Final + 15.0.1.Final ${version.wildfly} From 043a40591c3fc6dd2dacd23c943a863515333311 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Fri, 22 Mar 2019 11:02:42 +0000 Subject: [PATCH 204/393] [Jenkins release job] README.md updated by release build 6.1.0.Alpha4 --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f98e0fc64b..fec61dd66a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hibernate Validator -*Version: 6.1.0.Alpha3 - 18-02-2019* +*Version: 6.1.0.Alpha4 - 22-03-2019* ## What is it? @@ -35,7 +35,7 @@ Logging will delegate any log requests to that provider. org.hibernate.validator hibernate-validator - 6.1.0.Alpha3 + 6.1.0.Alpha4 You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. @@ -54,7 +54,7 @@ extension by adding the following dependency: org.hibernate.validator hibernate-validator-cdi - 6.1.0.Alpha3 + 6.1.0.Alpha4 * _hibernate-validator-annotation-processor-<version>.jar_ is an optional jar which can be integrated with your build From 080e853a892e9a1034d7f623ae0411043cce4138 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Fri, 22 Mar 2019 11:02:42 +0000 Subject: [PATCH 205/393] [Jenkins release job] changelog.txt updated by release build 6.1.0.Alpha4 --- changelog.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/changelog.txt b/changelog.txt index 08c8188939..5c6953de6f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,26 @@ Hibernate Validator Changelog ============================= +6.1.0.Alpha4 (22-03-2019) +------------------------- + +** Bug + * HV-1704 - build - Build fails on Windows + * HV-1699 - validators - Rounding error when having a BigDecimal at runtime with @Max/@Min annotation set on a Number field + +** Improvement + * HV-1701 - - Add Max/MinValidatorForInteger + * HV-1700 - tests - Remove reference of absent valueextractor from test resources + * HV-1697 - engine - Reduce memory allocation of ValidationContexts + * HV-1696 - engine - Avoid using computeIfAbsent for the common case when getting bean metadata + * HV-1695 - engine - Avoid creating an empty map for group conversions + * HV-1694 - engine - Reduce memory allocation for unconstrained beans + +** Task + * HV-1705 - build - Upgrade WildFly to 16.0.0.Final + * HV-1702 - build - Upgrade to checkstyle 8.18 and maven-checkstyle-plugin 3.0.0 + * HV-1693 - build - Test compatibility with JDK 12 + 6.1.0.Alpha3 (18-02-2019) ------------------------- From 72b6bd7a05544f7bb959eb1b19188bebd326d9d8 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Fri, 22 Mar 2019 11:02:50 +0000 Subject: [PATCH 206/393] [Jenkins release job] Preparing release 6.1.0.Alpha4 --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 6b70540803..7f265546ac 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 021058c8f5..e8ad0ac023 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index 64d7dc2320..c0731f5ba7 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index 480f2c2cb6..421c393d68 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 76e5181564..88543b05ac 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index 5fd0209f0b..5da884d76f 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 85364bd54c..24654443fd 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index 6ca85e82c6..af520dd94e 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 55c15d1c8c..dbe1e16698 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 28ce4576ea..3f506e74e8 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 1b9ec9f304..2406024ea5 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index fc4f7e3a85..f3959ff85c 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index 272ffbee1b..bb0b2409c3 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 ../pom.xml diff --git a/pom.xml b/pom.xml index f5d03aa7fb..96ce7fade1 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 3f99228d35..1ea712882d 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index acc9a54560..045bb03cb4 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index d793ee6b6e..627f24e645 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index c2eba20d47..c8a9c37c4a 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 6516654b3f..77ded6078c 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 469ad132ed..326ea0961f 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 3b0766e5c7..a05de793dd 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha4 hibernate-validator-test-utils From 68c0a706a7bdfb36a5ff70336fe4ee709b558e3d Mon Sep 17 00:00:00 2001 From: Jenkins Date: Fri, 22 Mar 2019 11:06:21 +0000 Subject: [PATCH 207/393] [Jenkins release job] Preparing next development iteration --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 7f265546ac..6b70540803 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index e8ad0ac023..021058c8f5 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index c0731f5ba7..64d7dc2320 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index 421c393d68..480f2c2cb6 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 88543b05ac..76e5181564 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index 5da884d76f..5fd0209f0b 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 24654443fd..85364bd54c 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index af520dd94e..6ca85e82c6 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index dbe1e16698..55c15d1c8c 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 3f506e74e8..28ce4576ea 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 2406024ea5..1b9ec9f304 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index f3959ff85c..fc4f7e3a85 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index bb0b2409c3..272ffbee1b 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 96ce7fade1..f5d03aa7fb 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 1ea712882d..3f99228d35 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index 045bb03cb4..acc9a54560 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index 627f24e645..d793ee6b6e 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index c8a9c37c4a..c2eba20d47 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 77ded6078c..6516654b3f 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 326ea0961f..469ad132ed 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index a05de793dd..3b0766e5c7 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha4 + 6.1.0-SNAPSHOT hibernate-validator-test-utils From b544643d218bf4cc7c43647b3717f36e5f3e54aa Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 22 Mar 2019 12:27:04 +0100 Subject: [PATCH 208/393] Update reference versions used by the performance tests --- performance/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/performance/pom.xml b/performance/pom.xml index 272ffbee1b..847461dfe5 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -203,7 +203,7 @@ Hibernate Validator - 6.1.0.Alpha3 + 6.1.0.Alpha4 @@ -244,7 +244,7 @@ Hibernate Validator - 6.0.15.Final + 6.0.16.Final From b173247ab36545b90f2bf64a3838f39f4aab2eb1 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Sun, 31 Mar 2019 17:22:32 +0200 Subject: [PATCH 209/393] HV-1706 Update the check algorithms for ISBN10/ISBN13 - To be able to correctly handle the 0 checksum cases instead of determining a check digit a whole sum is calculated and then its modulo is compared to 0. --- .../hv/ISBNValidator.java | 13 +- .../hv/ISBNValidatorTest.java | 200 ++++++++++++++++++ 2 files changed, 207 insertions(+), 6 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/ISBNValidator.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/ISBNValidator.java index 5d107e388c..6508215d5d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/ISBNValidator.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/ISBNValidator.java @@ -68,10 +68,11 @@ public boolean isValid(CharSequence isbn, ConstraintValidatorContext context) { private boolean checkChecksumISBN10(String isbn) { int sum = 0; for ( int i = 0; i < isbn.length() - 1; i++ ) { - sum += ( isbn.charAt( i ) - '0' ) * ( i + 1 ); + sum += ( isbn.charAt( i ) - '0' ) * ( 10 - i ); } - char checkSum = isbn.charAt( 9 ); - return sum % 11 == ( checkSum == 'X' ? 10 : checkSum - '0' ); + sum += isbn.charAt( 9 ) == 'X' ? 10 : isbn.charAt( 9 ) - '0'; + + return ( sum % 11 ) == 0; } /** @@ -80,10 +81,10 @@ private boolean checkChecksumISBN10(String isbn) { */ private boolean checkChecksumISBN13(String isbn) { int sum = 0; - for ( int i = 0; i < isbn.length() - 1; i++ ) { + for ( int i = 0; i < isbn.length(); i++ ) { sum += ( isbn.charAt( i ) - '0' ) * ( i % 2 == 0 ? 1 : 3 ); } - char checkSum = isbn.charAt( 12 ); - return 10 - sum % 10 == ( checkSum - '0' ); + + return ( sum % 10 ) == 0; } } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/ISBNValidatorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/ISBNValidatorTest.java index fd12559568..1dc7ee3cd2 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/ISBNValidatorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/ISBNValidatorTest.java @@ -57,6 +57,106 @@ public void validISBN10() throws Exception { assertValidISBN( "0-85131-041-9" ); assertValidISBN( "0-684-84328-5" ); assertValidISBN( "1-84356-028-3" ); + assertValidISBN( "3-598-21500-2" ); + assertValidISBN( "3-598-21501-0" ); + assertValidISBN( "3-598-21502-9" ); + assertValidISBN( "3-598-21503-7" ); + assertValidISBN( "3-598-21504-5" ); + assertValidISBN( "3-598-21505-3" ); + assertValidISBN( "3-598-21506-1" ); + assertValidISBN( "3-598-21507-X" ); + assertValidISBN( "3-598-21508-8" ); + assertValidISBN( "3-598-21509-6" ); + assertValidISBN( "3-598-21510-X" ); + assertValidISBN( "3-598-21511-8" ); + assertValidISBN( "3-598-21512-6" ); + assertValidISBN( "3-598-21513-4" ); + assertValidISBN( "3-598-21514-2" ); + assertValidISBN( "3-598-21515-0" ); + assertValidISBN( "3-598-21516-9" ); + assertValidISBN( "3-598-21517-7" ); + assertValidISBN( "3-598-21518-5" ); + assertValidISBN( "3-598-21519-3" ); + assertValidISBN( "3-598-21520-7" ); + assertValidISBN( "3-598-21521-5" ); + assertValidISBN( "3-598-21522-3" ); + assertValidISBN( "3-598-21523-1" ); + assertValidISBN( "3-598-21524-X" ); + assertValidISBN( "3-598-21525-8" ); + assertValidISBN( "3-598-21526-6" ); + assertValidISBN( "3-598-21527-4" ); + assertValidISBN( "3-598-21528-2" ); + assertValidISBN( "3-598-21529-0" ); + assertValidISBN( "3-598-21530-4" ); + assertValidISBN( "3-598-21531-2" ); + assertValidISBN( "3-598-21532-0" ); + assertValidISBN( "3-598-21533-9" ); + assertValidISBN( "3-598-21534-7" ); + assertValidISBN( "3-598-21535-5" ); + assertValidISBN( "3-598-21536-3" ); + assertValidISBN( "3-598-21537-1" ); + assertValidISBN( "3-598-21538-X" ); + assertValidISBN( "3-598-21539-8" ); + assertValidISBN( "3-598-21540-1" ); + assertValidISBN( "3-598-21541-X" ); + assertValidISBN( "3-598-21542-8" ); + assertValidISBN( "3-598-21543-6" ); + assertValidISBN( "3-598-21544-4" ); + assertValidISBN( "3-598-21545-2" ); + assertValidISBN( "3-598-21546-0" ); + assertValidISBN( "3-598-21547-9" ); + assertValidISBN( "3-598-21548-7" ); + assertValidISBN( "3-598-21549-5" ); + assertValidISBN( "3-598-21550-9" ); + assertValidISBN( "3-598-21551-7" ); + assertValidISBN( "3-598-21552-5" ); + assertValidISBN( "3-598-21553-3" ); + assertValidISBN( "3-598-21554-1" ); + assertValidISBN( "3-598-21555-X" ); + assertValidISBN( "3-598-21556-8" ); + assertValidISBN( "3-598-21557-6" ); + assertValidISBN( "3-598-21558-4" ); + assertValidISBN( "3-598-21559-2" ); + assertValidISBN( "3-598-21560-6" ); + assertValidISBN( "3-598-21561-4" ); + assertValidISBN( "3-598-21562-2" ); + assertValidISBN( "3-598-21563-0" ); + assertValidISBN( "3-598-21564-9" ); + assertValidISBN( "3-598-21565-7" ); + assertValidISBN( "3-598-21566-5" ); + assertValidISBN( "3-598-21567-3" ); + assertValidISBN( "3-598-21568-1" ); + assertValidISBN( "3-598-21569-X" ); + assertValidISBN( "3-598-21570-3" ); + assertValidISBN( "3-598-21571-1" ); + assertValidISBN( "3-598-21572-X" ); + assertValidISBN( "3-598-21573-8" ); + assertValidISBN( "3-598-21574-6" ); + assertValidISBN( "3-598-21575-4" ); + assertValidISBN( "3-598-21576-2" ); + assertValidISBN( "3-598-21577-0" ); + assertValidISBN( "3-598-21578-9" ); + assertValidISBN( "3-598-21579-7" ); + assertValidISBN( "3-598-21580-0" ); + assertValidISBN( "3-598-21581-9" ); + assertValidISBN( "3-598-21582-7" ); + assertValidISBN( "3-598-21583-5" ); + assertValidISBN( "3-598-21584-3" ); + assertValidISBN( "3-598-21585-1" ); + assertValidISBN( "3-598-21586-X" ); + assertValidISBN( "3-598-21587-8" ); + assertValidISBN( "3-598-21588-6" ); + assertValidISBN( "3-598-21589-4" ); + assertValidISBN( "3-598-21590-8" ); + assertValidISBN( "3-598-21591-6" ); + assertValidISBN( "3-598-21592-4" ); + assertValidISBN( "3-598-21593-2" ); + assertValidISBN( "3-598-21594-0" ); + assertValidISBN( "3-598-21595-9" ); + assertValidISBN( "3-598-21596-7" ); + assertValidISBN( "3-598-21597-5" ); + assertValidISBN( "3-598-21598-3" ); + assertValidISBN( "3-598-21599-1" ); } @Test @@ -93,6 +193,106 @@ public void validISBN13() throws Exception { assertValidISBN( "978-0-684-84328-5" ); assertValidISBN( "978-1-84356-028-9" ); assertValidISBN( "978-0-54560-495-6" ); + assertValidISBN( "978-3-598-21500-1" ); + assertValidISBN( "978-3-598-21501-8" ); + assertValidISBN( "978-3-598-21502-5" ); + assertValidISBN( "978-3-598-21503-2" ); + assertValidISBN( "978-3-598-21504-9" ); + assertValidISBN( "978-3-598-21505-6" ); + assertValidISBN( "978-3-598-21506-3" ); + assertValidISBN( "978-3-598-21507-0" ); + assertValidISBN( "978-3-598-21508-7" ); + assertValidISBN( "978-3-598-21509-4" ); + assertValidISBN( "978-3-598-21510-0" ); + assertValidISBN( "978-3-598-21511-7" ); + assertValidISBN( "978-3-598-21512-4" ); + assertValidISBN( "978-3-598-21513-1" ); + assertValidISBN( "978-3-598-21514-8" ); + assertValidISBN( "978-3-598-21515-5" ); + assertValidISBN( "978-3-598-21516-2" ); + assertValidISBN( "978-3-598-21517-9" ); + assertValidISBN( "978-3-598-21518-6" ); + assertValidISBN( "978-3-598-21519-3" ); + assertValidISBN( "978-3-598-21520-9" ); + assertValidISBN( "978-3-598-21521-6" ); + assertValidISBN( "978-3-598-21522-3" ); + assertValidISBN( "978-3-598-21523-0" ); + assertValidISBN( "978-3-598-21524-7" ); + assertValidISBN( "978-3-598-21525-4" ); + assertValidISBN( "978-3-598-21526-1" ); + assertValidISBN( "978-3-598-21527-8" ); + assertValidISBN( "978-3-598-21528-5" ); + assertValidISBN( "978-3-598-21529-2" ); + assertValidISBN( "978-3-598-21530-8" ); + assertValidISBN( "978-3-598-21531-5" ); + assertValidISBN( "978-3-598-21532-2" ); + assertValidISBN( "978-3-598-21533-9" ); + assertValidISBN( "978-3-598-21534-6" ); + assertValidISBN( "978-3-598-21535-3" ); + assertValidISBN( "978-3-598-21536-0" ); + assertValidISBN( "978-3-598-21537-7" ); + assertValidISBN( "978-3-598-21538-4" ); + assertValidISBN( "978-3-598-21539-1" ); + assertValidISBN( "978-3-598-21540-7" ); + assertValidISBN( "978-3-598-21541-4" ); + assertValidISBN( "978-3-598-21542-1" ); + assertValidISBN( "978-3-598-21543-8" ); + assertValidISBN( "978-3-598-21544-5" ); + assertValidISBN( "978-3-598-21545-2" ); + assertValidISBN( "978-3-598-21546-9" ); + assertValidISBN( "978-3-598-21547-6" ); + assertValidISBN( "978-3-598-21548-3" ); + assertValidISBN( "978-3-598-21549-0" ); + assertValidISBN( "978-3-598-21550-6" ); + assertValidISBN( "978-3-598-21551-3" ); + assertValidISBN( "978-3-598-21552-0" ); + assertValidISBN( "978-3-598-21553-7" ); + assertValidISBN( "978-3-598-21554-4" ); + assertValidISBN( "978-3-598-21555-1" ); + assertValidISBN( "978-3-598-21556-8" ); + assertValidISBN( "978-3-598-21557-5" ); + assertValidISBN( "978-3-598-21558-2" ); + assertValidISBN( "978-3-598-21559-9" ); + assertValidISBN( "978-3-598-21560-5" ); + assertValidISBN( "978-3-598-21561-2" ); + assertValidISBN( "978-3-598-21562-9" ); + assertValidISBN( "978-3-598-21563-6" ); + assertValidISBN( "978-3-598-21564-3" ); + assertValidISBN( "978-3-598-21565-0" ); + assertValidISBN( "978-3-598-21566-7" ); + assertValidISBN( "978-3-598-21567-4" ); + assertValidISBN( "978-3-598-21568-1" ); + assertValidISBN( "978-3-598-21569-8" ); + assertValidISBN( "978-3-598-21570-4" ); + assertValidISBN( "978-3-598-21571-1" ); + assertValidISBN( "978-3-598-21572-8" ); + assertValidISBN( "978-3-598-21573-5" ); + assertValidISBN( "978-3-598-21574-2" ); + assertValidISBN( "978-3-598-21575-9" ); + assertValidISBN( "978-3-598-21576-6" ); + assertValidISBN( "978-3-598-21577-3" ); + assertValidISBN( "978-3-598-21578-0" ); + assertValidISBN( "978-3-598-21579-7" ); + assertValidISBN( "978-3-598-21580-3" ); + assertValidISBN( "978-3-598-21581-0" ); + assertValidISBN( "978-3-598-21582-7" ); + assertValidISBN( "978-3-598-21583-4" ); + assertValidISBN( "978-3-598-21584-1" ); + assertValidISBN( "978-3-598-21585-8" ); + assertValidISBN( "978-3-598-21586-5" ); + assertValidISBN( "978-3-598-21587-2" ); + assertValidISBN( "978-3-598-21588-9" ); + assertValidISBN( "978-3-598-21589-6" ); + assertValidISBN( "978-3-598-21590-2" ); + assertValidISBN( "978-3-598-21591-9" ); + assertValidISBN( "978-3-598-21592-6" ); + assertValidISBN( "978-3-598-21593-3" ); + assertValidISBN( "978-3-598-21594-0" ); + assertValidISBN( "978-3-598-21595-7" ); + assertValidISBN( "978-3-598-21596-4" ); + assertValidISBN( "978-3-598-21597-1" ); + assertValidISBN( "978-3-598-21598-8" ); + assertValidISBN( "978-3-598-21599-5" ); } @Test From bc53b66442e2c27b948e5409d41e56cd057d0c5d Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Tue, 23 Apr 2019 13:58:53 +0200 Subject: [PATCH 210/393] HV-1707 Add ISBN.Type.ANY this new type allows to validate values that are either ISBN10 or ISBN13 --- .../hibernate/validator/constraints/ISBN.java | 6 +- .../hv/ISBNValidator.java | 124 +++++++++++++----- .../hv/ISBNValidatorTest.java | 36 +++++ 3 files changed, 129 insertions(+), 37 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/constraints/ISBN.java b/engine/src/main/java/org/hibernate/validator/constraints/ISBN.java index cbce289f99..fec95f5622 100644 --- a/engine/src/main/java/org/hibernate/validator/constraints/ISBN.java +++ b/engine/src/main/java/org/hibernate/validator/constraints/ISBN.java @@ -67,9 +67,13 @@ /** * Defines the ISBN length. Valid lengths of ISBNs are {@code 10} and {@code 13} * which are represented as {@link Type#ISBN_10} and {@link Type#ISBN_13} respectively. + *

+ * Using {@link Type#ANY} allows to validate values that could either be ISBN10 or ISBN13. + * In such case, ISBN type would be determined by the length of the corresponding value. */ enum Type { ISBN_10, - ISBN_13 + ISBN_13, + ANY } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/ISBNValidator.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/ISBNValidator.java index 6508215d5d..db104faadf 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/ISBNValidator.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/ISBNValidator.java @@ -6,13 +6,13 @@ */ package org.hibernate.validator.internal.constraintvalidators.hv; -import java.util.function.Function; import java.util.regex.Pattern; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import org.hibernate.validator.constraints.ISBN; +import org.hibernate.validator.internal.util.Contracts; /** * Checks that a given character sequence (e.g. string) is a valid ISBN. @@ -26,22 +26,11 @@ public class ISBNValidator implements ConstraintValidator { */ private static Pattern NOT_DIGITS_OR_NOT_X = Pattern.compile( "[^\\dX]" ); - private int length; - - private Function checkChecksumFunction; + private ISBNValidationAlgorithm isbnValidationAlgorithm; @Override public void initialize(ISBN constraintAnnotation) { - switch ( constraintAnnotation.type() ) { - case ISBN_10: - length = 10; - checkChecksumFunction = this::checkChecksumISBN10; - break; - case ISBN_13: - length = 13; - checkChecksumFunction = this::checkChecksumISBN13; - break; - } + this.isbnValidationAlgorithm = ISBNValidationAlgorithm.from( constraintAnnotation.type() ); } @Override @@ -54,37 +43,100 @@ public boolean isValid(CharSequence isbn, ConstraintValidatorContext context) { String digits = NOT_DIGITS_OR_NOT_X.matcher( isbn ).replaceAll( "" ); // Check if the length of resulting string matches the expecting one - if ( digits.length() != length ) { + if ( !isbnValidationAlgorithm.isValidLength( digits.length() ) ) { return false; } - return checkChecksumFunction.apply( digits ); + return isbnValidationAlgorithm.isValidChecksum( digits ); } - /** - * Check the digits for ISBN 10 using algorithm from - * Wikipedia. - */ - private boolean checkChecksumISBN10(String isbn) { - int sum = 0; - for ( int i = 0; i < isbn.length() - 1; i++ ) { - sum += ( isbn.charAt( i ) - '0' ) * ( 10 - i ); + private interface ISBNValidationAlgorithm { + boolean isValidLength(int length); + + boolean isValidChecksum(String isbn); + + static ISBNValidationAlgorithmImpl from(ISBN.Type type) { + Contracts.assertNotNull( type ); + switch ( type ) { + case ISBN_10: + return ISBNValidationAlgorithmImpl.ISBN_10; + case ISBN_13: + return ISBNValidationAlgorithmImpl.ISBN_13; + case ANY: + default: + return ISBNValidationAlgorithmImpl.ANY; + } } - sum += isbn.charAt( 9 ) == 'X' ? 10 : isbn.charAt( 9 ) - '0'; - - return ( sum % 11 ) == 0; } - /** - * Check the digits for ISBN 13 using algorithm from - * Wikipedia. - */ - private boolean checkChecksumISBN13(String isbn) { - int sum = 0; - for ( int i = 0; i < isbn.length(); i++ ) { - sum += ( isbn.charAt( i ) - '0' ) * ( i % 2 == 0 ? 1 : 3 ); + private enum ISBNValidationAlgorithmImpl implements ISBNValidationAlgorithm { + + ISBN_10 { + @Override + public boolean isValidChecksum(String isbn) { + return checkChecksumISBN10( isbn ); + } + + @Override + public boolean isValidLength(int length) { + return 10 == length; + } + }, + ISBN_13 { + @Override + public boolean isValidChecksum(String isbn) { + return checkChecksumISBN13( isbn ); + } + + @Override + public boolean isValidLength(int length) { + return 13 == length; + } + }, + ANY { + @Override + public boolean isValidLength(int length) { + return 10 == length || 13 == length; + } + + @Override + public boolean isValidChecksum(String isbn) { + int length = isbn.length(); + if ( length == 10 ) { + return checkChecksumISBN10( isbn ); + } + else if ( length == 13 ) { + return checkChecksumISBN13( isbn ); + } + throw new IllegalStateException( "Invalid/unsupported isbn value length" ); + } + }; + + /** + * Check the digits for ISBN 10 using algorithm from + * Wikipedia. + */ + private static boolean checkChecksumISBN10(String isbn) { + int sum = 0; + for ( int i = 0; i < isbn.length() - 1; i++ ) { + sum += ( isbn.charAt( i ) - '0' ) * ( 10 - i ); + } + sum += isbn.charAt( 9 ) == 'X' ? 10 : isbn.charAt( 9 ) - '0'; + + return ( sum % 11 ) == 0; } - return ( sum % 10 ) == 0; + /** + * Check the digits for ISBN 13 using algorithm from + * Wikipedia. + */ + private static boolean checkChecksumISBN13(String isbn) { + int sum = 0; + for ( int i = 0; i < isbn.length(); i++ ) { + sum += ( isbn.charAt( i ) - '0' ) * ( i % 2 == 0 ? 1 : 3 ); + } + + return ( sum % 10 ) == 0; + } } } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/ISBNValidatorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/ISBNValidatorTest.java index 1dc7ee3cd2..db29324f83 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/ISBNValidatorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/ISBNValidatorTest.java @@ -25,6 +25,7 @@ import org.hibernate.validator.constraints.ISBN; import org.hibernate.validator.internal.constraintvalidators.hv.ISBNValidator; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; +import org.hibernate.validator.testutil.TestForIssue; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -316,6 +317,41 @@ public void invalidISBN13() throws Exception { assertInvalidISBN( "978-0-55555555555555" ); } + @Test + @TestForIssue( jiraKey = "HV-1707") + public void testValidISBNAny() { + validator.initialize( initializeAnnotation( ISBN.Type.ANY ) ); + + assertValidISBN( null ); + // ISBN10 + assertValidISBN( "99921-58-10-7" ); + assertValidISBN( "9971-5-0210-0" ); + assertValidISBN( "960-425-059-0" ); + assertValidISBN( "80-902734-1-6" ); + assertValidISBN( "0-9752298-0-X" ); + + // ISBN13 + assertValidISBN( "978-123-456-789-7" ); + assertValidISBN( "978-91-983989-1-5" ); + assertValidISBN( "978-988-785-411-1" ); + assertValidISBN( "978-1-56619-909-4" ); + assertValidISBN( "978-1-4028-9462-6" ); + assertValidISBN( "978-0-85131-041-1" ); + + // invalid cases + assertInvalidISBN( "978-0-85131-041-0" ); + assertInvalidISBN( "80-902734-1-8" ); + assertInvalidISBN( "978-0-85131-0401-0" ); + assertInvalidISBN( "80-902734-10-8" ); + + // incorrect length: + assertInvalidISBN( "978-0-85" ); + assertInvalidISBN( "80-902734-1-877777" ); + assertInvalidISBN( "978-0-85131-0401-00074" ); + assertInvalidISBN( "80-902734-1" ); + + } + @Test public void testProgrammaticDefinition() throws Exception { HibernateValidatorConfiguration config = getConfiguration( HibernateValidator.class ); From 9c0958e08bf33b9da697a45442498d8418f50d70 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 14 May 2019 13:26:26 +0200 Subject: [PATCH 211/393] HV-1711 Fix aggregated javadoc build with recent JDK 11 Related to https://bugs.openjdk.java.net/browse/JDK-8212233 --- distribution/pom.xml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/distribution/pom.xml b/distribution/pom.xml index 480f2c2cb6..d79df95eec 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -211,19 +211,13 @@ - jdk12+ + jdk11+ - [12,) + [11,) -html5 -source 8 - - - jdk11+ - - [11,) - org.openjfx From c9f7a0b59d4934ef03cb88d020845e654f8aa0bf Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 14 May 2019 13:30:38 +0200 Subject: [PATCH 212/393] HV-1712 Add org.hibernate.validator.metadata to OSGi manifest --- engine/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/engine/pom.xml b/engine/pom.xml index 5fd0209f0b..36cf16db0b 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -230,6 +230,7 @@ org.hibernate.validator.engine.*;version="${project.version}", org.hibernate.validator.group;version="${project.version}", org.hibernate.validator.messageinterpolation;version="${project.version}", + org.hibernate.validator.metadata;version="${project.version}", org.hibernate.validator.parameternameprovider;version="${project.version}", org.hibernate.validator.path;version="${project.version}", org.hibernate.validator.resourceloading;version="${project.version}", From 0974534ff1a56e9082106f6912fe0ad046177d1b Mon Sep 17 00:00:00 2001 From: Damir Alibegovic Date: Wed, 26 Dec 2018 18:06:07 +0100 Subject: [PATCH 213/393] HV-823 Provide contract for customization of property names in constraint violation Added PropertyNodeNameProvider SPI with Property and JavaBeanProperty as supporting interfaces. This SPI lives in JavaBeanHelper and is used to get the name when creating JavaBeanField and JavaBeanGetter, so when a property path is constructed, this resolved name is used. If not set, the default implementation will be used that returns the actual name from the class. This new SPI can be configured through HibernateValidatorConfiguration. Testing: - Added tests for configuration - Added a sample implementation by using reflection and custom annotation - Added tests for reflection implementation - Added a sample implementation by using Jackson lib - Added tests for Jackson implementation Added documentation with examples. --- copyright.txt | 1 + documentation/pom.xml | 10 + documentation/src/main/asciidoc/ch12.asciidoc | 95 ++++++- .../JacksonPropertyNodeNameProvider.java | 41 +++ .../JacksonPropertyNodeNameProviderTest.java | 74 ++++++ .../chapter12/nodenameprovider/Person.java | 21 ++ .../PersonSerializationTest.java | 23 ++ .../chapter12/nodenameprovider/clarkKent.json | 4 + engine/pom.xml | 10 + .../BaseHibernateValidatorConfiguration.java | 24 ++ .../engine/AbstractConfigurationImpl.java | 35 ++- .../DefaultPropertyNodeNameProvider.java | 24 ++ .../PredefinedScopeValidatorFactoryImpl.java | 3 +- .../ValidatorFactoryConfigurationHelper.java | 27 ++ .../internal/engine/ValidatorFactoryImpl.java | 3 +- .../AbstractPropertyCascadable.java | 2 +- .../AbstractPropertyConstraintLocation.java | 2 +- .../provider/AnnotationMetaDataProvider.java | 2 +- .../internal/properties/Property.java | 2 + .../properties/javabean/JavaBeanField.java | 9 +- .../properties/javabean/JavaBeanGetter.java | 9 +- .../properties/javabean/JavaBeanHelper.java | 41 ++- .../validator/internal/util/logging/Log.java | 8 + .../config/ValidationBootstrapParameters.java | 10 + .../nodenameprovider/JavaBeanProperty.java | 25 ++ .../spi/nodenameprovider/Property.java | 26 ++ .../PropertyNodeNameProvider.java | 38 +++ .../internal/engine/path/PathImplTest.java | 3 +- .../metadata/BeanMetaDataManagerTest.java | 3 +- .../aggregated/ExecutableMetaDataTest.java | 3 +- .../aggregated/ParameterMetaDataTest.java | 5 +- .../aggregated/PropertyMetaDataTest.java | 3 +- .../metadata/core/MetaConstraintTest.java | 2 +- .../location/ConstraintLocationTest.java | 4 +- .../AnnotationMetaDataProviderTest.java | 5 +- .../AnnotationMetaDataProviderTestBase.java | 3 +- .../TypeAnnotationMetaDataRetrievalTest.java | 3 +- .../internal/xml/MappingXmlParserTest.java | 3 +- .../AnnotationPropertyNodeNameProvider.java | 90 +++++++ .../PropertyNodeNameProviderTest.java | 241 ++++++++++++++++++ ...sonAnnotationPropertyNodeNameProvider.java | 50 ++++ ...nnotationPropertyNodeNameProviderTest.java | 99 +++++++ pom.xml | 13 + 43 files changed, 1070 insertions(+), 29 deletions(-) create mode 100644 documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/JacksonPropertyNodeNameProvider.java create mode 100644 documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/JacksonPropertyNodeNameProviderTest.java create mode 100644 documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/Person.java create mode 100644 documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/PersonSerializationTest.java create mode 100644 documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/clarkKent.json create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/DefaultPropertyNodeNameProvider.java create mode 100644 engine/src/main/java/org/hibernate/validator/spi/nodenameprovider/JavaBeanProperty.java create mode 100644 engine/src/main/java/org/hibernate/validator/spi/nodenameprovider/Property.java create mode 100644 engine/src/main/java/org/hibernate/validator/spi/nodenameprovider/PropertyNodeNameProvider.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/spi/nodenameprovider/AnnotationPropertyNodeNameProvider.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/spi/nodenameprovider/PropertyNodeNameProviderTest.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/spi/nodenameprovider/jackson/JacksonAnnotationPropertyNodeNameProvider.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/spi/nodenameprovider/jackson/JacksonAnnotationPropertyNodeNameProviderTest.java diff --git a/copyright.txt b/copyright.txt index b6afa3d003..7a27c32024 100644 --- a/copyright.txt +++ b/copyright.txt @@ -11,6 +11,7 @@ Carlo de Wolf Chris Beckey Christian Ivan Dag Hovland +Damir Alibegovic Davide D'Alto Davide Marchignoli Denis Tiago diff --git a/documentation/pom.xml b/documentation/pom.xml index 76e5181564..76e9e2b194 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -103,6 +103,16 @@ javax.annotation-api test + + com.fasterxml.jackson.core + jackson-databind + test + + + com.fasterxml.jackson.core + jackson-annotations + test + diff --git a/documentation/src/main/asciidoc/ch12.asciidoc b/documentation/src/main/asciidoc/ch12.asciidoc index 5a7534542c..f75abf82ea 100644 --- a/documentation/src/main/asciidoc/ch12.asciidoc +++ b/documentation/src/main/asciidoc/ch12.asciidoc @@ -51,6 +51,9 @@ Note that when a package is part of the public API this is not necessarily true `org.hibernate.validator.spi.constraintdefinition`:: An SPI for registering additional constraint validators programmatically, see <>. +`org.hibernate.validator.spi.nodenameprovider`:: + An SPI that can be used to alter how the names of properties will be resolved when the property path is constructed. See <>. + [NOTE] ==== The public packages of Hibernate Validator fall into two categories: while the actual API parts are @@ -759,4 +762,94 @@ It is important to mention that in cases where programmatic constraints are adde `HibernateValidatorConfiguration#addMapping(ConstraintMapping)`, adding mappings should always be done after the required getter property selection strategy is configured. Otherwise, the default strategy will be used for the mappings added before defining the strategy. -==== \ No newline at end of file +==== + +[[section-property-node-name-provider]] +==== Changing the way property names are resolved when the property path is constructed + +Imagine that we have a simple data class that has `@NotNull` constraints on some fields: +[[example-person-class]] +.Person data class +==== +[source, JAVA, indent=0] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/Person.java[tags=include] +---- +==== + +This class can be serialized to JSON by using the https://github.com/FasterXML/jackson[Jackson] library: +[[example-person-object-to-json]] +.Serializing Person object to JSON +==== +[source, JAVA, indent=0] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/PersonSerializationTest.java[tags=include] +---- +==== + +As we can see, the object is serialized to: +[[example-person-json]] +.Person as json +==== +[source, indent=0] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/clarkKent.json[] +---- +==== + +Notice how the names of the properties differ. In the Java object, we have `firstName` and `lastName`, whereas in the JSON output, we have +`first_name` and `last_name`. We defined this behaviour through `@JsonProperty` annotations. + +Now imagine, that we use this class in a REST environment, where a user can send <> in the request body. +It would be nice, when telling the user on which field the validation failed, to tell them the name they use in their JSON request, `first_name`, +and not the name we use internally in our Java code, `firstName`. + +The `org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider` contract allows us to do this. By implementing it, +we can define how the name of a property will be resolved during validation. In our case, we want to read the value from the Jackson configuration. + +So, one example of how to do this is to leverage the Jackson API: +[[example-jackson-property-node-name-provider]] +.JacksonPropertyNodeNameProvider implementation +==== +[source, JAVA, indent=0] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/JacksonPropertyNodeNameProvider.java[tags=include] +---- +==== + +And when doing the validation: +[[example-jackson-property-node-name-provider-field]] +.JacksonPropertyNodeNameProvider usage +==== +[source, JAVA, indent=0] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/JacksonPropertyNodeNameProviderTest.java[tags=field] +---- +==== + +We can see that the property path now returns `first_name`. + +Note that this also works when the annotations are on the getter: +[[example-jackson-property-node-name-provider-getter]] +.Annotation on a getter +==== +[source, JAVA, indent=0] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/JacksonPropertyNodeNameProviderTest.java[tags=getter] +---- +==== + +This is just one use case of why we would like to change how the property names are resolved. + +`org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider` can be implemented to provide a property name in +whatever way you see fit (reading from annotations, for instance). + +There are two more interfaces that are worth mentioning: + +- `org.hibernate.validator.spi.nodenameprovider.Property` is a base interface that holds metadata about a property. It +has a single `String getName()` method that can be used to get the "original" name of a property. This interface +should be used as a default way of resolving the name (see how it is used in <>). + +- `org.hibernate.validator.spi.nodenameprovider.JavaBeanProperty` is an interface that holds metada about a bean property. It +extends `org.hibernate.validator.spi.nodenameprovider.Property` and provide some more data like `Class getDeclaringClass()` +which is the class that is the owner of the property. This additional metadata can be useful when revolving the name. diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/JacksonPropertyNodeNameProvider.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/JacksonPropertyNodeNameProvider.java new file mode 100644 index 0000000000..9b876a227b --- /dev/null +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/JacksonPropertyNodeNameProvider.java @@ -0,0 +1,41 @@ +package org.hibernate.validator.referenceguide.chapter12.nodenameprovider; + +//tag::include[] +import org.hibernate.validator.spi.nodenameprovider.JavaBeanProperty; +import org.hibernate.validator.spi.nodenameprovider.Property; +import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider; + +import com.fasterxml.jackson.databind.BeanDescription; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; + +public class JacksonPropertyNodeNameProvider implements PropertyNodeNameProvider { + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public String getName(Property property) { + if ( property instanceof JavaBeanProperty ) { + return getJavaBeanPropertyName( (JavaBeanProperty) property ); + } + + return getDefaultName( property ); + } + + private String getJavaBeanPropertyName(JavaBeanProperty property) { + JavaType type = objectMapper.constructType( property.getDeclaringClass() ); + BeanDescription desc = objectMapper.getSerializationConfig().introspect( type ); + + return desc.findProperties() + .stream() + .filter( prop -> prop.getInternalName().equals( property.getName() ) ) + .map( BeanPropertyDefinition::getName ) + .findFirst() + .orElse( property.getName() ); + } + + private String getDefaultName(Property property) { + return property.getName(); + } +} +//end::include[] diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/JacksonPropertyNodeNameProviderTest.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/JacksonPropertyNodeNameProviderTest.java new file mode 100644 index 0000000000..fe298f8f51 --- /dev/null +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/JacksonPropertyNodeNameProviderTest.java @@ -0,0 +1,74 @@ +package org.hibernate.validator.referenceguide.chapter12.nodenameprovider; + +import static org.junit.Assert.assertEquals; + +import java.util.Set; +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.HibernateValidator; + +import org.junit.Test; + +import com.fasterxml.jackson.annotation.JsonProperty; + +//tag::field[] +public class JacksonPropertyNodeNameProviderTest { + @Test + public void nameIsReadFromJacksonAnnotationOnField() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .propertyNodeNameProvider( new JacksonPropertyNodeNameProvider() ) + .buildValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + + Person clarkKent = new Person( null, "Kent" ); + + Set> violations = validator.validate( clarkKent ); + ConstraintViolation violation = violations.iterator().next(); + + assertEquals( violation.getPropertyPath().toString(), "first_name" ); + } +//end::field[] + +//tag::getter[] + @Test + public void nameIsReadFromJacksonAnnotationOnGetter() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .propertyNodeNameProvider( new JacksonPropertyNodeNameProvider() ) + .buildValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + + Person clarkKent = new Person( null, "Kent" ); + + Set> violations = validator.validate( clarkKent ); + ConstraintViolation violation = violations.iterator().next(); + + assertEquals( violation.getPropertyPath().toString(), "first_name" ); + } + + public class Person { + private final String firstName; + + @JsonProperty("last_name") + private final String lastName; + + public Person(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + @NotNull + @JsonProperty("first_name") + public String getFirstName() { + return firstName; + } + } +//end::getter[] +} diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/Person.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/Person.java new file mode 100644 index 0000000000..ce2266b79b --- /dev/null +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/Person.java @@ -0,0 +1,21 @@ +package org.hibernate.validator.referenceguide.chapter12.nodenameprovider; + +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonProperty; + +//tag::include[] +public class Person { + @NotNull + @JsonProperty("first_name") + private final String firstName; + + @JsonProperty("last_name") + private final String lastName; + + public Person(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } +} +//end::include[] diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/PersonSerializationTest.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/PersonSerializationTest.java new file mode 100644 index 0000000000..5c64af52b7 --- /dev/null +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/PersonSerializationTest.java @@ -0,0 +1,23 @@ +package org.hibernate.validator.referenceguide.chapter12.nodenameprovider; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +//tag::include[] +public class PersonSerializationTest { + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void personIsSerialized() throws JsonProcessingException { + Person person = new Person( "Clark", "Kent" ); + + String serializedPerson = objectMapper.writeValueAsString( person ); + + assertEquals( "{\"first_name\":\"Clark\",\"last_name\":\"Kent\"}", serializedPerson ); + } +} +//tag::include[] diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/clarkKent.json b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/clarkKent.json new file mode 100644 index 0000000000..dd8aa9b129 --- /dev/null +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/nodenameprovider/clarkKent.json @@ -0,0 +1,4 @@ +{ + "first_name": "Clark", + "last_name": "Kent" +} diff --git a/engine/pom.xml b/engine/pom.xml index 36cf16db0b..f371e3562c 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -147,6 +147,16 @@ moneta test + + com.fasterxml.jackson.core + jackson-databind + test + + + com.fasterxml.jackson.core + jackson-annotations + test + diff --git a/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java index 921ab2db44..b3347414aa 100644 --- a/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java @@ -10,6 +10,7 @@ import java.util.Set; import javax.validation.Configuration; +import javax.validation.ConstraintViolation; import javax.validation.TraversableResolver; import javax.validation.constraints.Future; import javax.validation.constraints.FutureOrPresent; @@ -20,6 +21,7 @@ import org.hibernate.validator.cfg.ConstraintMapping; import org.hibernate.validator.constraints.ParameterScriptAssert; import org.hibernate.validator.constraints.ScriptAssert; +import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider; import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; import org.hibernate.validator.spi.scripting.ScriptEvaluator; @@ -119,6 +121,15 @@ public interface BaseHibernateValidatorConfiguration * Returns the {@link ResourceBundleLocator} used by the @@ -336,4 +347,17 @@ public interface BaseHibernateValidatorConfiguration extractor) { Contracts.assertNotNull( extractor, MESSAGES.parameterMustNotBeNull( "extractor" ) ); @@ -327,7 +343,7 @@ public final DefaultConstraintMapping createConstraintMapping() { getterPropertySelectionStrategyToUse = getterPropertySelectionStrategy; } - return new DefaultConstraintMapping( new JavaBeanHelper( getterPropertySelectionStrategyToUse ) ); + return new DefaultConstraintMapping( new JavaBeanHelper( getterPropertySelectionStrategyToUse, defaultPropertyNodeNameProvider ) ); } @Override @@ -461,6 +477,10 @@ public ClockProvider getClockProvider() { return validationBootstrapParameters.getClockProvider(); } + public PropertyNodeNameProvider getPropertyNodeNameProvider() { + return validationBootstrapParameters.getPropertyNodeNameProvider(); + } + public ScriptEvaluatorFactory getScriptEvaluatorFactory() { return scriptEvaluatorFactory; } @@ -566,6 +586,9 @@ private void parseValidationXml() { if ( validationBootstrapParameters.getClockProvider() == null ) { validationBootstrapParameters.setClockProvider( defaultClockProvider ); } + if ( validationBootstrapParameters.getPropertyNodeNameProvider() == null ) { + validationBootstrapParameters.setPropertyNodeNameProvider( defaultPropertyNodeNameProvider ); + } } else { ValidationBootstrapParameters xmlParameters = new ValidationBootstrapParameters( @@ -634,6 +657,16 @@ private void applyXmlSettings(ValidationBootstrapParameters xmlParameters) { } } + if ( validationBootstrapParameters.getPropertyNodeNameProvider() == null ) { + if ( xmlParameters.getPropertyNodeNameProvider() != null ) { + validationBootstrapParameters.setPropertyNodeNameProvider( + xmlParameters.getPropertyNodeNameProvider() ); + } + else { + validationBootstrapParameters.setPropertyNodeNameProvider( defaultPropertyNodeNameProvider ); + } + } + for ( ValueExtractorDescriptor valueExtractorDescriptor : xmlParameters.getValueExtractorDescriptors().values() ) { validationBootstrapParameters.addValueExtractorDescriptor( valueExtractorDescriptor ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/DefaultPropertyNodeNameProvider.java b/engine/src/main/java/org/hibernate/validator/internal/engine/DefaultPropertyNodeNameProvider.java new file mode 100644 index 0000000000..d7dc7d74ab --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/DefaultPropertyNodeNameProvider.java @@ -0,0 +1,24 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine; + +import java.io.Serializable; + +import org.hibernate.validator.spi.nodenameprovider.Property; +import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider; + +/** + * A default {@link PropertyNodeNameProvider} implementation which returns the property name. + * + * @author Damir Alibegovic + */ +public class DefaultPropertyNodeNameProvider implements PropertyNodeNameProvider, Serializable { + @Override + public String getName(Property property) { + return property.getName(); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java index f41dff6f2a..fc2a1f61be 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java @@ -139,7 +139,8 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState constraintValidatorManager, typeResolutionHelper, valueExtractorManager ); ExecutableHelper executableHelper = new ExecutableHelper( typeResolutionHelper ); - JavaBeanHelper javaBeanHelper = new JavaBeanHelper( ValidatorFactoryConfigurationHelper.determineGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ) ); + JavaBeanHelper javaBeanHelper = new JavaBeanHelper( ValidatorFactoryConfigurationHelper.determineGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ), + ValidatorFactoryConfigurationHelper.determinePropertyNodeNameProvider( hibernateSpecificConfig, properties, externalClassLoader ) ); // HV-302; don't load XmlMappingParser if not necessary XmlMetaDataProvider xmlMetaDataProvider; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java index 8f449f3633..b480020202 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java @@ -39,6 +39,7 @@ import org.hibernate.validator.internal.util.privilegedactions.NewInstance; import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; import org.hibernate.validator.spi.cfg.ConstraintMappingContributor; +import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider; import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; @@ -289,6 +290,32 @@ static BeanMetaDataClassNormalizer determineBeanMetaDataClassNormalizer(Predefin return new DefaultBeanMetaDataClassNormalizer(); } + static PropertyNodeNameProvider determinePropertyNodeNameProvider(AbstractConfigurationImpl hibernateSpecificConfig, Map properties, + ClassLoader externalClassLoader) { + if ( hibernateSpecificConfig.getPropertyNodeNameProvider() != null ) { + LOG.usingPropertyNodeNameProvider( hibernateSpecificConfig.getPropertyNodeNameProvider().getClass() ); + + return hibernateSpecificConfig.getPropertyNodeNameProvider(); + } + + String propertyNodeNameProviderFqcn = properties.get( HibernateValidatorConfiguration.PROPERTY_NODE_NAME_PROVIDER_CLASSNAME ); + if ( propertyNodeNameProviderFqcn != null ) { + try { + @SuppressWarnings("unchecked") + Class clazz = (Class) run( LoadClass.action( propertyNodeNameProviderFqcn, externalClassLoader ) ); + PropertyNodeNameProvider propertyNodeNameProvider = run( NewInstance.action( clazz, "property node name provider class" ) ); + LOG.usingPropertyNodeNameProvider( clazz ); + + return propertyNodeNameProvider; + } + catch (Exception e) { + throw LOG.getUnableToInstantiatePropertyNodeNameProviderClassException( propertyNodeNameProviderFqcn, e ); + } + } + + return new DefaultPropertyNodeNameProvider(); + } + static void registerCustomConstraintValidators(Set constraintMappings, ConstraintHelper constraintHelper) { Set> definedConstraints = newHashSet(); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java index a075136fd8..9fb2a7705b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java @@ -169,7 +169,8 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { this.constraintCreationContext = new ConstraintCreationContext( constraintHelper, constraintValidatorManager, typeResolutionHelper, valueExtractorManager ); this.executableHelper = new ExecutableHelper( typeResolutionHelper ); - this.javaBeanHelper = new JavaBeanHelper( ValidatorFactoryConfigurationHelper.determineGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ) ); + this.javaBeanHelper = new JavaBeanHelper( ValidatorFactoryConfigurationHelper.determineGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ), + ValidatorFactoryConfigurationHelper.determinePropertyNodeNameProvider( hibernateSpecificConfig, properties, externalClassLoader ) ); // HV-302; don't load XmlMappingParser if not necessary if ( configurationState.getMappingStreams().isEmpty() ) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractPropertyCascadable.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractPropertyCascadable.java index 1cb08aea79..aea6cb0558 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractPropertyCascadable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/AbstractPropertyCascadable.java @@ -48,7 +48,7 @@ public Object getValue(Object parent) { @Override public void appendTo(PathImpl path) { - path.addPropertyNode( property.getPropertyName() ); + path.addPropertyNode( property.getResolvedPropertyName() ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java index 3d7e105ea3..950a49250c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/location/AbstractPropertyConstraintLocation.java @@ -54,7 +54,7 @@ public Type getTypeForValidatorResolution() { @Override public void appendTo(ExecutableParameterNameProvider parameterNameProvider, PathImpl path) { - path.addPropertyNode( property.getPropertyName() ); + path.addPropertyNode( property.getResolvedPropertyName() ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java index bae009a3f7..20076d9e85 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/provider/AnnotationMetaDataProvider.java @@ -220,7 +220,7 @@ private Set getFieldMetaData(Class beanClass) { continue; } - JavaBeanField javaBeanField = new JavaBeanField( field ); + JavaBeanField javaBeanField = javaBeanHelper.field( field ); if ( annotationProcessingOptions.areMemberConstraintsIgnoredFor( javaBeanField ) ) { continue; diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/Property.java b/engine/src/main/java/org/hibernate/validator/internal/properties/Property.java index 12018421e0..63cc7fa07c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/Property.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/Property.java @@ -13,5 +13,7 @@ public interface Property extends Constrainable { String getPropertyName(); + String getResolvedPropertyName(); + PropertyAccessor createAccessor(); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java index 647a33a3de..a45fefe27d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java @@ -25,13 +25,15 @@ public class JavaBeanField implements org.hibernate.validator.internal.properties.Field, JavaBeanAnnotatedConstrainable { private final Field field; + private final String resolvedPropertyName; private final Type typeForValidatorResolution; private final Type type; - public JavaBeanField(Field field) { + public JavaBeanField(Field field, String resolvedPropertyName) { this.field = field; this.type = ReflectionHelper.typeOf( field ); this.typeForValidatorResolution = ReflectionHelper.boxedType( this.type ); + this.resolvedPropertyName = resolvedPropertyName; } @Override @@ -59,6 +61,11 @@ public String getPropertyName() { return getName(); } + @Override + public String getResolvedPropertyName() { + return resolvedPropertyName; + } + @Override public AnnotatedType getAnnotatedType() { return field.getAnnotatedType(); diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java index f4993ec2ba..ae6d0cb74d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java @@ -25,6 +25,7 @@ public class JavaBeanGetter extends JavaBeanMethod implements Getter { private final String propertyName; + private final String resolvedPropertyName; /** * The class of the method for which the constraint was defined. @@ -34,12 +35,13 @@ public class JavaBeanGetter extends JavaBeanMethod implements Getter { */ private final Class declaringClass; - public JavaBeanGetter(Class declaringClass, Method method, String propertyName) { + public JavaBeanGetter(Class declaringClass, Method method, String propertyName, String resolvedPropertyName) { super( method ); Contracts.assertNotNull( propertyName, "Property name cannot be null." ); this.declaringClass = declaringClass; this.propertyName = propertyName; + this.resolvedPropertyName = resolvedPropertyName; } @Override @@ -47,6 +49,11 @@ public String getPropertyName() { return propertyName; } + @Override + public String getResolvedPropertyName() { + return resolvedPropertyName; + } + @Override public boolean hasReturnValue() { // getters should always have a return value diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java index b9788ea685..6afed49ecc 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanHelper.java @@ -22,6 +22,8 @@ import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredField; import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethod; import org.hibernate.validator.internal.util.privilegedactions.GetMethodFromGetterNameCandidates; +import org.hibernate.validator.spi.nodenameprovider.JavaBeanProperty; +import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider; import org.hibernate.validator.spi.properties.ConstrainableExecutable; import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; @@ -34,9 +36,11 @@ public class JavaBeanHelper { private final GetterPropertySelectionStrategy getterPropertySelectionStrategy; + private final PropertyNodeNameProvider propertyNodeNameProvider; - public JavaBeanHelper(GetterPropertySelectionStrategy getterPropertySelectionStrategy) { + public JavaBeanHelper(GetterPropertySelectionStrategy getterPropertySelectionStrategy, PropertyNodeNameProvider propertyNodeNameProvider) { this.getterPropertySelectionStrategy = getterPropertySelectionStrategy; + this.propertyNodeNameProvider = propertyNodeNameProvider; } public GetterPropertySelectionStrategy getGetterPropertySelectionStrategy() { @@ -47,7 +51,8 @@ public Optional findDeclaredField(Class declaringClass, String Contracts.assertNotNull( declaringClass, MESSAGES.classCannotBeNull() ); Field field = run( GetDeclaredField.action( declaringClass, property ) ); - return Optional.ofNullable( field ).map( JavaBeanField::new ); + + return Optional.ofNullable( field ).map( this::field ); } public Optional findDeclaredGetter(Class declaringClass, String property) { @@ -74,9 +79,8 @@ private Optional findGetter(Class declaringClass, String prop return Optional.empty(); } else { - return Optional.of( - new JavaBeanGetter( declaringClass, getter, property ) - ); + return Optional.of( new JavaBeanGetter( declaringClass, getter, property, propertyNodeNameProvider.getName( + new JavaBeanPropertyImpl( declaringClass, property ) ) ) ); } } @@ -117,12 +121,17 @@ public JavaBeanMethod executable(Class declaringClass, Method method) { Optional correspondingProperty = getterPropertySelectionStrategy.getProperty( executable ); if ( correspondingProperty.isPresent() ) { - return new JavaBeanGetter( declaringClass, method, correspondingProperty.get() ); + return new JavaBeanGetter( declaringClass, method, correspondingProperty.get(), propertyNodeNameProvider.getName( + new JavaBeanPropertyImpl( declaringClass, correspondingProperty.get() ) ) ); } return new JavaBeanMethod( method ); } + public JavaBeanField field(Field field) { + return new JavaBeanField( field, propertyNodeNameProvider.getName( new JavaBeanPropertyImpl( field.getDeclaringClass(), field.getName() ) ) ); + } + /** * Runs the given privileged action, using a privileged block if required. * @@ -156,4 +165,24 @@ public Class[] getParameterTypes() { return method.getParameterTypes(); } } + + private static class JavaBeanPropertyImpl implements JavaBeanProperty { + private final Class declaringClass; + private final String name; + + private JavaBeanPropertyImpl(Class declaringClass, String name) { + this.declaringClass = declaringClass; + this.name = name; + } + + @Override + public Class getDeclaringClass() { + return declaringClass; + } + + @Override + public String getName() { + return name; + } + } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 4107e2502b..37b270810b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -63,6 +63,7 @@ import org.hibernate.validator.internal.util.logging.formatter.ObjectArrayFormatter; import org.hibernate.validator.internal.util.logging.formatter.TypeFormatter; import org.hibernate.validator.internal.xml.mapping.ContainerElementTypePath; +import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider; import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; import org.hibernate.validator.spi.scripting.ScriptEvaluationException; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; @@ -887,4 +888,11 @@ ConstraintDefinitionException getConstraintValidatorDefinitionConstraintMismatch @LogMessage(level = ERROR) @Message(id = 251, value = "An error occurred while loading an instance of service %s.") void unableToLoadInstanceOfService(String serviceName, @Cause ServiceConfigurationError e); + + @LogMessage(level = DEBUG) + @Message(id = 252, value = "Using %s as property node name provider.") + void usingPropertyNodeNameProvider(@FormatWith(ClassObjectFormatter.class) Class propertyNodeNameProviderClass); + + @Message(id = 253, value = "Unable to instantiate property node name provider class %s.") + ValidationException getUnableToInstantiatePropertyNodeNameProviderClassException(String propertyNodeNameProviderClassName, @Cause Exception e); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationBootstrapParameters.java b/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationBootstrapParameters.java index 47925728c7..0ccaa9cec4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationBootstrapParameters.java +++ b/engine/src/main/java/org/hibernate/validator/internal/xml/config/ValidationBootstrapParameters.java @@ -32,6 +32,7 @@ import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.util.privilegedactions.LoadClass; import org.hibernate.validator.internal.util.privilegedactions.NewInstance; +import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider; /** * @author Hardy Ferentschik @@ -50,6 +51,7 @@ public class ValidationBootstrapParameters { private final Map configProperties = new HashMap<>(); private final Set mappings = new HashSet<>(); private final Map valueExtractorDescriptors = new HashMap<>(); + private PropertyNodeNameProvider propertyNodeNameProvider; public ValidationBootstrapParameters() { } @@ -150,6 +152,14 @@ public void addValueExtractorDescriptor(ValueExtractorDescriptor descriptor) { valueExtractorDescriptors.put( descriptor.getKey(), descriptor ); } + public PropertyNodeNameProvider getPropertyNodeNameProvider() { + return propertyNodeNameProvider; + } + + public void setPropertyNodeNameProvider(PropertyNodeNameProvider propertyNodeNameProvider) { + this.propertyNodeNameProvider = propertyNodeNameProvider; + } + @SuppressWarnings("unchecked") private void setProviderClass(String providerFqcn, ClassLoader externalClassLoader) { if ( providerFqcn != null ) { diff --git a/engine/src/main/java/org/hibernate/validator/spi/nodenameprovider/JavaBeanProperty.java b/engine/src/main/java/org/hibernate/validator/spi/nodenameprovider/JavaBeanProperty.java new file mode 100644 index 0000000000..ebc845b6d5 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/spi/nodenameprovider/JavaBeanProperty.java @@ -0,0 +1,25 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.spi.nodenameprovider; + +import org.hibernate.validator.Incubating; + +/** + * Contains metadata for a JavaBean property. + * + * @author Damir Alibegovic + * @since 6.1.0 + */ +@Incubating +public interface JavaBeanProperty extends Property { + /** + * Owner class of the property. + * + * @return {@link Class} owning class of the property + */ + Class getDeclaringClass(); +} diff --git a/engine/src/main/java/org/hibernate/validator/spi/nodenameprovider/Property.java b/engine/src/main/java/org/hibernate/validator/spi/nodenameprovider/Property.java new file mode 100644 index 0000000000..ac9bc4d98e --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/spi/nodenameprovider/Property.java @@ -0,0 +1,26 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.spi.nodenameprovider; + + +import org.hibernate.validator.Incubating; + +/** + * Base interface for property metadata. + * + * @author Damir Alibegovic + * @since 6.1.0 + */ +@Incubating +public interface Property { + /** + * Returns the property name. + * + * @return {@link String} representing the property name + */ + String getName(); +} diff --git a/engine/src/main/java/org/hibernate/validator/spi/nodenameprovider/PropertyNodeNameProvider.java b/engine/src/main/java/org/hibernate/validator/spi/nodenameprovider/PropertyNodeNameProvider.java new file mode 100644 index 0000000000..751668cfc8 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/spi/nodenameprovider/PropertyNodeNameProvider.java @@ -0,0 +1,38 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.spi.nodenameprovider; + +import org.hibernate.validator.Incubating; + +/** + * This interface is used to resolve the name of a property node when creating the property path. + * + * @author Damir Alibegovic + * @since 6.1.0 + */ +@Incubating +public interface PropertyNodeNameProvider { + /** + * Returns the resolved name of a property. + *

+ * Depending on the subtype of the {@link Property}, + * a different strategy for name resolution could be applied, defaulting to {@link Property#getName()}. For example: + * + *

+	 * if (property instanceof {@link JavaBeanProperty}) {
+	 *     // for instance, generate a property name based on the annotations of the property
+	 * } else {
+	 *     return property.getName();
+	 * }
+	 * 
+ * + * @param property who's name needs to be resolved + * + * @return String representing the resolved name + */ + String getName(Property property); +} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java index 09a67ac8f4..6c4a45fcbd 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java @@ -29,6 +29,7 @@ import javax.validation.constraints.NotNull; import org.hibernate.validator.internal.engine.DefaultParameterNameProvider; +import org.hibernate.validator.internal.engine.DefaultPropertyNodeNameProvider; import org.hibernate.validator.internal.engine.MethodValidationConfiguration; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.engine.path.PathImpl; @@ -196,7 +197,7 @@ public void testCreationOfExecutablePath() throws Exception { getDummyConstraintCreationContext(), new ExecutableHelper( new TypeResolutionHelper() ), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), - new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy(), new DefaultPropertyNodeNameProvider() ), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java index 306006d7d0..55ec5dd048 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java @@ -22,6 +22,7 @@ import java.util.List; import org.hibernate.validator.internal.engine.DefaultParameterNameProvider; +import org.hibernate.validator.internal.engine.DefaultPropertyNodeNameProvider; import org.hibernate.validator.internal.engine.MethodValidationConfiguration; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl; @@ -55,7 +56,7 @@ public void setUpBeanMetaDataManager() { getDummyConstraintCreationContext(), new ExecutableHelper( new TypeResolutionHelper() ), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), - new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy(), new DefaultPropertyNodeNameProvider() ), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java index 172df763ed..dee545145b 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java @@ -24,6 +24,7 @@ import javax.validation.groups.Default; import org.hibernate.validator.internal.engine.DefaultParameterNameProvider; +import org.hibernate.validator.internal.engine.DefaultPropertyNodeNameProvider; import org.hibernate.validator.internal.engine.MethodValidationConfiguration; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; @@ -61,7 +62,7 @@ public void setupBeanMetaData() { getDummyConstraintCreationContext(), new ExecutableHelper( new TypeResolutionHelper() ), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), - new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy(), new DefaultPropertyNodeNameProvider() ), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java index 189b3a75d0..cb8b39c6f1 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java @@ -25,6 +25,7 @@ import javax.validation.groups.Default; import org.hibernate.validator.internal.engine.DefaultParameterNameProvider; +import org.hibernate.validator.internal.engine.DefaultPropertyNodeNameProvider; import org.hibernate.validator.internal.engine.MethodValidationConfiguration; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; @@ -61,7 +62,7 @@ public void setupBeanMetaData() { getDummyConstraintCreationContext(), new ExecutableHelper( new TypeResolutionHelper() ), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), - new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy(), new DefaultPropertyNodeNameProvider() ), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() @@ -130,7 +131,7 @@ public void parameterNameInInheritanceHierarchy() throws Exception { getDummyConstraintCreationContext(), new ExecutableHelper( new TypeResolutionHelper() ), new ExecutableParameterNameProvider( new SkewedParameterNameProvider() ), - new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy(), new DefaultPropertyNodeNameProvider() ), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java index e7a723fd00..cd83158b14 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java @@ -18,6 +18,7 @@ import javax.validation.groups.Default; import org.hibernate.validator.internal.engine.DefaultParameterNameProvider; +import org.hibernate.validator.internal.engine.DefaultPropertyNodeNameProvider; import org.hibernate.validator.internal.engine.MethodValidationConfiguration; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; @@ -45,7 +46,7 @@ public void setupBeanMetaDataManager() { getDummyConstraintCreationContext(), new ExecutableHelper( new TypeResolutionHelper() ), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), - new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy(), new DefaultPropertyNodeNameProvider() ), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java index e4965e5ce0..cb8a4a04b2 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java @@ -56,7 +56,7 @@ public void setUp() throws Exception { @Test @TestForIssue(jiraKey = "HV-930") public void two_meta_constraints_for_the_same_constraint_should_be_equal() throws Exception { - JavaBeanGetter javaBeanGetter = new JavaBeanGetter( Foo.class, Foo.class.getDeclaredMethod( "getBar" ), "bar" ); + JavaBeanGetter javaBeanGetter = new JavaBeanGetter( Foo.class, Foo.class.getDeclaredMethod( "getBar" ), "bar", "bar" ); ConstraintDescriptorImpl constraintDescriptor1 = new ConstraintDescriptorImpl<>( constraintHelper, javaBeanGetter, constraintAnnotationDescriptor, ConstraintLocationKind.METHOD ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/location/ConstraintLocationTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/location/ConstraintLocationTest.java index 7cb7424737..b83a97c1fc 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/location/ConstraintLocationTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/location/ConstraintLocationTest.java @@ -33,8 +33,8 @@ public void two_constraint_locations_for_the_same_type_should_be_equal() { @TestForIssue(jiraKey = "HV-930") public void two_constraint_locations_for_the_same_member_should_be_equal() throws Exception { Method getter = Foo.class.getMethod( "getBar" ); - ConstraintLocation location1 = ConstraintLocation.forGetter( new JavaBeanGetter( Foo.class, getter, "bar" ) ); - ConstraintLocation location2 = ConstraintLocation.forGetter( new JavaBeanGetter( Foo.class, getter, "bar" ) ); + ConstraintLocation location1 = ConstraintLocation.forGetter( new JavaBeanGetter( Foo.class, getter, "bar", "bar" ) ); + ConstraintLocation location2 = ConstraintLocation.forGetter( new JavaBeanGetter( Foo.class, getter, "bar", "bar" ) ); assertEquals( location1, location2, "Two constraint locations for the same type should be equal" ); } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java index 21ab1a450c..1f4016a66f 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTest.java @@ -29,6 +29,7 @@ import javax.validation.metadata.ConstraintDescriptor; import org.hibernate.validator.constraints.ScriptAssert; +import org.hibernate.validator.internal.engine.DefaultPropertyNodeNameProvider; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; @@ -58,7 +59,7 @@ public class AnnotationMetaDataProviderTest extends AnnotationMetaDataProviderTe public void setUpProvider() { provider = new AnnotationMetaDataProvider( getDummyConstraintCreationContext(), - new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy(), new DefaultPropertyNodeNameProvider() ), new AnnotationProcessingOptionsImpl() ); } @@ -100,7 +101,7 @@ public void testGetCrossParameterMetaData() throws Exception { assertThat( createEvent.getCrossParameterConstraints() ).hasSize( 1 ); assertThat( createEvent.getCallable() ).isEqualTo( - new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ) + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy(), new DefaultPropertyNodeNameProvider() ) .findDeclaredMethod( Calendar.class, "createEvent", LocalDate.class, LocalDate.class ) .get() ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTestBase.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTestBase.java index d4f430f361..a75be4b083 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTestBase.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/AnnotationMetaDataProviderTestBase.java @@ -11,6 +11,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Member; +import org.hibernate.validator.internal.engine.DefaultPropertyNodeNameProvider; import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; @@ -61,7 +62,7 @@ protected ConstrainedType findConstrainedType(BeanConfiguration beanConfi } protected ConstrainedElement findConstrainedElement(BeanConfiguration beanConfiguration, Member member) { - JavaBeanHelper javaBeanHelper = new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ); + JavaBeanHelper javaBeanHelper = new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy(), new DefaultPropertyNodeNameProvider() ); Constrainable constrainable; if ( member instanceof Field ) { constrainable = javaBeanHelper.findDeclaredField( member.getDeclaringClass(), member.getName() ).get(); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/TypeAnnotationMetaDataRetrievalTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/TypeAnnotationMetaDataRetrievalTest.java index ee70424dab..e7895e5f3e 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/TypeAnnotationMetaDataRetrievalTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/provider/TypeAnnotationMetaDataRetrievalTest.java @@ -19,6 +19,7 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; +import org.hibernate.validator.internal.engine.DefaultPropertyNodeNameProvider; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; import org.hibernate.validator.internal.metadata.core.MetaConstraint; import org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider; @@ -44,7 +45,7 @@ public class TypeAnnotationMetaDataRetrievalTest extends AnnotationMetaDataProvi public void setup() { provider = new AnnotationMetaDataProvider( getDummyConstraintCreationContext(), - new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy(), new DefaultPropertyNodeNameProvider() ), new AnnotationProcessingOptionsImpl() ); } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/xml/MappingXmlParserTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/xml/MappingXmlParserTest.java index b264cd1d17..0609a452a2 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/xml/MappingXmlParserTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/xml/MappingXmlParserTest.java @@ -23,6 +23,7 @@ import javax.validation.constraints.DecimalMin; import org.hibernate.validator.internal.engine.ConstraintCreationContext; +import org.hibernate.validator.internal.engine.DefaultPropertyNodeNameProvider; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorDescriptor; import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; @@ -44,7 +45,7 @@ public void setupParserHelper() { constraintCreationContext = getDummyConstraintCreationContext(); xmlMappingParser = new MappingXmlParser( constraintCreationContext, - new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy() ), null + new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy(), new DefaultPropertyNodeNameProvider() ), null ); } diff --git a/engine/src/test/java/org/hibernate/validator/test/spi/nodenameprovider/AnnotationPropertyNodeNameProvider.java b/engine/src/test/java/org/hibernate/validator/test/spi/nodenameprovider/AnnotationPropertyNodeNameProvider.java new file mode 100644 index 0000000000..c7215ea880 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/spi/nodenameprovider/AnnotationPropertyNodeNameProvider.java @@ -0,0 +1,90 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.spi.nodenameprovider; + +import java.io.Serializable; +import java.lang.annotation.Annotation; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.Objects; +import java.util.Optional; + +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.spi.nodenameprovider.JavaBeanProperty; +import org.hibernate.validator.spi.nodenameprovider.Property; +import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider; + +/** + * An example of how a name can be resolved from an annotation + * + * @author Damir Alibegovic + */ +class AnnotationPropertyNodeNameProvider implements PropertyNodeNameProvider, Serializable { + private static final String VALUE = "value"; + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + private final Class annotationType; + private final String annotationMemberName; + + AnnotationPropertyNodeNameProvider(Class annotationType) { + this( annotationType, VALUE ); + } + + AnnotationPropertyNodeNameProvider(Class annotationType, String annotationMemberName) { + this.annotationType = Objects.requireNonNull( annotationType ); + this.annotationMemberName = Objects.requireNonNull( annotationMemberName ); + } + + @Override + public String getName(Property property) { + if ( property instanceof JavaBeanProperty ) { + return getJavaBeanPropertyName( (JavaBeanProperty) property ); + } + + return getDefaultName( property ); + } + + private String getJavaBeanPropertyName(JavaBeanProperty property) { + Optional field = getField( property ); + + if ( field.isPresent() && field.get().isAnnotationPresent( annotationType ) ) { + return getAnnotationMemberValue( field.get(), annotationMemberName ) + .orElse( getDefaultName( property ) ); + } + else { + return getDefaultName( property ); + } + } + + private Optional getField(JavaBeanProperty property) { + return Arrays.stream( property.getDeclaringClass().getFields() ) + .peek( field -> field.setAccessible( true ) ) + .filter( field -> property.getName().equals( field.getName() ) ) + .findFirst(); + } + + private Optional getAnnotationMemberValue(Field field, String annotationMemberName) { + Annotation annotation = field.getAnnotation( annotationType ); + + try { + return Optional.of( + (String) annotation.annotationType().getMethod( annotationMemberName ).invoke( annotation ) ); + } + catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + LOG.error( "Unable to get annotation member value", e ); + + return Optional.empty(); + } + } + + private String getDefaultName(Property property) { + return property.getName(); + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/spi/nodenameprovider/PropertyNodeNameProviderTest.java b/engine/src/test/java/org/hibernate/validator/test/spi/nodenameprovider/PropertyNodeNameProviderTest.java new file mode 100644 index 0000000000..ba94821cfe --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/spi/nodenameprovider/PropertyNodeNameProviderTest.java @@ -0,0 +1,241 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.spi.nodenameprovider; + +import static org.testng.Assert.assertEquals; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import javax.validation.ConstraintViolation; +import javax.validation.Valid; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import javax.validation.constraints.Min; +import javax.validation.constraints.Size; + +import org.hibernate.validator.HibernateValidator; +import org.hibernate.validator.testutil.TestForIssue; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * @author Damir Alibegovic + */ +@TestForIssue(jiraKey = "HV-823") +public class PropertyNodeNameProviderTest { + private static final String INVALID_BRAND_NAME = "BMW"; + private static final String VALID_BRAND_NAME = "Mercedes"; + + private Validator validator; + + @BeforeMethod + public void setUp() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .propertyNodeNameProvider( new AnnotationPropertyNodeNameProvider( PropertyName.class ) ) + .buildValidatorFactory(); + + validator = validatorFactory.getValidator(); + } + + @Test + public void nameIsResolvedFromCustomAnnotationByUsingValidate() { + Car testInstance = new Car( INVALID_BRAND_NAME ); + + Set> violations = validator.validate( testInstance ); + ConstraintViolation violation = violations.iterator().next(); + + assertEquals( violation.getPropertyPath().toString(), "brand.brand_name" ); + } + + @Test + public void nameIsResolvedFromCustomAnnotationByUsingValidateProperty() { + Car testInstance = new Car( INVALID_BRAND_NAME ); + + Set> violations = validator.validateProperty( testInstance, "brand.name" ); + ConstraintViolation violation = violations.iterator().next(); + + assertEquals( violation.getPropertyPath().toString(), "brand.brand_name" ); + } + + @Test + public void nameIsResolvedFromCustomAnnotationByUsingValidateValue() { + Set> violations = validator.validateValue( Brand.class, "name", INVALID_BRAND_NAME ); + ConstraintViolation violation = violations.iterator().next(); + + assertEquals( violation.getPropertyPath().toString(), "brand_name" ); + } + + @Test + public void nameIsResolvedFromCustomAnnotationWithConstraintOnGetter() { + int horsePower = 125; + int speedInRpm = 500; + Airplane testInstance = new Airplane( new Engine( horsePower, speedInRpm ) ); + + Set> violations = validator.validate( testInstance ); + ConstraintViolation violation = violations.iterator().next(); + + assertEquals( violation.getPropertyPath().toString(), "turbojet_engine.speed_in_rpm" ); + } + + @Test + public void propertyCanBeOfTypeMap() { + int horsePower = 0; + int speedInRpm = 1000; + Car testInstance = new Car( VALID_BRAND_NAME ); + testInstance.addComponent( "engine", new Engine( horsePower, speedInRpm ) ); + + Set> violations = validator.validate( testInstance ); + ConstraintViolation violation = violations.iterator().next(); + + assertEquals( violation.getPropertyPath().toString(), "components[engine].horse_power" ); + + } + + @Test + public void defaultValidatorFactoryUsesDefaultPropertyNodeNameProvider() { + ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + Validator val = factory.getValidator(); + + Car testInstance = new Car( INVALID_BRAND_NAME ); + + Set> violations = val.validate( testInstance ); + ConstraintViolation violation = violations.iterator().next(); + + assertEquals( violation.getPropertyPath().toString(), "brand.name" ); + } + + @Test + public void defaultProviderUsesDefaultPropertyNodeNameProvider() { + ValidatorFactory validatorFactory = Validation.byDefaultProvider() + .configure() + .buildValidatorFactory(); + Validator val = validatorFactory.getValidator(); + + Car testInstance = new Car( INVALID_BRAND_NAME ); + + Set> violations = val.validate( testInstance ); + ConstraintViolation violation = violations.iterator().next(); + + assertEquals( violation.getPropertyPath().toString(), "brand.name" ); + } + + @Test + public void hibernateValidatorUsesDefaultPropertyNodeProvider() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .buildValidatorFactory(); + Validator val = validatorFactory.getValidator(); + + Car testInstance = new Car( INVALID_BRAND_NAME ); + + Set> violations = val.validate( testInstance ); + ConstraintViolation violation = violations.iterator().next(); + + assertEquals( violation.getPropertyPath().toString(), "brand.name" ); + } + + @Test + public void hibernateValidatorCanUseCustomPropertyNodeNameProvider() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .propertyNodeNameProvider( new AnnotationPropertyNodeNameProvider( PropertyName.class ) ) + .buildValidatorFactory(); + Validator val = validatorFactory.getValidator(); + + Car testInstance = new Car( INVALID_BRAND_NAME ); + + Set> violations = val.validate( testInstance ); + ConstraintViolation violation = violations.iterator().next(); + + assertEquals( violation.getPropertyPath().toString(), "brand.brand_name" ); + } + + @Test + public void hibernateValidatorFallsBackToDefaultPropertyNodeNameProvider() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .propertyNodeNameProvider( null ) + .buildValidatorFactory(); + Validator val = validatorFactory.getValidator(); + + Car testInstance = new Car( INVALID_BRAND_NAME ); + + Set> violations = val.validate( testInstance ); + ConstraintViolation violation = violations.iterator().next(); + + assertEquals( violation.getPropertyPath().toString(), "brand.name" ); + } + + @Retention(RetentionPolicy.RUNTIME) + @Target({ ElementType.FIELD, ElementType.METHOD }) + public @interface PropertyName { + String value(); + } + + private class Car { + @PropertyName("components") + public final Map comps = new HashMap<>(); + + @Valid + public final Brand brand; + + Car(String brand) { + this.brand = new Brand( brand ); + } + + public void addComponent(String name, Object component) { + comps.put( name, component ); + } + } + + private class Brand { + @PropertyName("brand_name") + @Size(min = 4) + public final String name; + + Brand(String name) { + this.name = name; + } + } + + private class Engine { + @PropertyName("horse_power") + @Min(1) + public final int horsePower; + + @PropertyName("speed_in_rpm") + public final int speedInRpm; + + public Engine(int horsePower, int speedInRpm) { + this.horsePower = horsePower; + this.speedInRpm = speedInRpm; + } + + @Min(1000) + public int getSpeedInRpm() { + return speedInRpm; + } + } + + private class Airplane { + @Valid + @PropertyName("turbojet_engine") + public final Engine engine; + + public Airplane(Engine engine) { + this.engine = engine; + } + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/spi/nodenameprovider/jackson/JacksonAnnotationPropertyNodeNameProvider.java b/engine/src/test/java/org/hibernate/validator/test/spi/nodenameprovider/jackson/JacksonAnnotationPropertyNodeNameProvider.java new file mode 100644 index 0000000000..829b5ad5f8 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/spi/nodenameprovider/jackson/JacksonAnnotationPropertyNodeNameProvider.java @@ -0,0 +1,50 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.spi.nodenameprovider.jackson; + +import org.hibernate.validator.spi.nodenameprovider.JavaBeanProperty; +import org.hibernate.validator.spi.nodenameprovider.Property; +import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider; + +import com.fasterxml.jackson.databind.BeanDescription; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; + +/** + * An example of how a name can be resolved from a Jackson annotation. + * + * @author Damir Alibegovic + */ +public class JacksonAnnotationPropertyNodeNameProvider implements PropertyNodeNameProvider { + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public String getName(Property property) { + if ( property instanceof JavaBeanProperty ) { + return getJavaBeanPropertyName( (JavaBeanProperty) property ); + } + + return getDefaultName( property ); + } + + private String getJavaBeanPropertyName(JavaBeanProperty property) { + JavaType type = objectMapper.constructType( property.getDeclaringClass() ); + BeanDescription desc = objectMapper.getSerializationConfig().introspect( type ); + + return desc.findProperties() + .stream() + .filter( prop -> prop.getInternalName().equals( property.getName() ) ) + .map( BeanPropertyDefinition::getName ) + .findFirst() + .orElse( property.getName() ); + } + + private String getDefaultName(Property property) { + return property.getName(); + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/spi/nodenameprovider/jackson/JacksonAnnotationPropertyNodeNameProviderTest.java b/engine/src/test/java/org/hibernate/validator/test/spi/nodenameprovider/jackson/JacksonAnnotationPropertyNodeNameProviderTest.java new file mode 100644 index 0000000000..b10f1c3767 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/spi/nodenameprovider/jackson/JacksonAnnotationPropertyNodeNameProviderTest.java @@ -0,0 +1,99 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.spi.nodenameprovider.jackson; + +import static org.testng.Assert.assertEquals; + +import java.util.Set; +import javax.validation.ConstraintViolation; +import javax.validation.Valid; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; + +import org.hibernate.validator.HibernateValidator; +import org.hibernate.validator.testutil.TestForIssue; + +import com.fasterxml.jackson.annotation.JsonProperty; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * @author Damir Alibegovic + */ +@TestForIssue(jiraKey = "HV-823") +public class JacksonAnnotationPropertyNodeNameProviderTest { + private static final int VALID_HORSE_POWER = 150; + private static final int INVALID_HORSE_POWER = 250; + + private Validator validator; + + @BeforeMethod + public void setUp() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .propertyNodeNameProvider( new JacksonAnnotationPropertyNodeNameProvider() ) + .buildValidatorFactory(); + + validator = validatorFactory.getValidator(); + } + + @Test + public void jsonPropertyOnFieldIsUsedForPathResolution() { + Car testInstance = new Car( new Engine( INVALID_HORSE_POWER ) ); + + Set> violations = validator.validate( testInstance ); + ConstraintViolation violation = violations.iterator().next(); + + assertEquals( violation.getPropertyPath().toString(), "engine.horse_power" ); + } + + @Test + public void jsonPropertyOnGetterIsUsedForPathResolution() { + int invalidNumberOfSeats = 0; + Car testInstance = new Car( new Engine( VALID_HORSE_POWER ), invalidNumberOfSeats ); + + Set> violations = validator.validate( testInstance ); + ConstraintViolation violation = violations.iterator().next(); + + assertEquals( violation.getPropertyPath().toString(), "number_of_seats" ); + } + + private class Car { + @Valid + private final Engine engine; + + @Min(1) + private final int numberOfSeats; + + Car(Engine engine) { + this( engine, 4 ); + } + + Car(Engine engine, int numberOfSeats) { + this.engine = engine; + this.numberOfSeats = numberOfSeats; + } + + @JsonProperty("number_of_seats") + public int getNumberOfSeats() { + return numberOfSeats; + } + } + + private class Engine { + @JsonProperty("horse_power") + @Max(200) + private final int horsePower; + + Engine(int horsePower) { + this.horsePower = horsePower; + } + } +} diff --git a/pom.xml b/pom.xml index f5d03aa7fb..801e2622f1 100644 --- a/pom.xml +++ b/pom.xml @@ -170,6 +170,7 @@ 23.0 4.3.10.RELEASE 1.0.0.Final + 2.9.8 4.2.0 @@ -492,6 +493,18 @@ ${version.org.springframework.spring-expression} test + + com.fasterxml.jackson.core + jackson-databind + ${version.com.fasterxml.jackson.core} + test + + + com.fasterxml.jackson.core + jackson-annotations + ${version.com.fasterxml.jackson.core} + test + From 7af945416378502b4e4d17f6ce5bfa12a533c022 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 13 May 2019 16:37:45 +0200 Subject: [PATCH 214/393] HV-823 Minor adjustments to the documentation --- documentation/src/main/asciidoc/ch12.asciidoc | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/documentation/src/main/asciidoc/ch12.asciidoc b/documentation/src/main/asciidoc/ch12.asciidoc index f75abf82ea..27960a4043 100644 --- a/documentation/src/main/asciidoc/ch12.asciidoc +++ b/documentation/src/main/asciidoc/ch12.asciidoc @@ -765,7 +765,7 @@ Otherwise, the default strategy will be used for the mappings added before defin ==== [[section-property-node-name-provider]] -==== Changing the way property names are resolved when the property path is constructed +=== Customizing the property name resolution for constraint violations Imagine that we have a simple data class that has `@NotNull` constraints on some fields: [[example-person-class]] @@ -798,16 +798,18 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/nodenamepr ==== Notice how the names of the properties differ. In the Java object, we have `firstName` and `lastName`, whereas in the JSON output, we have -`first_name` and `last_name`. We defined this behaviour through `@JsonProperty` annotations. +`first_name` and `last_name`. +We customized this behavior through `@JsonProperty` annotations. -Now imagine, that we use this class in a REST environment, where a user can send <> in the request body. -It would be nice, when telling the user on which field the validation failed, to tell them the name they use in their JSON request, `first_name`, +Now imagine that we use this class in a REST environment, where a user can send <> in the request body. +It would be nice, when indicating on which field the validation failed, to indicate the name they use in their JSON request, `first_name`, and not the name we use internally in our Java code, `firstName`. -The `org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider` contract allows us to do this. By implementing it, -we can define how the name of a property will be resolved during validation. In our case, we want to read the value from the Jackson configuration. +The `org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider` contract allows us to do this. +By implementing it, we can define how the name of a property will be resolved during validation. +In our case, we want to read the value from the Jackson configuration. -So, one example of how to do this is to leverage the Jackson API: +One example of how to do this is to leverage the Jackson API: [[example-jackson-property-node-name-provider]] .JacksonPropertyNodeNameProvider implementation ==== @@ -829,7 +831,7 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/nodenamepr We can see that the property path now returns `first_name`. -Note that this also works when the annotations are on the getter: +Note that this also works when the annotations are on a getter: [[example-jackson-property-node-name-provider-getter]] .Annotation on a getter ==== @@ -850,6 +852,6 @@ There are two more interfaces that are worth mentioning: has a single `String getName()` method that can be used to get the "original" name of a property. This interface should be used as a default way of resolving the name (see how it is used in <>). -- `org.hibernate.validator.spi.nodenameprovider.JavaBeanProperty` is an interface that holds metada about a bean property. It -extends `org.hibernate.validator.spi.nodenameprovider.Property` and provide some more data like `Class getDeclaringClass()` -which is the class that is the owner of the property. This additional metadata can be useful when revolving the name. +- `org.hibernate.validator.spi.nodenameprovider.JavaBeanProperty` is an interface that holds metadata about a bean property. It +extends `org.hibernate.validator.spi.nodenameprovider.Property` and provide some additional methods like `Class getDeclaringClass()` +which returns the class that is the owner of the property. From cbc6d14af99e3d8669dd7e0fbab26f3211727e79 Mon Sep 17 00:00:00 2001 From: preuss Date: Tue, 7 May 2019 09:38:42 +0200 Subject: [PATCH 215/393] HV-1708 Add Danish translations for validation messages --- copyright.txt | 1 + .../ValidationMessages_da.properties | 53 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 engine/src/main/resources/org/hibernate/validator/ValidationMessages_da.properties diff --git a/copyright.txt b/copyright.txt index 7a27c32024..30095168ef 100644 --- a/copyright.txt +++ b/copyright.txt @@ -31,6 +31,7 @@ Henno Vermeulen Hillmer Chona Jan-Willem Willebrands Jason T. Greene +Jesper Preuss Jiri Bilek Julien Furgerot Julien May diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_da.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_da.properties new file mode 100644 index 0000000000..c2eb592ead --- /dev/null +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_da.properties @@ -0,0 +1,53 @@ +javax.validation.constraints.AssertFalse.message = skal v\u00e6re falsk +javax.validation.constraints.AssertTrue.message = skal v\u00e6re sand +javax.validation.constraints.DecimalMax.message = skal v\u00e6re mindre end ${inclusive == true ? 'eller det samme som ' : ''}{value} +javax.validation.constraints.DecimalMin.message = skal v\u00e6re st\u00f8rre end ${inclusive == true ? 'eller det samme som ' : ''}{value} +javax.validation.constraints.Digits.message = tal v\u00e6rdierne er udenfor det gyldige omr\u00e5de (<{integer} digits>.<{fraction} digits> forventet) +javax.validation.constraints.Email.message = skal v\u00e6re en korrekt formateret e-mail-adresse +javax.validation.constraints.Future.message = skal v\u00e6re en dato i fremtiden +javax.validation.constraints.FutureOrPresent.message = skal v\u00e6re en dato i nutiden eller i fremtiden +javax.validation.constraints.Max.message = skal v\u00e6re mindre end eller lig med {value} +javax.validation.constraints.Min.message = skal v\u00e6re st\u00f8rre end eller lig med {value} +javax.validation.constraints.Negative.message = skal v\u00e6re mindre end 0 +javax.validation.constraints.NegativeOrZero.message = skal v\u00e6re mindre end eller lig med 0 +javax.validation.constraints.NotBlank.message = m\u00e5 ikke v\u00e6re blank +javax.validation.constraints.NotEmpty.message = m\u00e5 ikke v\u00e6re tom +javax.validation.constraints.NotNull.message = m\u00e5 ikke v\u00e6re null +javax.validation.constraints.Null.message = skal v\u00e6re null +javax.validation.constraints.Past.message = skal v\u00e6re en dato fortiden +javax.validation.constraints.PastOrPresent.message = skal v\u00e6re en dato i fortiden eller i nutiden +javax.validation.constraints.Pattern.message = skal matche "{regexp}" +javax.validation.constraints.Positive.message = skal v\u00e6re st\u00f8rre end 0 +javax.validation.constraints.PositiveOrZero.message = skal v\u00e6re st\u00f8rre end eller lig med 0 +javax.validation.constraints.Size.message = st\u00f8rrelse skal v\u00e6re mellem {min} og {max} + +org.hibernate.validator.constraints.CreditCardNumber.message = ugyldigt kreditkortnummer +org.hibernate.validator.constraints.Currency.message = ugyldig valuta (skal v\u00e6re en af {v\u00e6rdi}) +org.hibernate.validator.constraints.EAN.message = ugyldig {type} stregkode +org.hibernate.validator.constraints.Email.message = ikke en velformuleret email adresse +org.hibernate.validator.constraints.ISBN.message = ugyldigt ISBN +org.hibernate.validator.constraints.Length.message = l\u00e6ngden skal v\u00e6re mellem {min} og {max} +org.hibernate.validator.constraints.CodePointLength.message = l\u00e6ngden skal v\u00e6re mellem {min} og {max} +org.hibernate.validator.constraints.LuhnCheck.message = kontrolcifferet for $ {validatedValue} er ugyldigt, Luhn Modulo 10 checksum mislykkedes +org.hibernate.validator.constraints.Mod10Check.message = kontrolcifferet for $ {validatedValue} er ugyldigt, Modulo 10 checksum mislykkedes +org.hibernate.validator.constraints.Mod11Check.message = kontrolcifferet for $ {validatedValue} er ugyldigt, Modulo 11 checksum mislykkedes +org.hibernate.validator.constraints.ModCheck.message = kontrolcifferet for $ {validatedValue} er ugyldigt, $ {modType} checksummet mislykkedes +org.hibernate.validator.constraints.NotBlank.message = m\u00e5 ikke v\u00e6re tomt +org.hibernate.validator.constraints.NotEmpty.message = m\u00e5 ikke v\u00e6re tomt +org.hibernate.validator.constraints.ParametersScriptAssert.message = script udtryk "{script}" evaluerede ikke til true +org.hibernate.validator.constraints.Range.message = skal v\u00e6re mellem {min} og {max} +org.hibernate.validator.constraints.SafeHtml.message = kan have usikkert HTML-indhold +org.hibernate.validator.constraints.ScriptAssert.message = script udtryk "{script}" evaluerede ikke til true +org.hibernate.validator.constraints.UniqueElements.message = m\u00e5 kun indeholde unikke elementer +org.hibernate.validator.constraints.URL.message = skal v\u00e6re en gyldig webadresse + +org.hibernate.validator.constraints.br.CNPJ.message = ugyldigt brasiliansk selskabsskattem\u00e6ssige registreringsnummer (CNPJ) +org.hibernate.validator.constraints.br.CPF.message = ugyldigt brasiliansk enkeltregistratornummer (CPF) +org.hibernate.validator.constraints.br.TituloEleitoral.message = Ugyldigt brasiliansk Voter ID-kortnummer + +org.hibernate.validator.constraints.pl.REGON.message = ugyldigt polsk skattebetalers identifikationsnummer (REGON) +org.hibernate.validator.constraints.pl.NIP.message = ugyldigt momsidentifikationsnummer (NIP) +org.hibernate.validator.constraints.pl.PESEL.message = ugyldigt polsk nationalt identifikationsnummer (PESEL) + +org.hibernate.validator.constraints.time.DurationMax.message = skal v\u00e6re kortere end${inclusive == true ? ' eller lig med' : ''}${days == 0 ? '' : days == 1 ? ' 1 dag' : ' ' += days += ' dage'}${hours == 0 ? '' : hours == 1 ? ' 1 time' : ' ' += hours += ' timer'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minut' : ' ' += minutes += ' minutter'}${seconds == 0 ? '' : seconds == 1 ? ' 1 sekund' : ' ' += seconds += ' sekunder'}${millis == 0 ? '' : millis == 1 ? ' 1 millisekund' : ' ' += millis += ' millisekunder'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanosekund' : ' ' += nanos += ' nanosekunder'} +org.hibernate.validator.constraints.time.DurationMin.message = skal v\u00e6re l\u00e6ngere end${inclusive == true ? ' eller lig med' : ''}${days == 0 ? '' : days == 1 ? ' 1 dag' : ' ' += days += ' dage'}${hours == 0 ? '' : hours == 1 ? ' 1 time' : ' ' += hours += ' timer'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minut' : ' ' += minutes += ' minutter'}${seconds == 0 ? '' : seconds == 1 ? ' 1 sekund : ' ' += seconds += ' sekunder'}${millis == 0 ? '' : millis == 1 ? ' 1 millisekund' : ' ' += millis += ' millisekunder'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanosekund' : ' ' += nanos += ' nanosekunder'} From 948aaa2776ec915451ebd2e40401a095fa3cdba0 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Tue, 7 May 2019 20:27:26 +0200 Subject: [PATCH 216/393] HV-1709 Check that Polish Identification numbers are of correct length - Check the length of validated identification number - Add tests for short/long values - Add tests for nondigits in the values - Disallow nondigits in PESEL --- .../hv/pl/PESELValidator.java | 7 +++++- .../hv/pl/PolishNumberValidator.java | 9 ++++++- .../annotations/hv/pl/NIPValidatorTest.java | 18 +++++++++++++- .../annotations/hv/pl/PESELValidatorTest.java | 24 +++++++++++++++++++ .../annotations/hv/pl/REGONValidatorTest.java | 24 +++++++++++++++++++ 5 files changed, 79 insertions(+), 3 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/pl/PESELValidator.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/pl/PESELValidator.java index 4b33031e2c..326e558e8c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/pl/PESELValidator.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/pl/PESELValidator.java @@ -30,7 +30,7 @@ public void initialize(PESEL constraintAnnotation) { 0, Integer.MAX_VALUE, -1, - true + false ); } @@ -38,6 +38,11 @@ public void initialize(PESEL constraintAnnotation) { public boolean isCheckDigitValid(List digits, char checkDigit) { Collections.reverse( digits ); + // if the length of the number is incorrect we can return fast + if ( digits.size() != WEIGHTS_PESEL.length ) { + return false; + } + int modResult = ModUtil.calculateModXCheckWithWeights( digits, 10, Integer.MAX_VALUE, WEIGHTS_PESEL ); switch ( modResult ) { case 10: diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/pl/PolishNumberValidator.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/pl/PolishNumberValidator.java index f41cdb780a..1ab9289d7e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/pl/PolishNumberValidator.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/pl/PolishNumberValidator.java @@ -27,8 +27,15 @@ public abstract class PolishNumberValidator extends ModChe public boolean isCheckDigitValid(List digits, char checkDigit) { Collections.reverse( digits ); + int[] weights = getWeights( digits ); + + // if the length of the number is incorrect we can return fast + if ( weights.length != digits.size() ) { + return false; + } + // as we need sum % 11 rather than 11 - (sum % 11) returned by Mod11 algorithm: - int modResult = 11 - ModUtil.calculateModXCheckWithWeights( digits, 11, Integer.MAX_VALUE, getWeights( digits ) ); + int modResult = 11 - ModUtil.calculateModXCheckWithWeights( digits, 11, Integer.MAX_VALUE, weights ); switch ( modResult ) { case 10: case 11: diff --git a/engine/src/test/java/org/hibernate/validator/test/constraints/annotations/hv/pl/NIPValidatorTest.java b/engine/src/test/java/org/hibernate/validator/test/constraints/annotations/hv/pl/NIPValidatorTest.java index 59680961d2..678ec69422 100644 --- a/engine/src/test/java/org/hibernate/validator/test/constraints/annotations/hv/pl/NIPValidatorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/constraints/annotations/hv/pl/NIPValidatorTest.java @@ -24,10 +24,26 @@ public class NIPValidatorTest extends AbstractConstrainedTest { @Test - public void testCorrectNipNumber() { + public void testAdditionalCharactersAreAllowed() { assertNoViolations( validator.validate( new Person( "123-456-78-19" ) ) ); assertNoViolations( validator.validate( new Person( "123-45-67-819" ) ) ); assertNoViolations( validator.validate( new Person( "123-456-32-18" ) ) ); + } + + @Test + public void testIncorrectLength() { + assertThat( validator.validate( new Person( "123-456-78-14113-312-310" ) ) ) + .containsOnlyViolations( + violationOf( NIP.class ).withProperty( "nip" ) + ); + assertThat( validator.validate( new Person( "123-45-62" ) ) ) + .containsOnlyViolations( + violationOf( NIP.class ).withProperty( "nip" ) + ); + } + + @Test + public void testCorrectNipNumber() { assertNoViolations( validator.validate( new Person( "5931423811" ) ) ); assertNoViolations( validator.validate( new Person( "2596048500" ) ) ); assertNoViolations( validator.validate( new Person( "4163450312" ) ) ); diff --git a/engine/src/test/java/org/hibernate/validator/test/constraints/annotations/hv/pl/PESELValidatorTest.java b/engine/src/test/java/org/hibernate/validator/test/constraints/annotations/hv/pl/PESELValidatorTest.java index 352344df31..7b7752df0f 100644 --- a/engine/src/test/java/org/hibernate/validator/test/constraints/annotations/hv/pl/PESELValidatorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/constraints/annotations/hv/pl/PESELValidatorTest.java @@ -23,6 +23,30 @@ */ public class PESELValidatorTest extends AbstractConstrainedTest { + @Test + public void testAdditionalCharactersNotAllowed() { + assertThat( validator.validate( new Person( "9204-190-37-90" ) ) ) + .containsOnlyViolations( + violationOf( PESEL.class ).withProperty( "pesel" ) + ); + assertThat( validator.validate( new Person( "44-0-5-1-4-01359" ) ) ) + .containsOnlyViolations( + violationOf( PESEL.class ).withProperty( "pesel" ) + ); + } + + @Test + public void testIncorrectLength() { + assertThat( validator.validate( new Person( "920419795" ) ) ) + .containsOnlyViolations( + violationOf( PESEL.class ).withProperty( "pesel" ) + ); + assertThat( validator.validate( new Person( "92041903790123" ) ) ) + .containsOnlyViolations( + violationOf( PESEL.class ).withProperty( "pesel" ) + ); + } + @Test public void testCorrectPESELNumber() { assertNoViolations( validator.validate( new Person( "92041903790" ) ) ); diff --git a/engine/src/test/java/org/hibernate/validator/test/constraints/annotations/hv/pl/REGONValidatorTest.java b/engine/src/test/java/org/hibernate/validator/test/constraints/annotations/hv/pl/REGONValidatorTest.java index 50ea4b4c08..f54e4bf041 100644 --- a/engine/src/test/java/org/hibernate/validator/test/constraints/annotations/hv/pl/REGONValidatorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/constraints/annotations/hv/pl/REGONValidatorTest.java @@ -23,6 +23,30 @@ */ public class REGONValidatorTest extends AbstractConstrainedTest { + @Test + public void testAdditionalCharactersNotAllowed() { + assertThat( validator.validate( new Company( "123-456-785" ) ) ) + .containsOnlyViolations( + violationOf( REGON.class ).withProperty( "regon" ) + ); + assertThat( validator.validate( new Company( "6-9-1-6-5-7-1-8-2" ) ) ) + .containsOnlyViolations( + violationOf( REGON.class ).withProperty( "regon" ) + ); + } + + @Test + public void testIncorrectLength() { + assertThat( validator.validate( new Company( "1234567845" ) ) ) + .containsOnlyViolations( + violationOf( REGON.class ).withProperty( "regon" ) + ); + assertThat( validator.validate( new Company( "12345673" ) ) ) + .containsOnlyViolations( + violationOf( REGON.class ).withProperty( "regon" ) + ); + } + @Test public void testCorrectRegon9Number() { assertNoViolations( validator.validate( new Company( "123456785" ) ) ); From 7e2609a851553843e1c56ef9514fb4e5056be07a Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Thu, 16 May 2019 13:15:47 +0200 Subject: [PATCH 217/393] HV-1713 Convert current group before checking if the bean is processed - We need to convert the group before checking if the bean was processed or not as group defines the processed status --- .../internal/engine/ValidatorImpl.java | 20 +++++++++------- .../AbstractGroupConversionTest.java | 23 +++++++++++++++++++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index 48005de326..82e006babd 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -609,14 +609,16 @@ private void validateCascadedConstraints(BaseBeanValidationContext validation private void validateCascadedAnnotatedObjectForCurrentGroup(Object value, BaseBeanValidationContext validationContext, ValueContext valueContext, CascadingMetaData cascadingMetaData) { - if ( validationContext.isBeanAlreadyValidated( value, valueContext.getCurrentGroup(), valueContext.getPropertyPath() ) || + // We need to convert the group before checking if the bean was processed or not + // as group defines the processed status. + Class originalGroup = valueContext.getCurrentGroup(); + Class currentGroup = cascadingMetaData.convertGroup( originalGroup ); + + if ( validationContext.isBeanAlreadyValidated( value, currentGroup, valueContext.getPropertyPath() ) || shouldFailFast( validationContext ) ) { return; } - Class originalGroup = valueContext.getCurrentGroup(); - Class currentGroup = cascadingMetaData.convertGroup( originalGroup ); - // expand the group only if was created by group conversion; // otherwise we're looping through the right validation order // already and need only to pass the current element @@ -686,15 +688,17 @@ public void keyedValue(String nodeName, Object key, Object value) { } private void doValidate(Object value, String nodeName) { + // We need to convert the group before checking if the bean was processed or not + // as group defines the processed status. + Class originalGroup = valueContext.getCurrentGroup(); + Class currentGroup = cascadingMetaData.convertGroup( originalGroup ); + if ( value == null || - validationContext.isBeanAlreadyValidated( value, valueContext.getCurrentGroup(), valueContext.getPropertyPath() ) || + validationContext.isBeanAlreadyValidated( value, currentGroup, valueContext.getPropertyPath() ) || shouldFailFast( validationContext ) ) { return; } - Class originalGroup = valueContext.getCurrentGroup(); - Class currentGroup = cascadingMetaData.convertGroup( originalGroup ); - // expand the group only if was created by group conversion; // otherwise we're looping through the right validation order // already and need only to pass the current element diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/groups/conversion/AbstractGroupConversionTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/groups/conversion/AbstractGroupConversionTest.java index 5075439f51..c78abcee4c 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/groups/conversion/AbstractGroupConversionTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/groups/conversion/AbstractGroupConversionTest.java @@ -23,6 +23,7 @@ import javax.validation.GroupSequence; import javax.validation.Valid; import javax.validation.Validator; +import javax.validation.constraints.AssertTrue; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import javax.validation.groups.ConvertGroup; @@ -30,6 +31,7 @@ import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.testutils.CandidateForTck; import org.testng.annotations.Test; /** @@ -214,6 +216,19 @@ public void conversionFromSequenceCausesException() { validator.validate( new User8() ); } + @Test + @CandidateForTck + public void sameBeanDifferentGroups() { + Set> violations = validator.validate( new User9() ); + assertThat( violations ).containsOnlyViolations( + violationOf( AssertTrue.class ).withPropertyPath( pathWith() + .property( "a" ) + .property( "b" ) + ) + ); + } + + public interface Complete extends Default { } @@ -341,4 +356,12 @@ private static class User8 { @ConvertGroup(from = PostalSequence.class, to = BasicPostal.class) private final List
addresses = Arrays.asList( new Address() ); } + + private static class User9 { + @Valid + @ConvertGroup(from = Default.class, to = BasicNumber.class) + User9 a = this; + @AssertTrue(groups = BasicNumber.class) + boolean b; + } } From 87fedbabe6441d4efb4876bbae46f27d27d2fffb Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 3 Jun 2019 15:42:41 +0200 Subject: [PATCH 218/393] HV-1716 Update WildFly secondary version to 17.0.0.Beta1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 801e2622f1..44a5a23ed5 100644 --- a/pom.xml +++ b/pom.xml @@ -124,7 +124,7 @@ 16.0.0.Final - 15.0.1.Final + 17.0.0.Beta1 ${version.wildfly} From 1874d9fcdd07a3740c175ec43f158a350d86151b Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 3 Jun 2019 15:43:26 +0200 Subject: [PATCH 219/393] HV-1717 Update test dependencies --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 44a5a23ed5..b6bf9d5ec6 100644 --- a/pom.xml +++ b/pom.xml @@ -167,10 +167,10 @@ 4.12 3.4 2.4.12 - 23.0 + 27.1-jre 4.3.10.RELEASE 1.0.0.Final - 2.9.8 + 2.9.9 4.2.0 From 8d914a8f4db7a9dc0df0a0cc990fcd62ba052131 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 11 Jun 2019 14:57:04 +0200 Subject: [PATCH 220/393] HV-1719 Accept setting per-validator TraversableResolver with PredefinedScopeValidatorFactoryImpl --- .../PredefinedScopeValidatorContextImpl.java | 3 +- .../PredefinedScopeValidatorFactoryTest.java | 46 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorContextImpl.java index 6f83cd90db..6951658a47 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorContextImpl.java @@ -39,7 +39,8 @@ public HibernateValidatorContext messageInterpolator(MessageInterpolator message @Override public HibernateValidatorContext traversableResolver(TraversableResolver traversableResolver) { - throw new IllegalStateException( "Defining a Validator-specific traversable resolver is not supported by the predefined scope ValidatorFactory." ); + validatorFactoryScopedContextBuilder.setTraversableResolver( traversableResolver ); + return this; } @Override diff --git a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java index 624e9bc1d4..47c4653062 100644 --- a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java @@ -10,13 +10,18 @@ import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; import static org.hibernate.validator.testutil.ConstraintViolationAssert.pathWith; import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; +import static org.testng.Assert.fail; +import java.lang.annotation.ElementType; import java.util.Collections; import java.util.HashSet; import java.util.Locale; import java.util.Set; import javax.validation.ConstraintViolation; +import javax.validation.Path; +import javax.validation.Path.Node; +import javax.validation.TraversableResolver; import javax.validation.Valid; import javax.validation.Validation; import javax.validation.ValidationException; @@ -25,6 +30,7 @@ import javax.validation.constraints.Email; import javax.validation.constraints.NotNull; +import org.assertj.core.api.Assertions; import org.hibernate.validator.PredefinedScopeHibernateValidator; import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; import org.hibernate.validator.testutil.TestForIssue; @@ -216,6 +222,28 @@ public void testBeanMetaDataClassNormalizer() { violationOf( NotNull.class ).withProperty( "property" ) ); } + @Test + public void validatorSpecificTraversableResolver() { + Set> beanMetaDataToInitialize = new HashSet<>(); + beanMetaDataToInitialize.add( Bean.class ); + beanMetaDataToInitialize.add( AnotherBean.class ); + + ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) + .configure() + .initializeBeanMetaData( beanMetaDataToInitialize ) + .buildValidatorFactory(); + + try { + Validator validator = validatorFactory.usingContext().traversableResolver( new ThrowExceptionTraversableResolver() ) + .getValidator(); + validator.validate( new Bean() ); + fail(); + } + catch (ValidationException e) { + Assertions.assertThat( e ).hasCauseExactlyInstanceOf( ValidatorSpecificTraversableResolverUsedException.class ); + } + } + private static Validator getValidator() { Set> beanMetaDataToInitialize = new HashSet<>(); beanMetaDataToInitialize.add( Bean.class ); @@ -321,4 +349,22 @@ public Class normalize(Class beanClass) { private static class BeanProxy extends Bean implements MyProxyInterface { } + + private static class ThrowExceptionTraversableResolver implements TraversableResolver { + + @Override + public boolean isReachable(Object traversableObject, Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, + ElementType elementType) { + throw new ValidatorSpecificTraversableResolverUsedException(); + } + + @Override + public boolean isCascadable(Object traversableObject, Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, + ElementType elementType) { + throw new ValidatorSpecificTraversableResolverUsedException(); + } + } + + private static class ValidatorSpecificTraversableResolverUsedException extends RuntimeException { + } } From f2d5f06fa45780649c842dfdb0db5f649a9c7cec Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 4 Jun 2019 20:13:02 +0200 Subject: [PATCH 221/393] HV-1718 Support validating unconstrained beans with PredefinedScopeValidatorFactory --- .../PredefinedScopeBeanMetaDataManager.java | 229 ++++++++++++++++-- .../validator/internal/util/logging/Log.java | 3 - .../PredefinedScopeValidatorFactoryTest.java | 36 ++- 3 files changed, 237 insertions(+), 31 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java index 4751ebc4a4..b7215b0637 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/PredefinedScopeBeanMetaDataManager.java @@ -8,44 +8,57 @@ import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; -import java.lang.invoke.MethodHandles; +import java.lang.annotation.ElementType; +import java.lang.reflect.Executable; import java.util.ArrayList; -import java.util.HashMap; +import java.util.Collections; +import java.util.Iterator; import java.util.List; -import java.util.Map; +import java.util.Optional; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.validation.metadata.BeanDescriptor; +import javax.validation.metadata.ConstraintDescriptor; +import javax.validation.metadata.ConstructorDescriptor; +import javax.validation.metadata.ElementDescriptor.ConstraintFinder; +import javax.validation.metadata.MethodDescriptor; +import javax.validation.metadata.MethodType; +import javax.validation.metadata.PropertyDescriptor; +import javax.validation.metadata.Scope; import org.hibernate.validator.internal.engine.ConstraintCreationContext; import org.hibernate.validator.internal.engine.MethodValidationConfiguration; +import org.hibernate.validator.internal.engine.groups.Sequence; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataBuilder; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl; +import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; +import org.hibernate.validator.internal.metadata.aggregated.PropertyMetaData; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptions; import org.hibernate.validator.internal.metadata.core.AnnotationProcessingOptionsImpl; +import org.hibernate.validator.internal.metadata.core.MetaConstraint; +import org.hibernate.validator.internal.metadata.facets.Cascadable; import org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; import org.hibernate.validator.internal.metadata.raw.BeanConfiguration; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; -import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.ExecutableHelper; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper; import org.hibernate.validator.internal.util.classhierarchy.Filters; -import org.hibernate.validator.internal.util.logging.Log; -import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; public class PredefinedScopeBeanMetaDataManager implements BeanMetaDataManager { - private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - private final BeanMetaDataClassNormalizer beanMetaDataClassNormalizer; /** - * Used to cache the constraint meta data for validated entities + * Used to cache the constraint meta data for validated entities. */ - private final Map, BeanMetaData> beanMetaDataMap; + private final ConcurrentMap, BeanMetaData> beanMetaDataMap = new ConcurrentHashMap<>(); public PredefinedScopeBeanMetaDataManager(ConstraintCreationContext constraintCreationContext, ExecutableHelper executableHelper, @@ -71,32 +84,37 @@ public PredefinedScopeBeanMetaDataManager(ConstraintCreationContext constraintCr metaDataProviders.add( defaultProvider ); metaDataProviders.addAll( optionalMetaDataProviders ); - Map, BeanMetaData> tmpBeanMetadataMap = new HashMap<>(); - for ( Class validatedClass : beanClassesToInitialize ) { + Class normalizedValidatedClass = beanMetaDataClassNormalizer.normalize( validatedClass ); + @SuppressWarnings("unchecked") - List> classHierarchy = (List>) (Object) ClassHierarchyHelper.getHierarchy( validatedClass, Filters.excludeInterfaces() ); + List> classHierarchy = (List>) (Object) ClassHierarchyHelper.getHierarchy( normalizedValidatedClass, Filters.excludeInterfaces() ); // note that the hierarchy also contains the initial class for ( Class hierarchyElement : classHierarchy ) { - tmpBeanMetadataMap.put( beanMetaDataClassNormalizer.normalize( hierarchyElement ), + if ( this.beanMetaDataMap.containsKey( hierarchyElement ) ) { + continue; + } + + this.beanMetaDataMap.put( hierarchyElement, createBeanMetaData( constraintCreationContext, executableHelper, parameterNameProvider, javaBeanHelper, validationOrderGenerator, optionalMetaDataProviders, methodValidationConfiguration, metaDataProviders, hierarchyElement ) ); } } - this.beanMetaDataMap = CollectionHelper.toImmutableMap( tmpBeanMetadataMap ); - this.beanMetaDataClassNormalizer = beanMetaDataClassNormalizer; } @SuppressWarnings("unchecked") @Override public BeanMetaData getBeanMetaData(Class beanClass) { - BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataMap.get( beanMetaDataClassNormalizer.normalize( beanClass ) ); + Class normalizedBeanClass = beanMetaDataClassNormalizer.normalize( beanClass ); + BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataMap.get( normalizedBeanClass ); if ( beanMetaData == null ) { - throw LOG.uninitializedBeanMetaData( beanClass ); + // note that if at least one element of the hierarchy is constrained, the child classes should really be initialized + // otherwise they will be considered unconstrained. + beanMetaData = (BeanMetaData) beanMetaDataMap.computeIfAbsent( normalizedBeanClass, UninitializedBeanMetaData::new ); } return beanMetaData; } @@ -170,4 +188,179 @@ private static List> getBeanConfigurationForHie return configurations; } + + private static class UninitializedBeanMetaData implements BeanMetaData { + + private final Class beanClass; + + private final BeanDescriptor beanDescriptor; + + private final List> classHierarchy; + + @SuppressWarnings("unchecked") + private UninitializedBeanMetaData(Class beanClass) { + this.beanClass = beanClass; + this.classHierarchy = (List>) (Object) ClassHierarchyHelper.getHierarchy( beanClass, Filters.excludeInterfaces() ); + this.beanDescriptor = new UninitializedBeanDescriptor( beanClass ); + } + + @Override + public Iterable getCascadables() { + return Collections.emptyList(); + } + + @Override + public boolean hasCascadables() { + return false; + } + + @Override + public Class getBeanClass() { + return beanClass; + } + + @Override + public boolean hasConstraints() { + return false; + } + + @Override + public BeanDescriptor getBeanDescriptor() { + return beanDescriptor; + } + + @Override + public PropertyMetaData getMetaDataFor(String propertyName) { + throw new IllegalStateException( "Metadata has not been initialized for bean of type " + beanClass.getName() ); + } + + @Override + public List> getDefaultGroupSequence(T beanState) { + throw new IllegalStateException( "Metadata has not been initialized for bean of type " + beanClass.getName() ); + } + + @Override + public Iterator getDefaultValidationSequence(T beanState) { + throw new IllegalStateException( "Metadata has not been initialized for bean of type " + beanClass.getName() ); + } + + @Override + public boolean isDefaultGroupSequenceRedefined() { + return false; + } + + @Override + public Set> getMetaConstraints() { + return Collections.emptySet(); + } + + @Override + public Set> getDirectMetaConstraints() { + return Collections.emptySet(); + } + + @Override + public Optional getMetaDataFor(Executable executable) throws IllegalArgumentException { + return Optional.empty(); + } + + @Override + public List> getClassHierarchy() { + return classHierarchy; + } + } + + private static class UninitializedBeanDescriptor implements BeanDescriptor { + + private final Class elementClass; + + private UninitializedBeanDescriptor(Class elementClass) { + this.elementClass = elementClass; + } + + @Override + public boolean hasConstraints() { + return false; + } + + @Override + public Class getElementClass() { + return elementClass; + } + + @Override + public Set> getConstraintDescriptors() { + return Collections.emptySet(); + } + + @Override + public ConstraintFinder findConstraints() { + return UninitializedConstaintFinder.INSTANCE; + } + + @Override + public boolean isBeanConstrained() { + return false; + } + + @Override + public PropertyDescriptor getConstraintsForProperty(String propertyName) { + return null; + } + + @Override + public Set getConstrainedProperties() { + return Collections.emptySet(); + } + + @Override + public MethodDescriptor getConstraintsForMethod(String methodName, Class... parameterTypes) { + return null; + } + + @Override + public Set getConstrainedMethods(MethodType methodType, MethodType... methodTypes) { + return Collections.emptySet(); + } + + @Override + public ConstructorDescriptor getConstraintsForConstructor(Class... parameterTypes) { + return null; + } + + @Override + public Set getConstrainedConstructors() { + return Collections.emptySet(); + } + } + + private static class UninitializedConstaintFinder implements ConstraintFinder { + + private static final UninitializedConstaintFinder INSTANCE = new UninitializedConstaintFinder(); + + @Override + public ConstraintFinder unorderedAndMatchingGroups(Class... groups) { + return this; + } + + @Override + public ConstraintFinder lookingAt(Scope scope) { + return this; + } + + @Override + public ConstraintFinder declaredOn(ElementType... types) { + return this; + } + + @Override + public Set> getConstraintDescriptors() { + return Collections.emptySet(); + } + + @Override + public boolean hasConstraints() { + return false; + } + } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 37b270810b..66efaa85bf 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -879,9 +879,6 @@ ConstraintDefinitionException getConstraintValidatorDefinitionConstraintMismatch @Message(id = 248, value = "Unable to get an XML schema named %s.") ValidationException unableToGetXmlSchema(String schemaResourceName); - @Message(id = 249, value = "Uninitialized bean metadata for class: %s. Please register your bean class as a class to initialize when initializing your ValidatorFactory.") - ValidationException uninitializedBeanMetaData(@FormatWith(ClassObjectFormatter.class) Class clazz); - @Message(id = 250, value = "Uninitialized locale: %s. Please register your locale as a locale to initialize when initializing your ValidatorFactory.") ValidationException uninitializedLocale(Locale locale); diff --git a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java index 47c4653062..d90b239f79 100644 --- a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java @@ -85,7 +85,7 @@ public void testValidation() throws NoSuchMethodException, SecurityException { .property( "email" ) ) ); } - @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000249:.*") + @Test public void testValidationOnUnknownBean() throws NoSuchMethodException, SecurityException { Validator validator = getValidator(); @@ -93,7 +93,7 @@ public void testValidationOnUnknownBean() throws NoSuchMethodException, Security assertNoViolations( violations ); } - @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000249:.*") + @Test public void testValidationOnUnknownBeanMethodParameter() throws NoSuchMethodException, SecurityException { Validator validator = getValidator(); @@ -106,7 +106,7 @@ public void testValidationOnUnknownBeanMethodParameter() throws NoSuchMethodExce assertNoViolations( violations ); } - @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000249:.*") + @Test public void testValidationOnUnknownBeanMethodReturnValue() throws NoSuchMethodException, SecurityException { Validator validator = getValidator(); @@ -115,7 +115,7 @@ public void testValidationOnUnknownBeanMethodReturnValue() throws NoSuchMethodEx assertNoViolations( violations ); } - @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000249:.*") + @Test public void testValidationOnUnknownBeanConstructorParameters() throws NoSuchMethodException, SecurityException { Validator validator = getValidator(); @@ -125,7 +125,7 @@ public void testValidationOnUnknownBeanConstructorParameters() throws NoSuchMeth assertNoViolations( violations ); } - @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000249:.*") + @Test public void testValidationOnUnknownBeanConstructorReturnValue() throws NoSuchMethodException, SecurityException { Validator validator = getValidator(); @@ -173,9 +173,10 @@ public void testUnavailableInitializedLocale() { } @TestForIssue(jiraKey = "HV-1681") - @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000249:.*") + @Test public void testValidOnUnknownBean() { - getValidator().validate( new AnotherBean() ); + Set> violations = getValidator().validate( new AnotherBean() ); + assertNoViolations( violations ); } @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000250:.*") @@ -196,11 +197,26 @@ public void testUninitializedLocale() { } } - @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000249:.*") + @Test public void testBeanMetaDataClassNormalizerNoNormalizer() { - Validator validator = getValidator(); + // In this case, as we haven't registered any metadata for the hierarchy, even if we have constraints, + // we won't have any violations. + Set> violations = getValidator().validate( new BeanProxy() ); + assertNoViolations( violations ); - validator.validate( new BeanProxy() ); + // Now let's register the metadata for Bean and see how it goes + Set> beanMetaDataToInitialize = new HashSet<>(); + beanMetaDataToInitialize.add( Bean.class ); + + ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) + .configure() + .initializeBeanMetaData( beanMetaDataToInitialize ) + .initializeLocales( Collections.singleton( Locale.ENGLISH ) ) + .buildValidatorFactory(); + + // As we don't have any metadata for BeanProxy, we consider it is not constrained at all. + violations = validatorFactory.getValidator().validate( new BeanProxy() ); + assertNoViolations( violations ); } @Test From fc5bb1f29e5ebd06d1d58d5617fa74d94927a618 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 12 Jun 2019 17:10:45 +0200 Subject: [PATCH 222/393] HV-1710 Remove settings-example.xml It has not been used for ages, let's drop it from the repository. --- settings-example.xml | 68 -------------------------------------------- 1 file changed, 68 deletions(-) delete mode 100644 settings-example.xml diff --git a/settings-example.xml b/settings-example.xml deleted file mode 100644 index e96f41de72..0000000000 --- a/settings-example.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - jboss-public-repository - - - - central - Maven Central - http://repo.maven.apache.org/maven2/ - - false - never - - - - jboss-public-repository-group - JBoss Public Maven Repository Group - https://repository.jboss.org/nexus/content/groups/public-jboss/ - default - - true - never - - - true - never - - - - - - - central - Maven Central - http://repo.maven.apache.org/maven2/ - - false - never - - - - jboss-public-repository-group - JBoss Public Maven Repository Group - https://repository.jboss.org/nexus/content/groups/public-jboss/ - default - - true - never - - - true - never - - - - - - - - jboss-public-repository - - - From 0e1c2422c9ab8d5af7be7b6b448be1da0f83d01c Mon Sep 17 00:00:00 2001 From: Jenkins Date: Thu, 13 Jun 2019 13:17:34 +0000 Subject: [PATCH 223/393] [Jenkins release job] README.md updated by release build 6.1.0.Alpha5 --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fec61dd66a..5184969913 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hibernate Validator -*Version: 6.1.0.Alpha4 - 22-03-2019* +*Version: 6.1.0.Alpha5 - 13-06-2019* ## What is it? @@ -35,7 +35,7 @@ Logging will delegate any log requests to that provider. org.hibernate.validator hibernate-validator - 6.1.0.Alpha4 + 6.1.0.Alpha5 You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. @@ -54,7 +54,7 @@ extension by adding the following dependency: org.hibernate.validator hibernate-validator-cdi - 6.1.0.Alpha4 + 6.1.0.Alpha5 * _hibernate-validator-annotation-processor-<version>.jar_ is an optional jar which can be integrated with your build From 29b42e54c80c2fdbd1cce604ae9eef19501c7322 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Thu, 13 Jun 2019 13:17:35 +0000 Subject: [PATCH 224/393] [Jenkins release job] changelog.txt updated by release build 6.1.0.Alpha5 --- changelog.txt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/changelog.txt b/changelog.txt index 5c6953de6f..5a7db91774 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,30 @@ Hibernate Validator Changelog ============================= +6.1.0.Alpha5 (13-06-2019) +------------------------- + +** Bug + * HV-1713 - engine - Missing violation when a bean is validated with different groups + * HV-1709 - validators - Polish Identification numbers are not considering length of the value + * HV-1706 - validators - ISBN-13 algorithm does not handle checksum 10 + +** Improvement + * HV-1719 - engine - Accept setting per-validator TraversableResolver with PredefinedScopeValidatorFactoryImpl + * HV-1708 - translations - Add Danish translations of validation messages + * HV-1707 - validators - Add ISBN.Type.ANY + +** New Feature + * HV-823 - engine - Provide contract for customization of property names in constraint violation + +** Task + * HV-1718 - engine - Predefined scope ValidatorFactory: uninitialized bean class shouldn't throw an exception + * HV-1717 - build - Update test dependencies + * HV-1716 - build - Update WildFly secondary version to 17.0.0.Beta1 + * HV-1712 - engine - Add org.hibernate.validator.metadata to OSGi manifest + * HV-1711 - build - Fix aggregated javadoc build with recent JDK 11 + * HV-1710 - build - Remove settings-example.xml + 6.1.0.Alpha4 (22-03-2019) ------------------------- From f04caba86e3b600a78fad7d23b54617073b10f0c Mon Sep 17 00:00:00 2001 From: Jenkins Date: Thu, 13 Jun 2019 13:17:44 +0000 Subject: [PATCH 225/393] [Jenkins release job] Preparing release 6.1.0.Alpha5 --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 6b70540803..6934e963e6 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 021058c8f5..4c36ab5d4e 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index 64d7dc2320..aebba6cbcd 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index d79df95eec..2b8f0e741c 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 76e9e2b194..6d104a0f2c 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index f371e3562c..c17fe103a5 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 85364bd54c..455ad301c0 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index 6ca85e82c6..5ec2dfc605 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 55c15d1c8c..6eda9e5f18 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 28ce4576ea..c1be698d29 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 1b9ec9f304..97bd3afb75 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index fc4f7e3a85..43768dfddd 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index 847461dfe5..2e56df0686 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 ../pom.xml diff --git a/pom.xml b/pom.xml index b6bf9d5ec6..8f3507d260 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 3f99228d35..df2a332eb8 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index acc9a54560..4dcea09833 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index d793ee6b6e..99e5d32464 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index c2eba20d47..cfcbbb8695 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 6516654b3f..2938449c12 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 469ad132ed..b29d36a8b4 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 3b0766e5c7..21ebff19cf 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha5 hibernate-validator-test-utils From 511009d0c6b1330b8c2575b5e535101d0fdfb85b Mon Sep 17 00:00:00 2001 From: Jenkins Date: Thu, 13 Jun 2019 13:21:27 +0000 Subject: [PATCH 226/393] [Jenkins release job] Preparing next development iteration --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 6934e963e6..6b70540803 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 4c36ab5d4e..021058c8f5 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index aebba6cbcd..64d7dc2320 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index 2b8f0e741c..d79df95eec 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 6d104a0f2c..76e9e2b194 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index c17fe103a5..f371e3562c 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 455ad301c0..85364bd54c 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index 5ec2dfc605..6ca85e82c6 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 6eda9e5f18..55c15d1c8c 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index c1be698d29..28ce4576ea 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 97bd3afb75..1b9ec9f304 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index 43768dfddd..fc4f7e3a85 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index 2e56df0686..847461dfe5 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 8f3507d260..b6bf9d5ec6 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index df2a332eb8..3f99228d35 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index 4dcea09833..acc9a54560 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index 99e5d32464..d793ee6b6e 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index cfcbbb8695..c2eba20d47 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 2938449c12..6516654b3f 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index b29d36a8b4..469ad132ed 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 21ebff19cf..3b0766e5c7 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha5 + 6.1.0-SNAPSHOT hibernate-validator-test-utils From 70f5fe5f8bbdce7bdbd6806d7262dc4b3152be34 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 1 Jul 2019 13:11:38 +0200 Subject: [PATCH 227/393] HV-1721 Take into account HV-specific config with predefined scope VF --- .../ValidatorFactoryConfigurationHelper.java | 20 ++-- ...peConstraintDefinitionContributorTest.java | 94 +++++++++++++++++++ 2 files changed, 105 insertions(+), 9 deletions(-) create mode 100644 engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeConstraintDefinitionContributorTest.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java index b480020202..635d6a61bb 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java @@ -51,15 +51,17 @@ private ValidatorFactoryConfigurationHelper() { } static ClassLoader determineExternalClassLoader(ConfigurationState configurationState) { - return ( configurationState instanceof ConfigurationImpl ) ? ( (ConfigurationImpl) configurationState ).getExternalClassLoader() : null; + return ( configurationState instanceof AbstractConfigurationImpl ) + ? ( (AbstractConfigurationImpl) configurationState ).getExternalClassLoader() + : null; } static Set determineConstraintMappings(TypeResolutionHelper typeResolutionHelper, ConfigurationState configurationState, JavaBeanHelper javaBeanHelper, ClassLoader externalClassLoader) { Set constraintMappings = newHashSet(); - if ( configurationState instanceof ConfigurationImpl ) { - ConfigurationImpl hibernateConfiguration = (ConfigurationImpl) configurationState; + if ( configurationState instanceof AbstractConfigurationImpl ) { + AbstractConfigurationImpl hibernateConfiguration = (AbstractConfigurationImpl) configurationState; // programmatic config /* We add these first so that constraint mapping created through DefaultConstraintMappingBuilder will take @@ -192,8 +194,8 @@ static boolean determineFailFast(AbstractConfigurationImpl configuration, Map static ScriptEvaluatorFactory determineScriptEvaluatorFactory(ConfigurationState configurationState, Map properties, ClassLoader externalClassLoader) { - if ( configurationState instanceof ConfigurationImpl ) { - ConfigurationImpl hibernateSpecificConfig = (ConfigurationImpl) configurationState; + if ( configurationState instanceof AbstractConfigurationImpl ) { + AbstractConfigurationImpl hibernateSpecificConfig = (AbstractConfigurationImpl) configurationState; if ( hibernateSpecificConfig.getScriptEvaluatorFactory() != null ) { LOG.usingScriptEvaluatorFactory( hibernateSpecificConfig.getScriptEvaluatorFactory().getClass() ); return hibernateSpecificConfig.getScriptEvaluatorFactory(); @@ -221,8 +223,8 @@ static ScriptEvaluatorFactory determineScriptEvaluatorFactory(ConfigurationState } static Duration determineTemporalValidationTolerance(ConfigurationState configurationState, Map properties) { - if ( configurationState instanceof ConfigurationImpl ) { - ConfigurationImpl hibernateSpecificConfig = (ConfigurationImpl) configurationState; + if ( configurationState instanceof AbstractConfigurationImpl ) { + AbstractConfigurationImpl hibernateSpecificConfig = (AbstractConfigurationImpl) configurationState; if ( hibernateSpecificConfig.getTemporalValidationTolerance() != null ) { LOG.logTemporalValidationTolerance( hibernateSpecificConfig.getTemporalValidationTolerance() ); return hibernateSpecificConfig.getTemporalValidationTolerance(); @@ -244,8 +246,8 @@ static Duration determineTemporalValidationTolerance(ConfigurationState configur } static Object determineConstraintValidatorPayload(ConfigurationState configurationState) { - if ( configurationState instanceof ConfigurationImpl ) { - ConfigurationImpl hibernateSpecificConfig = (ConfigurationImpl) configurationState; + if ( configurationState instanceof AbstractConfigurationImpl ) { + AbstractConfigurationImpl hibernateSpecificConfig = (AbstractConfigurationImpl) configurationState; if ( hibernateSpecificConfig.getConstraintValidatorPayload() != null ) { LOG.logConstraintValidatorPayload( hibernateSpecificConfig.getConstraintValidatorPayload() ); return hibernateSpecificConfig.getConstraintValidatorPayload(); diff --git a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeConstraintDefinitionContributorTest.java b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeConstraintDefinitionContributorTest.java new file mode 100644 index 0000000000..5f540bcc50 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeConstraintDefinitionContributorTest.java @@ -0,0 +1,94 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.predefinedscope; + +import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; +import static org.hibernate.validator.testutils.ValidatorUtil.getValidator; + +import java.util.HashSet; +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; + +import org.hibernate.validator.PredefinedScopeHibernateValidator; +import org.hibernate.validator.test.constraintvalidator.MustMatch; +import org.hibernate.validator.test.constraintvalidator.MustNotMatch; +import org.hibernate.validator.testutil.TestForIssue; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * Test related to constraint validator discovery in the predefined scope case. + * + * @author Hardy Ferentschik + * @author Guillaume Smet + */ +@TestForIssue(jiraKey = "HV-1721") +public class PredefinedScopeConstraintDefinitionContributorTest { + + private Validator validator; + + @BeforeMethod + public void setUp() { + validator = getValidator(); + Set> beanMetaDataToInitialize = new HashSet<>(); + beanMetaDataToInitialize.add( Foo.class ); + beanMetaDataToInitialize.add( Quz.class ); + + ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) + .configure() + .initializeBeanMetaData( beanMetaDataToInitialize ) + .buildValidatorFactory(); + validator = validatorFactory.getValidator(); + } + + @Test + public void constraint_definitions_can_be_configured_via_service_loader() { + Set> constraintViolations = validator.validate( new Foo() ); + assertThat( constraintViolations ).containsOnlyViolations( + violationOf( MustMatch.class ) + ); + } + + @Test + @TestForIssue(jiraKey = "HV-953") + public void constraints_defined_via_constraint_definition_contributor_can_have_default_message() { + Set> constraintViolations = validator.validate( new Foo() ); + assertThat( constraintViolations ).containsOnlyViolations( + violationOf( MustMatch.class ).withMessage( "MustMatch default message" ) + ); + } + + @Test + @TestForIssue(jiraKey = "HV-953") + public void user_can_override_default_message_of_constraint_definition_contributor() { + Set> constraintViolations = validator.validate( new Quz() ); + assertThat( constraintViolations ).containsOnlyViolations( + violationOf( MustNotMatch.class ).withMessage( "MustNotMatch user message" ) + ); + } + + public class Foo { + // constraint validator defined in service file! + @MustMatch("Foo") + String getFoo() { + return "Bar"; + } + } + + public class Quz { + // constraint validator defined in service file! + @MustNotMatch("Foo") + String getFoo() { + return "Foo"; + } + } +} From 543aedca558d8eb8cd65be6f346587d55884407a Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 1 Jul 2019 13:19:19 +0200 Subject: [PATCH 228/393] HV-1722 Remove settings-example.xml reference from .travis.yml --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1c7f86505d..eb421ac9dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,8 +16,6 @@ addons: cache: directories: - $HOME/.m2 -before_install: - - BUILD_OPTIONS='-s settings-example.xml' install: # The Maven install provided by Travis is outdated, use Maven wrapper to get the latest version - mvn -N io.takari:maven:wrapper From 6cc74f5cc0bebb793aaf4c08b9d4704fd4e4e4a6 Mon Sep 17 00:00:00 2001 From: Dario Seidl Date: Fri, 12 Jul 2019 14:52:35 +0200 Subject: [PATCH 229/393] HV-1723 Add Digits validator for MonetaryAmount --- .../ap/internal/util/ConstraintHelper.java | 1 + .../ap/testmodel/ModelWithJavaMoneyTypes.java | 2 + documentation/src/main/asciidoc/ch02.asciidoc | 2 +- .../DigitsValidatorForMonetaryAmount.java | 62 ++++++++++ .../metadata/core/ConstraintHelper.java | 11 +- .../DigitsValidatorForMonetaryAmountTest.java | 117 ++++++++++++++++++ 6 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/money/DigitsValidatorForMonetaryAmount.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/money/DigitsValidatorForMonetaryAmountTest.java diff --git a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/ConstraintHelper.java b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/ConstraintHelper.java index c390a8f43a..9b5090f802 100644 --- a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/ConstraintHelper.java +++ b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/ConstraintHelper.java @@ -254,6 +254,7 @@ public ConstraintHelper(Types typeUtils, AnnotationApiHelper annotationApiHelper registerAllowedTypesForBuiltInConstraint( BeanValidationTypes.DECIMAL_MIN, Number.class, String.class ); registerAllowedTypesForBuiltInConstraint( BeanValidationTypes.DECIMAL_MIN, JavaMoneyTypes.MONETARY_AMOUNT ); registerAllowedTypesForBuiltInConstraint( BeanValidationTypes.DIGITS, Number.class, String.class ); + registerAllowedTypesForBuiltInConstraint( BeanValidationTypes.DIGITS, JavaMoneyTypes.MONETARY_AMOUNT ); registerAllowedTypesForBuiltInConstraint( BeanValidationTypes.EMAIL, CharSequence.class ); registerAllowedTypesForBuiltInConstraint( BeanValidationTypes.FUTURE, Calendar.class, Date.class ); registerAllowedTypesForBuiltInConstraint( BeanValidationTypes.FUTURE, JodaTypes.READABLE_PARTIAL, JodaTypes.READABLE_INSTANT ); diff --git a/annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/ModelWithJavaMoneyTypes.java b/annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/ModelWithJavaMoneyTypes.java index 67268ae7f8..2dd5279f51 100644 --- a/annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/ModelWithJavaMoneyTypes.java +++ b/annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/ModelWithJavaMoneyTypes.java @@ -9,6 +9,7 @@ import javax.money.MonetaryAmount; import javax.validation.constraints.DecimalMax; import javax.validation.constraints.DecimalMin; +import javax.validation.constraints.Digits; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.Negative; @@ -29,6 +30,7 @@ public class ModelWithJavaMoneyTypes { @DecimalMin("0.00") @Positive @PositiveOrZero + @Digits(integer = 6, fraction = 2) public MonetaryAmount monetaryAmount; @Max(1000L) diff --git a/documentation/src/main/asciidoc/ch02.asciidoc b/documentation/src/main/asciidoc/ch02.asciidoc index 8f62d8c3c2..591af81796 100644 --- a/documentation/src/main/asciidoc/ch02.asciidoc +++ b/documentation/src/main/asciidoc/ch02.asciidoc @@ -580,7 +580,7 @@ impact portability of your application between Bean Validation providers. Hibernate metadata impact::: None `@Digits(integer=, fraction=)`:: Checks whether the annotated value is a number having up to `integer` digits and `fraction` fractional digits - Supported data types::: BigDecimal, `BigInteger`, `CharSequence`, `byte`, `short`, `int`, `long` and the respective wrappers of the primitive types; additionally supported by HV: any sub-type of `Number` + Supported data types::: BigDecimal, `BigInteger`, `CharSequence`, `byte`, `short`, `int`, `long` and the respective wrappers of the primitive types; additionally supported by HV: any sub-type of `Number` and `javax.money.MonetaryAmount` Hibernate metadata impact::: Defines column precision and scale `@Email`:: Checks whether the specified character sequence is a valid email address. The optional parameters `regexp` and `flags` allow to specify an additional regular expression (including regular expression flags) which the email must match. diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/money/DigitsValidatorForMonetaryAmount.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/money/DigitsValidatorForMonetaryAmount.java new file mode 100644 index 0000000000..f46ddd81bc --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/money/DigitsValidatorForMonetaryAmount.java @@ -0,0 +1,62 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.money; + +import java.lang.invoke.MethodHandles; +import java.math.BigDecimal; +import javax.money.MonetaryAmount; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import javax.validation.constraints.Digits; + +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; + +/** + * Validates that the number part of the {@code MonetaryAmount} being validated matches the pattern + * defined in the constraint. + * + * @author Dario Seidl + */ +public class DigitsValidatorForMonetaryAmount implements ConstraintValidator { + + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + + private int maxIntegerLength; + private int maxFractionLength; + + @Override + public void initialize(Digits constraintAnnotation) { + this.maxIntegerLength = constraintAnnotation.integer(); + this.maxFractionLength = constraintAnnotation.fraction(); + validateParameters(); + } + + @Override + public boolean isValid(MonetaryAmount monetaryAmount, ConstraintValidatorContext constraintValidatorContext) { + //null values are valid + if ( monetaryAmount == null ) { + return true; + } + + BigDecimal bigNum = monetaryAmount.getNumber().numberValueExact( BigDecimal.class ); + + int integerPartLength = bigNum.precision() - bigNum.scale(); + int fractionPartLength = bigNum.scale() < 0 ? 0 : bigNum.scale(); + + return ( maxIntegerLength >= integerPartLength && maxFractionLength >= fractionPartLength ); + } + + private void validateParameters() { + if ( maxIntegerLength < 0 ) { + throw LOG.getInvalidLengthForIntegerPartException(); + } + if ( maxFractionLength < 0 ) { + throw LOG.getInvalidLengthForFractionPartException(); + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java index 965d2c7737..b38a5543b3 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java @@ -95,6 +95,7 @@ import org.hibernate.validator.internal.constraintvalidators.bv.money.CurrencyValidatorForMonetaryAmount; import org.hibernate.validator.internal.constraintvalidators.bv.money.DecimalMaxValidatorForMonetaryAmount; import org.hibernate.validator.internal.constraintvalidators.bv.money.DecimalMinValidatorForMonetaryAmount; +import org.hibernate.validator.internal.constraintvalidators.bv.money.DigitsValidatorForMonetaryAmount; import org.hibernate.validator.internal.constraintvalidators.bv.money.MaxValidatorForMonetaryAmount; import org.hibernate.validator.internal.constraintvalidators.bv.money.MinValidatorForMonetaryAmount; import org.hibernate.validator.internal.constraintvalidators.bv.money.NegativeOrZeroValidatorForMonetaryAmount; @@ -366,6 +367,11 @@ public ConstraintHelper() { DecimalMinValidatorForCharSequence.class, DecimalMinValidatorForMonetaryAmount.class ) ); + putConstraints( tmpConstraints, Digits.class, Arrays.asList( + DigitsValidatorForCharSequence.class, + DigitsValidatorForNumber.class, + DigitsValidatorForMonetaryAmount.class + ) ); } else { putConstraints( tmpConstraints, DecimalMax.class, Arrays.asList( @@ -392,9 +398,12 @@ public ConstraintHelper() { DecimalMinValidatorForShort.class, DecimalMinValidatorForCharSequence.class ) ); + putConstraints( tmpConstraints, Digits.class, Arrays.asList( + DigitsValidatorForCharSequence.class, + DigitsValidatorForNumber.class + ) ); } - putConstraints( tmpConstraints, Digits.class, DigitsValidatorForCharSequence.class, DigitsValidatorForNumber.class ); putConstraint( tmpConstraints, Email.class, EmailValidator.class ); List>> futureValidators = new ArrayList<>( 18 ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/money/DigitsValidatorForMonetaryAmountTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/money/DigitsValidatorForMonetaryAmountTest.java new file mode 100644 index 0000000000..2fc8739eb1 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/money/DigitsValidatorForMonetaryAmountTest.java @@ -0,0 +1,117 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.constraintvalidators.bv.money; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import java.math.BigDecimal; +import javax.money.CurrencyUnit; +import javax.money.Monetary; +import javax.validation.constraints.Digits; + +import org.hibernate.validator.internal.constraintvalidators.bv.money.DigitsValidatorForMonetaryAmount; +import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; +import org.hibernate.validator.testutil.TestForIssue; + +import org.javamoney.moneta.Money; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * @author Dario Seidl + */ +@TestForIssue(jiraKey = "HV-1723") +public class DigitsValidatorForMonetaryAmountTest { + + private ConstraintAnnotationDescriptor.Builder descriptorBuilder; + + @BeforeMethod + public void setUp() { + descriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( Digits.class ); + descriptorBuilder.setMessage( "{validator.digits}" ); + } + + @Test + public void testIsValid() { + descriptorBuilder.setAttribute( "integer", 5 ); + descriptorBuilder.setAttribute( "fraction", 2 ); + Digits p = descriptorBuilder.build().getAnnotation(); + + DigitsValidatorForMonetaryAmount constraint = new DigitsValidatorForMonetaryAmount(); + constraint.initialize( p ); + + CurrencyUnit currency = Monetary.getCurrency( "EUR" ); + + assertTrue( constraint.isValid( null, null ) ); + assertTrue( constraint.isValid( Money.of( Byte.valueOf( "0" ), currency ), null ) ); + assertTrue( constraint.isValid( Money.of( Double.valueOf( "500.2" ), currency ), null ) ); + + assertTrue( constraint.isValid( Money.of( new BigDecimal( "-12345.12" ), currency ), null ) ); + assertFalse( constraint.isValid( Money.of( new BigDecimal( "-123456.12" ), currency ), null ) ); + assertFalse( constraint.isValid( Money.of( new BigDecimal( "-123456.123" ), currency ), null ) ); + assertFalse( constraint.isValid( Money.of( new BigDecimal( "-12345.123" ), currency ), null ) ); + assertFalse( constraint.isValid( Money.of( new BigDecimal( "12345.123" ), currency ), null ) ); + + assertTrue( constraint.isValid( Money.of( Float.valueOf( "-000000000.22" ), currency ), null ) ); + assertFalse( constraint.isValid( Money.of( Integer.valueOf( "256874" ), currency ), null ) ); + assertFalse( constraint.isValid( Money.of( Double.valueOf( "12.0001" ), currency ), null ) ); + } + + @Test + public void testIsValidZeroLength() { + descriptorBuilder.setAttribute( "integer", 0 ); + descriptorBuilder.setAttribute( "fraction", 0 ); + Digits p = descriptorBuilder.build().getAnnotation(); + + DigitsValidatorForMonetaryAmount constraint = new DigitsValidatorForMonetaryAmount(); + constraint.initialize( p ); + + CurrencyUnit currency = Monetary.getCurrency( "EUR" ); + + assertTrue( constraint.isValid( null, null ) ); + assertFalse( constraint.isValid( Money.of( Byte.valueOf( "0" ), currency ), null ) ); + assertFalse( constraint.isValid( Money.of( Double.valueOf( "500.2" ), currency ), null ) ); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testNegativeIntegerLength() { + descriptorBuilder.setAttribute( "integer", -1 ); + descriptorBuilder.setAttribute( "fraction", 1 ); + Digits p = descriptorBuilder.build().getAnnotation(); + + DigitsValidatorForMonetaryAmount constraint = new DigitsValidatorForMonetaryAmount(); + constraint.initialize( p ); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testNegativeFractionLength() { + descriptorBuilder.setAttribute( "integer", 1 ); + descriptorBuilder.setAttribute( "fraction", -1 ); + Digits p = descriptorBuilder.build().getAnnotation(); + + DigitsValidatorForMonetaryAmount constraint = new DigitsValidatorForMonetaryAmount(); + constraint.initialize( p ); + } + + @Test + public void testTrailingZerosAreTrimmed() { + descriptorBuilder.setAttribute( "integer", 12 ); + descriptorBuilder.setAttribute( "fraction", 3 ); + Digits p = descriptorBuilder.build().getAnnotation(); + + DigitsValidatorForMonetaryAmount constraint = new DigitsValidatorForMonetaryAmount(); + constraint.initialize( p ); + + CurrencyUnit currency = Monetary.getCurrency( "EUR" ); + + assertTrue( constraint.isValid( Money.of( 0.001d, currency ), null ) ); + assertTrue( constraint.isValid( Money.of( 0.00100d, currency ), null ) ); + assertFalse( constraint.isValid( Money.of( 0.0001d, currency ), null ) ); + } + +} From 3947d9fe987a184b8847b2fa67697392972edbbf Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 16 Jul 2019 13:36:36 +0200 Subject: [PATCH 230/393] HV-1723 Add Dario Seidl to the authors --- copyright.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/copyright.txt b/copyright.txt index 30095168ef..9016a56980 100644 --- a/copyright.txt +++ b/copyright.txt @@ -12,6 +12,7 @@ Chris Beckey Christian Ivan Dag Hovland Damir Alibegovic +Dario Seidl Davide D'Alto Davide Marchignoli Denis Tiago From e84694e9a4a0032e83f77e13e1f4f9e3de17a9bf Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Fri, 21 Jun 2019 13:26:52 +0200 Subject: [PATCH 231/393] HV-1720 Add wildcard type to allowed reference types list --- .../validator/internal/util/TypeHelper.java | 4 +- .../ContainerWithWildcardTest.java | 84 +++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/valueextraction/ContainerWithWildcardTest.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/TypeHelper.java b/engine/src/main/java/org/hibernate/validator/internal/util/TypeHelper.java index a657a582e6..1a348ce20e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/TypeHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/TypeHelper.java @@ -538,6 +538,7 @@ private static boolean isSuperAssignable(Type supertype, Type type) { *
  • a parameterized type
  • *
  • a type variable
  • *
  • the null type
  • + *
  • a wildcard type
  • * * * @param type the type to check @@ -551,7 +552,8 @@ private static boolean isReferenceType(Type type) { || type instanceof Class || type instanceof ParameterizedType || type instanceof TypeVariable - || type instanceof GenericArrayType; + || type instanceof GenericArrayType + || type instanceof WildcardType; } private static boolean isArraySupertype(Class type) { diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/valueextraction/ContainerWithWildcardTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/valueextraction/ContainerWithWildcardTest.java new file mode 100644 index 0000000000..e33456e2e8 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/valueextraction/ContainerWithWildcardTest.java @@ -0,0 +1,84 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.engine.valueextraction; + +import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; +import static org.hibernate.validator.testutils.ValidatorUtil.getValidator; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.testutil.TestForIssue; + +import org.testng.annotations.Test; + +/** + * @author Marko Bekhta + */ +@TestForIssue(jiraKey = "HV-1720") +public class ContainerWithWildcardTest { + + @Test + public void containerWithUpperBoundWildcard() { + Set> constraintViolations = getValidator().validate( new Foo( Arrays.asList( null, null ) ) ); + + assertThat( constraintViolations ).containsOnlyViolations( + violationOf( NotNull.class ), + violationOf( NotNull.class ) + ); + } + + @Test + public void containerWithWildcard() { + Set> constraintViolations = getValidator().validate( new Bar( Arrays.asList( null, null ) ) ); + + assertThat( constraintViolations ).containsOnlyViolations( + violationOf( NotNull.class ), + violationOf( NotNull.class ) + ); + } + + @Test + public void containerWithLowerBoundWildcard() { + Set> constraintViolations = getValidator().validate( new FooBar( Arrays.asList( null, null ) ) ); + + assertThat( constraintViolations ).containsOnlyViolations( + violationOf( NotNull.class ), + violationOf( NotNull.class ) + ); + } + + private static class Foo { + private final List<@NotNull ? extends BigDecimal> list; + + private Foo(List list) { + this.list = list; + } + } + + private static class Bar { + private final List<@NotNull ?> list; + + private Bar(List list) { + this.list = list; + } + } + + private static class FooBar { + private final List<@NotNull ? super BigDecimal> list; + + private FooBar(List list) { + this.list = list; + } + } +} From 27b96b87d777a800b96a8b64fed15dad7f08c266 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 17 Jul 2019 17:37:11 +0200 Subject: [PATCH 232/393] HV-1726 Make PredefinedScopeHibernateValidatorFactory extend HibernateValidatorFactory --- ...definedScopeHibernateValidatorFactory.java | 46 +------------------ .../PredefinedScopeValidatorFactoryImpl.java | 5 +- 2 files changed, 4 insertions(+), 47 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorFactory.java b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorFactory.java index 63d4f52437..7b0586f4f5 100644 --- a/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorFactory.java +++ b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorFactory.java @@ -7,57 +7,13 @@ package org.hibernate.validator; -import java.time.Duration; - import javax.validation.ValidatorFactory; -import org.hibernate.validator.constraints.ParameterScriptAssert; -import org.hibernate.validator.constraints.ScriptAssert; -import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; -import org.hibernate.validator.spi.scripting.ScriptEvaluator; -import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; - /** * Provides Hibernate Validator extensions to {@link ValidatorFactory} in the context of a predefined scope. * * @since 6.1 */ @Incubating -public interface PredefinedScopeHibernateValidatorFactory extends ValidatorFactory { - - /** - * Returns the factory responsible for creating {@link ScriptEvaluator}s used to - * evaluate script expressions of {@link ScriptAssert} and {@link ParameterScriptAssert} - * constraints. - * - * @return a {@link ScriptEvaluatorFactory} instance - */ - @Incubating - ScriptEvaluatorFactory getScriptEvaluatorFactory(); - - /** - * Returns the temporal validation tolerance i.e. the acceptable margin of error when comparing date/time in - * temporal constraints. - * - * @return the tolerance - */ - @Incubating - Duration getTemporalValidationTolerance(); - - /** - * Returns the getter property selection strategy defining the rules determining if a method is a getter or not. - * - * @return the getter property selection strategy of the current {@link ValidatorFactory} - */ - @Incubating - GetterPropertySelectionStrategy getGetterPropertySelectionStrategy(); - - /** - * Returns a context for validator configuration via options from the - * Bean Validation API as well as specific ones from Hibernate Validator. - * - * @return A context for validator configuration. - */ - @Override - HibernateValidatorContext usingContext(); +public interface PredefinedScopeHibernateValidatorFactory extends HibernateValidatorFactory { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java index fc2a1f61be..03cbdb8962 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java @@ -240,8 +240,9 @@ public boolean isTraversableResolverResultCacheEnabled() { @Override public T unwrap(Class type) { - //allow unwrapping into public super types - if ( type.isAssignableFrom( HibernateValidatorFactory.class ) ) { + // allow unwrapping into public super types + if ( type.isAssignableFrom( PredefinedScopeHibernateValidatorFactory.class ) + || type.isAssignableFrom( HibernateValidatorFactory.class ) ) { return type.cast( this ); } throw LOG.getTypeNotSupportedForUnwrappingException( type ); From 80049a40e4a8299396c66fd6665717d67241c5e0 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Fri, 19 Jul 2019 13:47:49 +0000 Subject: [PATCH 233/393] [Jenkins release job] README.md updated by release build 6.1.0.Alpha6 --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5184969913..7a3eedae70 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hibernate Validator -*Version: 6.1.0.Alpha5 - 13-06-2019* +*Version: 6.1.0.Alpha6 - 19-07-2019* ## What is it? @@ -35,7 +35,7 @@ Logging will delegate any log requests to that provider. org.hibernate.validator hibernate-validator - 6.1.0.Alpha5 + 6.1.0.Alpha6 You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. @@ -54,7 +54,7 @@ extension by adding the following dependency: org.hibernate.validator hibernate-validator-cdi - 6.1.0.Alpha5 + 6.1.0.Alpha6 * _hibernate-validator-annotation-processor-<version>.jar_ is an optional jar which can be integrated with your build From aa888aeafa9a8b8b0f80663cdebb7ecb0d55af43 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Fri, 19 Jul 2019 13:47:50 +0000 Subject: [PATCH 234/393] [Jenkins release job] changelog.txt updated by release build 6.1.0.Alpha6 --- changelog.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/changelog.txt b/changelog.txt index 5a7db91774..516e64432f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,20 @@ Hibernate Validator Changelog ============================= +6.1.0.Alpha6 (19-07-2019) +------------------------- + +** Bug + * HV-1722 - engine - Remove settings-example.xml reference from .travis.yml + * HV-1721 - engine - Take into account Hibernate Validator-specific configuration with PredefinedScopeValidatorFactoryImpl + * HV-1720 - engine - Support bounded wildcard types in container value unwrapping + +** New Feature + * HV-1723 - validators - Provide a DigitsValidatorForMonetaryAmount to support @Digits on MonetaryAmounts + +** Task + * HV-1726 - engine - Make PredefinedScopeHibernateValidatorFactory extend HibernateValidatorFactory + 6.1.0.Alpha5 (13-06-2019) ------------------------- From 595438167d4e0642002febf2faef6fae2bfec710 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Fri, 19 Jul 2019 13:47:58 +0000 Subject: [PATCH 235/393] [Jenkins release job] Preparing release 6.1.0.Alpha6 --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 6b70540803..95d7a808bb 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 021058c8f5..aef749ae0e 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index 64d7dc2320..83e3881120 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index d79df95eec..f8827df1a5 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 76e9e2b194..02d727f05f 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index f371e3562c..2013eb83a5 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 85364bd54c..7950ab7932 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index 6ca85e82c6..64cc844ed1 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 55c15d1c8c..99c89f31ca 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 28ce4576ea..74246db7f5 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 1b9ec9f304..8818d1c08e 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index fc4f7e3a85..7cf2f5944c 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index 847461dfe5..446c5fbb05 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 ../pom.xml diff --git a/pom.xml b/pom.xml index b6bf9d5ec6..2abfa87f6e 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 3f99228d35..0164590c8b 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index acc9a54560..d4f340e4e4 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index d793ee6b6e..64005cb08a 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index c2eba20d47..f0d4899375 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 6516654b3f..f4d2b78257 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 469ad132ed..580bd2aedd 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 3b0766e5c7..cbecb908f0 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Alpha6 hibernate-validator-test-utils From 8c176440e061bc831dce677dfbd55db24fa28279 Mon Sep 17 00:00:00 2001 From: Jenkins Date: Fri, 19 Jul 2019 13:51:41 +0000 Subject: [PATCH 236/393] [Jenkins release job] Preparing next development iteration --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 95d7a808bb..6b70540803 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index aef749ae0e..021058c8f5 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index 83e3881120..64d7dc2320 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index f8827df1a5..d79df95eec 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 02d727f05f..76e9e2b194 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index 2013eb83a5..f371e3562c 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 7950ab7932..85364bd54c 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index 64cc844ed1..6ca85e82c6 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 99c89f31ca..55c15d1c8c 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 74246db7f5..28ce4576ea 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 8818d1c08e..1b9ec9f304 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index 7cf2f5944c..fc4f7e3a85 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index 446c5fbb05..847461dfe5 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 2abfa87f6e..b6bf9d5ec6 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 0164590c8b..3f99228d35 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index d4f340e4e4..acc9a54560 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index 64005cb08a..d793ee6b6e 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index f0d4899375..c2eba20d47 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index f4d2b78257..6516654b3f 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 580bd2aedd..469ad132ed 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index cbecb908f0..3b0766e5c7 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Alpha6 + 6.1.0-SNAPSHOT hibernate-validator-test-utils From 3b821ec7e096137e713af8993a99821810877910 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 1 Aug 2019 11:24:23 +0200 Subject: [PATCH 237/393] HV-1728 Upgrade to WildFly 17.0.1.Final --- pom.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index b6bf9d5ec6..de71a97fdb 100644 --- a/pom.xml +++ b/pom.xml @@ -122,9 +122,9 @@ 2.1.0.Final - 16.0.0.Final + 17.0.1.Final - 17.0.0.Beta1 + 16.0.0.Final ${version.wildfly} @@ -145,9 +145,9 @@ See http://search.maven.org/#search|gav|1|g%3A"org.wildfly"%20AND%20a%3A"wildfly-parent" --> 2.0.SP1 - 3.0.5.Final - 2.1.1.Final - 1.0.1.Final + 3.1.1.Final + 2.2.0.Final + 1.0.2.Final 1.0.0.Final From fa20ae1f6dd6d71f340bc4c8c549e98f9e89d4ca Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 1 Aug 2019 10:44:52 +0200 Subject: [PATCH 238/393] HV-1724 Update to OpenJFX 11.0.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index de71a97fdb..45d70c6874 100644 --- a/pom.xml +++ b/pom.xml @@ -157,7 +157,7 @@ 1.2 - 11-ea+19 + 11.0.2 1.1.11.Final From b06721e4997297039ba2a14508aecd5ac3387e22 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 1 Aug 2019 10:59:14 +0200 Subject: [PATCH 239/393] HV-1727 Update Jackson Databind test dependency to 2.9.9.2 --- pom.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 45d70c6874..5579f4179c 100644 --- a/pom.xml +++ b/pom.xml @@ -170,7 +170,8 @@ 27.1-jre 4.3.10.RELEASE 1.0.0.Final - 2.9.9 + 2.9.9.2 + 2.9.9 4.2.0 @@ -496,13 +497,13 @@ com.fasterxml.jackson.core jackson-databind - ${version.com.fasterxml.jackson.core} + ${version.com.fasterxml.jackson.core.jackson-databind} test com.fasterxml.jackson.core jackson-annotations - ${version.com.fasterxml.jackson.core} + ${version.com.fasterxml.jackson.core.jackson-annotations} test From 15a36e56bb1c80f830adfaf2f7a8938588860e62 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Fri, 2 Aug 2019 15:24:27 +0100 Subject: [PATCH 240/393] HV-1729 Skip allocation of an action for each need to access the context classloader --- .../internal/util/privilegedactions/GetClassLoader.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetClassLoader.java b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetClassLoader.java index 9f1a626e94..79a817d456 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetClassLoader.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetClassLoader.java @@ -16,10 +16,13 @@ * @author Emmanuel Bernard */ public final class GetClassLoader implements PrivilegedAction { + + private static final GetClassLoader CONTEXT = new GetClassLoader( null ); + private final Class clazz; public static GetClassLoader fromContext() { - return new GetClassLoader( null ); + return CONTEXT; } public static GetClassLoader fromClass(Class clazz) { From 35a054ef78c86a66ac6a63b290cfa3a79491995d Mon Sep 17 00:00:00 2001 From: Gunnar Morling Date: Tue, 13 Aug 2019 16:27:19 +0200 Subject: [PATCH 241/393] HV-1731 SigTest updates * Moving to tck-runner module * Upgrading to latest version * Enabling strict check --- engine/pom.xml | 52 ---------------------------------------------- pom.xml | 2 +- tck-runner/pom.xml | 40 +++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 53 deletions(-) diff --git a/engine/pom.xml b/engine/pom.xml index f371e3562c..2867cb4415 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -307,57 +307,5 @@ - - sigtest - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-tck-bv-api-signature-file - generate-test-sources - - unpack - - - - - org.hibernate.beanvalidation.tck - beanvalidation-tck-tests - ${version.org.hibernate.beanvalidation.tck} - jar - true - - - - **/*.sig - ${project.build.directory}/api-signature - - - - - - org.netbeans.tools - sigtest-maven-plugin - - - - check - - - - - javax.validation,javax.validation.bootstrap,javax.validation.constraints, - javax.validation.constraintvalidation,javax.validation.executable,javax.validation.groups, - javax.validation.metadata,javax.validation.spi,javax.validation.valueextraction - - ${project.build.directory}/api-signature/validation-api-java8.sig - - - - - diff --git a/pom.xml b/pom.xml index 5579f4179c..ab7ca38f88 100644 --- a/pom.xml +++ b/pom.xml @@ -222,7 +222,7 @@ 2.5.3 3.0.2 3.1.0 - 1.0 + 1.2 3.0.1 2.21.0 ${version.surefire.plugin} diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 469ad132ed..50fa8708ea 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -101,6 +101,27 @@ org.apache.maven.plugins maven-dependency-plugin + + copy-tck-bv-api-signature-file + generate-test-sources + + unpack + + + + + org.hibernate.beanvalidation.tck + beanvalidation-tck-tests + ${version.org.hibernate.beanvalidation.tck} + jar + true + + + + **/*.sig + ${project.build.directory}/api-signature + + copy-tck-test-suite-file generate-test-sources @@ -156,6 +177,25 @@ test-report + + org.netbeans.tools + sigtest-maven-plugin + + + + check + + + + + strictcheck + javax.validation,javax.validation.bootstrap,javax.validation.constraints, + javax.validation.constraintvalidation,javax.validation.executable,javax.validation.groups, + javax.validation.metadata,javax.validation.spi,javax.validation.valueextraction + + ${project.build.directory}/api-signature/validation-api-java8.sig + + From 0f31664ff273e4693ea82df4640cc0119afe8611 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 21 Aug 2019 18:05:48 +0200 Subject: [PATCH 242/393] HV-1731 Move back the sigtest testing into a profile It does not work with JDK 11+ as a deprecated annotation has been added to Object#finalize(). It's built with a specific CI job. --- tck-runner/pom.xml | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 50fa8708ea..e34ebfc67e 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -177,25 +177,6 @@ test-report - - org.netbeans.tools - sigtest-maven-plugin - - - - check - - - - - strictcheck - javax.validation,javax.validation.bootstrap,javax.validation.constraints, - javax.validation.constraintvalidation,javax.validation.executable,javax.validation.groups, - javax.validation.metadata,javax.validation.spi,javax.validation.valueextraction - - ${project.build.directory}/api-signature/validation-api-java8.sig - - @@ -383,6 +364,32 @@ + + sigtest + + + + org.netbeans.tools + sigtest-maven-plugin + + + + check + + + + + strictcheck + javax.validation,javax.validation.bootstrap,javax.validation.constraints, + javax.validation.constraintvalidation,javax.validation.executable,javax.validation.groups, + javax.validation.metadata,javax.validation.spi,javax.validation.valueextraction + + ${project.build.directory}/api-signature/validation-api-java8.sig + + + + + jdk9+ From 4b9f1a172a0b66aa5cd4f82ae916b78afa856e6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szynkiewicz?= Date: Mon, 9 Sep 2019 14:19:47 +0200 Subject: [PATCH 243/393] HV-1732 Change tarLongFileMode to posix for assembly building totoz tat The currently selected gnu results in the following errors in environments with large user ids: Execution make-assembly of goal org.apache.maven.plugins:maven-assembly-plugin:3.1.0:single failed: user id '...' is too big --- distribution/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distribution/pom.xml b/distribution/pom.xml index d79df95eec..1b573a898c 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -166,7 +166,7 @@ ${basedir}/src/main/assembly/dist.xml hibernate-validator-${project.version} - gnu + posix ${project.build.directory}/dist/ From 4f422302ab8232dd57e0f1b742b4fa148b63caae Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Thu, 13 Dec 2018 23:10:46 +0100 Subject: [PATCH 244/393] HV-1680 Add EnhancedBean marker interface and use it when possible - Add HibernateValidatorEnhancedBean that exposes getter and field values - Check if bean implements this marker interface and if it is - use it to access getters and fields for faster access and to omit usage of reflection --- .../HibernateValidatorEnhancedBean.java | 41 +++++++ .../properties/javabean/JavaBeanField.java | 25 ++++- .../properties/javabean/JavaBeanGetter.java | 24 ++++- .../validator/internal/util/TypeHelper.java | 5 + .../engine/EnhancedBeanAccessorTest.java | 102 ++++++++++++++++++ .../test/internal/util/TypeHelperTest.java | 21 ++++ 6 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/engine/HibernateValidatorEnhancedBean.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/EnhancedBeanAccessorTest.java diff --git a/engine/src/main/java/org/hibernate/validator/engine/HibernateValidatorEnhancedBean.java b/engine/src/main/java/org/hibernate/validator/engine/HibernateValidatorEnhancedBean.java new file mode 100644 index 0000000000..fa7d8285ec --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/engine/HibernateValidatorEnhancedBean.java @@ -0,0 +1,41 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.engine; + +/** + * Hibernate Validator specific marker interface. Beans implementing this interface + * would use corresponding {@link HibernateValidatorEnhancedBean#getFieldValue(String)} + * and {@link HibernateValidatorEnhancedBean#getGetterValue(String)} methods to retrieve + * bean property values instead of using reflection or any other means. + *

    + * It is important to keep in mind that in case of explicit implementation of this interface + * access to all possible constrained getters and fields should be provided, for a class implementing + * the interface and all its super classes as well. Otherwise unexpected {@link IllegalArgumentException} + * could be thrown by the Hibernate Validator engine. + * + * @author Marko Bekhta + * @since 6.1 + */ +public interface HibernateValidatorEnhancedBean { + /** + * @param name the name of a field property of interest. + * + * @return the value of the field named {@code name} of the current bean. + * + * @throws IllegalArgumentException in case no field could be found for the given name. + */ + Object getFieldValue(String name); + + /** + * @param name the name of a getter of interest. + * + * @return the value returned by the getter named {@code name} of the current bean. + * + * @throws IllegalArgumentException in case when no getter property could be found for the given name. + */ + Object getGetterValue(String name); +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java index a45fefe27d..a08ff8638c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java @@ -6,6 +6,8 @@ */ package org.hibernate.validator.internal.properties.javabean; +import static org.hibernate.validator.internal.util.TypeHelper.isHibernateValidatorEnhancedBean; + import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedType; import java.lang.reflect.Field; @@ -15,6 +17,7 @@ import java.security.PrivilegedAction; import org.hibernate.validator.HibernateValidatorPermission; +import org.hibernate.validator.engine.HibernateValidatorEnhancedBean; import org.hibernate.validator.internal.properties.PropertyAccessor; import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredField; @@ -93,7 +96,12 @@ public TypeVariable[] getTypeParameters() { @Override public PropertyAccessor createAccessor() { - return new FieldAccessor( field ); + if ( isHibernateValidatorEnhancedBean( field.getDeclaringClass() ) ) { + return new EnhancedBeanFieldAccessor( field.getName() ); + } + else { + return new FieldAccessor( field ); + } } @Override @@ -129,6 +137,21 @@ public String toString() { return getName(); } + private static class EnhancedBeanFieldAccessor implements PropertyAccessor { + + private final String name; + + private EnhancedBeanFieldAccessor(final String name) { + this.name = name; + } + + @Override + public Object getValueFrom(Object bean) { + // we don't do an instanceof check here as it should already be applied when the accessor was created. + return ( (HibernateValidatorEnhancedBean) bean ).getFieldValue( name ); + } + } + private static class FieldAccessor implements PropertyAccessor { private Field accessibleField; diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java index ae6d0cb74d..f7133e8148 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java @@ -6,11 +6,14 @@ */ package org.hibernate.validator.internal.properties.javabean; +import static org.hibernate.validator.internal.util.TypeHelper.isHibernateValidatorEnhancedBean; + import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; import org.hibernate.validator.HibernateValidatorPermission; +import org.hibernate.validator.engine.HibernateValidatorEnhancedBean; import org.hibernate.validator.internal.metadata.raw.ConstrainedElement.ConstrainedElementKind; import org.hibernate.validator.internal.properties.Getter; import org.hibernate.validator.internal.properties.PropertyAccessor; @@ -83,7 +86,13 @@ public ConstrainedElementKind getConstrainedElementKind() { @Override public PropertyAccessor createAccessor() { - return new GetterAccessor( executable ); + if ( isHibernateValidatorEnhancedBean( executable.getDeclaringClass() ) ) { + return new EnhancedBeanGetterAccessor( executable.getName() ); + } + else { + return new GetterAccessor( executable ); + } + } @Override @@ -110,6 +119,19 @@ public int hashCode() { return result; } + private static class EnhancedBeanGetterAccessor implements PropertyAccessor { + private final String getterFullName; + + private EnhancedBeanGetterAccessor(final String getterFullName) { + this.getterFullName = getterFullName; + } + + @Override + public Object getValueFrom(Object bean) { + // we don't do an instanceof check here as it should already be applied when the accessor was created. + return ( (HibernateValidatorEnhancedBean) bean ).getGetterValue( getterFullName ); + } + } private static class GetterAccessor implements PropertyAccessor { private Method accessibleGetter; diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/TypeHelper.java b/engine/src/main/java/org/hibernate/validator/internal/util/TypeHelper.java index 1a348ce20e..0a4e0c1318 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/TypeHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/TypeHelper.java @@ -40,6 +40,7 @@ import javax.validation.ConstraintValidator; +import org.hibernate.validator.engine.HibernateValidatorEnhancedBean; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorDescriptor; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -77,6 +78,10 @@ private TypeHelper() { throw new AssertionError(); } + public static boolean isHibernateValidatorEnhancedBean(Class clazz) { + return HibernateValidatorEnhancedBean.class.isAssignableFrom( clazz ); + } + public static boolean isAssignable(Type supertype, Type type) { Contracts.assertNotNull( supertype, "supertype" ); Contracts.assertNotNull( type, "type" ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/EnhancedBeanAccessorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/EnhancedBeanAccessorTest.java new file mode 100644 index 0000000000..cbd5cf70e0 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/EnhancedBeanAccessorTest.java @@ -0,0 +1,102 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.engine; + +import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; +import static org.hibernate.validator.testutils.ValidatorUtil.getValidator; + +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.Validator; +import javax.validation.constraints.AssertTrue; +import javax.validation.constraints.Min; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Positive; + +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.engine.HibernateValidatorEnhancedBean; +import org.hibernate.validator.testutil.TestForIssue; + +import org.testng.annotations.Test; + +/** + * @author Marko Bekhta + */ +@TestForIssue(jiraKey = "HV-1680") +public class EnhancedBeanAccessorTest { + @Test + public void testValidatePropertyWithRedefinedDefaultGroupOnMainEntity() { + Validator validator = getValidator(); + Foo foo = new Foo(); + + Set> constraintViolations = validator.validate( foo ); + + assertThat( constraintViolations ).containsOnlyViolations( + violationOf( Pattern.class ).withProperty( "string" ), + violationOf( Positive.class ).withProperty( "num" ), + violationOf( Min.class ).withProperty( "looooong" ), + violationOf( Length.class ).withProperty( "message" ), + violationOf( AssertTrue.class ).withProperty( "key" ) + ); + } + + private static class Foo implements HibernateValidatorEnhancedBean { + @Pattern(regexp = "[A-Z]") + private String string; + @Positive + private Integer num; + @Min(100_000L) + private long looooong; + + public Foo() { + this( "test", -1, 100L ); + } + + public Foo(final String string, final Integer num, final long looooong) { + this.string = string; + this.num = num; + this.looooong = looooong; + } + + @Length(min = 100) + public String getMessage() { + return "messssssage"; + } + + @AssertTrue + public boolean getKey() { + return false; + } + + @Override + public Object getFieldValue(String name) { + if ( "string".equals( name ) ) { + return string; + } + if ( "num".equals( name ) ) { + return num; + } + if ( "looooong".equals( name ) ) { + return looooong; + } + throw new IllegalArgumentException( "No such property as '" + name + "'" ); + } + + @Override + public Object getGetterValue(String name) { + if ( "getKey".equals( name ) ) { + return getKey(); + } + if ( "getMessage".equals( name ) ) { + return getMessage(); + } + throw new IllegalArgumentException( "No such property as '" + name + "'" ); + } + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/util/TypeHelperTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/util/TypeHelperTest.java index efe128ad6a..0b28f4787f 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/util/TypeHelperTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/util/TypeHelperTest.java @@ -40,9 +40,11 @@ import java.util.Map; import java.util.Set; +import org.hibernate.validator.engine.HibernateValidatorEnhancedBean; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorDescriptor; import org.hibernate.validator.internal.util.TypeHelper; import org.hibernate.validator.testutil.TestForIssue; + import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -875,6 +877,25 @@ public void testTypeHelperDoesntGoIntoInfiniteLoop() { assertTrue( TypeHelper.isAssignable( parentEntityType, childEntityType ) ); } + @Test + public void testIsHibernateValidatorEnhancedBean() { + class Foo { + } + class Bar implements HibernateValidatorEnhancedBean { + @Override + public Object getFieldValue(String name) { + return null; + } + + @Override + public Object getGetterValue(String name) { + return null; + } + } + assertTrue( TypeHelper.isHibernateValidatorEnhancedBean( Bar.class ) ); + assertFalse( TypeHelper.isHibernateValidatorEnhancedBean( Foo.class ) ); + } + private static void assertAsymmetricallyAssignable(Type supertype, Type type) { assertAssignable( supertype, type ); assertUnassignable( type, supertype ); From 9776680e68dcb2333ffb2f9ec04a8ff1ab0ec7c2 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Fri, 14 Dec 2018 22:21:36 +0100 Subject: [PATCH 245/393] HV-1680 Add a test using ByteBuddy for the enhancement --- engine/pom.xml | 5 + .../engine/EnhancedBeanAccessorTest.java | 25 +- .../bytebuddy/ByteBuddyWrapperTest.java | 369 ++++++++++++++++++ pom.xml | 7 + 4 files changed, 404 insertions(+), 2 deletions(-) create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/metadata/bytebuddy/ByteBuddyWrapperTest.java diff --git a/engine/pom.xml b/engine/pom.xml index 2867cb4415..c9ecf37108 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -157,6 +157,11 @@ jackson-annotations test + + net.bytebuddy + byte-buddy + test + diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/EnhancedBeanAccessorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/EnhancedBeanAccessorTest.java index cbd5cf70e0..6b84d7de72 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/EnhancedBeanAccessorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/EnhancedBeanAccessorTest.java @@ -10,12 +10,15 @@ import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; import static org.hibernate.validator.testutils.ValidatorUtil.getValidator; +import java.util.Collections; +import java.util.List; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validator; import javax.validation.constraints.AssertTrue; import javax.validation.constraints.Min; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.Pattern; import javax.validation.constraints.Positive; @@ -33,7 +36,7 @@ public class EnhancedBeanAccessorTest { @Test public void testValidatePropertyWithRedefinedDefaultGroupOnMainEntity() { Validator validator = getValidator(); - Foo foo = new Foo(); + Foo foo = new Bar(); Set> constraintViolations = validator.validate( foo ); @@ -42,10 +45,28 @@ public void testValidatePropertyWithRedefinedDefaultGroupOnMainEntity() { violationOf( Positive.class ).withProperty( "num" ), violationOf( Min.class ).withProperty( "looooong" ), violationOf( Length.class ).withProperty( "message" ), - violationOf( AssertTrue.class ).withProperty( "key" ) + violationOf( AssertTrue.class ).withProperty( "key" ), + violationOf( NotEmpty.class ).withProperty( "strings" ) ); } + private static class Bar extends Foo implements HibernateValidatorEnhancedBean { + @NotEmpty + private final List strings; + + private Bar() { + this.strings = Collections.emptyList(); + } + + @Override + public Object getFieldValue(String name) { + if ( "strings".equals( name ) ) { + return strings; + } + return super.getFieldValue( name ); + } + } + private static class Foo implements HibernateValidatorEnhancedBean { @Pattern(regexp = "[A-Z]") private String string; diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/bytebuddy/ByteBuddyWrapperTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/bytebuddy/ByteBuddyWrapperTest.java new file mode 100644 index 0000000000..59e0058b74 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/bytebuddy/ByteBuddyWrapperTest.java @@ -0,0 +1,369 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.metadata.bytebuddy; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.assertj.core.api.Assertions.assertThat; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.List; + +import org.hibernate.validator.engine.HibernateValidatorEnhancedBean; +import org.hibernate.validator.internal.util.StringHelper; + +import net.bytebuddy.ByteBuddy; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.dynamic.ClassFileLocator; +import net.bytebuddy.dynamic.loading.ByteArrayClassLoader; +import net.bytebuddy.dynamic.loading.ClassLoadingStrategy; +import net.bytebuddy.implementation.Implementation; +import net.bytebuddy.implementation.bytecode.ByteCodeAppender; +import net.bytebuddy.implementation.bytecode.assign.Assigner; +import net.bytebuddy.implementation.bytecode.assign.primitive.PrimitiveBoxingDelegate; +import net.bytebuddy.implementation.bytecode.assign.reference.ReferenceTypeAwareAssigner; +import net.bytebuddy.jar.asm.Label; +import net.bytebuddy.jar.asm.MethodVisitor; +import net.bytebuddy.jar.asm.Opcodes; +import net.bytebuddy.jar.asm.Type; +import net.bytebuddy.matcher.ElementMatchers; +import org.testng.annotations.Test; + +/** + * @author Marko Bekhta + */ +public class ByteBuddyWrapperTest { + + + @Test + public void testByteBuddy() throws Exception { + Class clazz = Foo.class; + + ClassLoader classLoader = new ByteArrayClassLoader( + ClassLoadingStrategy.BOOTSTRAP_LOADER, + ClassFileLocator.ForClassLoader.readToNames( Foo.class, HibernateValidatorEnhancedBean.class, + MyContracts.class, StringHelper.class ) ); + + Class aClass = new ByteBuddy().rebase( clazz ) + .implement( HibernateValidatorEnhancedBean.class ) + .method( + named( "getFieldValue" ) + .and( ElementMatchers.takesArguments( String.class ) ) + .and( ElementMatchers.returns( Object.class ) ) + ) + .intercept( new Implementation.Simple( new GetFieldValue( clazz ) ) ) + .method( + named( "getGetterValue" ) + .and( ElementMatchers.takesArguments( String.class ) ) + .and( ElementMatchers.returns( Object.class ) ) + ) + .intercept( new Implementation.Simple( new GetGetterValue( clazz ) ) ) + .make() + .load( classLoader, ClassLoadingStrategy.Default.INJECTION ) + .getLoaded(); + + Object object = aClass.newInstance(); + + Method getFieldValue = aClass.getMethod( "getFieldValue", String.class ); + + assertThat( getFieldValue.invoke( object, "num" ) ).isEqualTo( -1 ); + assertThat( getFieldValue.invoke( object, "string" ) ).isEqualTo( "test" ); + assertThat( getFieldValue.invoke( object, "looooong" ) ).isEqualTo( 100L ); + + Method getGetterValue = aClass.getMethod( "getGetterValue", String.class ); + + assertThat( getGetterValue.invoke( object, "getMessage" ) ).isEqualTo( "messssssage" ); + assertThat( getGetterValue.invoke( object, "getKey" ) ).isEqualTo( false ); + } + + private static class GetFieldValue implements ByteCodeAppender { + + private final Class clazz; + + private final Field[] fields; + + public GetFieldValue(Class clazz) { + this.clazz = clazz; + this.fields = clazz.getDeclaredFields(); + } + + @Override + public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext, MethodDescription instrumentedMethod) { + try { + // Contracts.assertNotEmpty(propertyName, "Property cannot be blank"); + Label contractsPropertyNameCheckLabel = new Label(); + methodVisitor.visitLabel( contractsPropertyNameCheckLabel ); + methodVisitor.visitVarInsn( Opcodes.ALOAD, 1 ); + methodVisitor.visitLdcInsn( "Property cannot be blank" ); + methodVisitor.visitMethodInsn( + Opcodes.INVOKESTATIC, + Type.getType( MyContracts.class ).getInternalName(), + "assertNotEmpty", + Type.getType( MyContracts.class.getDeclaredMethod( "assertNotEmpty", String.class, String.class ) ).getDescriptor(), + false + ); + + Label l1 = new Label(); + methodVisitor.visitLabel( l1 ); + int index = 0; + for ( Field field : fields ) { + String fieldName = field.getName(); + + if ( index > 0 ) { + methodVisitor.visitFrame( Opcodes.F_SAME, 0, null, 0, null ); + } + + // if (propertyName.equals(field_name_goes_here)) { + // return field; + // } + methodVisitor.visitVarInsn( Opcodes.ALOAD, 1 ); + methodVisitor.visitLdcInsn( fieldName ); + methodVisitor.visitMethodInsn( + Opcodes.INVOKEVIRTUAL, + Type.getType( String.class ).getInternalName(), + "equals", + Type.getType( String.class.getDeclaredMethod( "equals", Object.class ) ).getDescriptor(), + false + ); + + Label ifCheckLabel = new Label(); + methodVisitor.visitJumpInsn( Opcodes.IFEQ, ifCheckLabel ); + + Label returnFieldLabel = new Label(); + methodVisitor.visitLabel( returnFieldLabel ); + methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 ); + methodVisitor.visitFieldInsn( + Opcodes.GETFIELD, + Type.getInternalName( clazz ), + fieldName, + Type.getDescriptor( field.getType() ) + ); + if ( field.getType().isPrimitive() ) { + PrimitiveBoxingDelegate.forPrimitive( new TypeDescription.ForLoadedType( field.getType() ) ) + .assignBoxedTo( + TypeDescription.Generic.OBJECT, + ReferenceTypeAwareAssigner.INSTANCE, + Assigner.Typing.STATIC + ) + .apply( methodVisitor, implementationContext ); + } + methodVisitor.visitInsn( Opcodes.ARETURN ); + methodVisitor.visitLabel( ifCheckLabel ); + + index++; + } + + // throw new IllegalArgumentException("No property was found for a given name"); + + methodVisitor.visitFrame( Opcodes.F_SAME, 0, null, 0, null ); + methodVisitor.visitTypeInsn( Opcodes.NEW, Type.getInternalName( IllegalArgumentException.class ) ); + methodVisitor.visitInsn( Opcodes.DUP ); + methodVisitor.visitLdcInsn( "No property was found for a given name" ); + methodVisitor.visitMethodInsn( + Opcodes.INVOKESPECIAL, + Type.getInternalName( IllegalArgumentException.class ), + "", + Type.getType( IllegalArgumentException.class.getDeclaredConstructor( String.class ) ).getDescriptor(), + false + ); + methodVisitor.visitInsn( Opcodes.ATHROW ); + + Label label = new Label(); + methodVisitor.visitLabel( label ); + methodVisitor.visitLocalVariable( + "this", + Type.getDescriptor( clazz ), + null, + contractsPropertyNameCheckLabel, + label, + 0 + ); + methodVisitor.visitLocalVariable( + "name", + Type.getDescriptor( String.class ), + null, + contractsPropertyNameCheckLabel, + label, + 1 + ); + methodVisitor.visitMaxs( 3, 2 ); + + return new Size( 6, instrumentedMethod.getStackSize() ); + } + catch (NoSuchMethodException e) { + throw new IllegalArgumentException( e ); + } + } + } + + private static class GetGetterValue implements ByteCodeAppender { + + private final Class clazz; + + private final Method[] methods; + + public GetGetterValue(Class clazz) { + this.clazz = clazz; + this.methods = clazz.getDeclaredMethods(); + } + + @Override + public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext, MethodDescription instrumentedMethod) { + try { + // Contracts.assertNotEmpty(propertyName, "Property cannot be blank"); + Label contractsPropertyNameCheckLabel = new Label(); + methodVisitor.visitLabel( contractsPropertyNameCheckLabel ); + methodVisitor.visitVarInsn( Opcodes.ALOAD, 1 ); + methodVisitor.visitLdcInsn( "Property cannot be blank" ); + methodVisitor.visitMethodInsn( + Opcodes.INVOKESTATIC, + Type.getType( MyContracts.class ).getInternalName(), + "assertNotEmpty", + Type.getType( MyContracts.class.getDeclaredMethod( "assertNotEmpty", String.class, String.class ) ).getDescriptor(), + false + ); + + Label l1 = new Label(); + methodVisitor.visitLabel( l1 ); + int index = 0; + for ( Method method : methods ) { + String fieldName = method.getName(); + + if ( index > 0 ) { + methodVisitor.visitFrame( Opcodes.F_SAME, 0, null, 0, null ); + } + + // if (propertyName.equals(field_name_goes_here)) { + // return field; + // } + methodVisitor.visitVarInsn( Opcodes.ALOAD, 1 ); + methodVisitor.visitLdcInsn( fieldName ); + methodVisitor.visitMethodInsn( + Opcodes.INVOKEVIRTUAL, + Type.getType( String.class ).getInternalName(), + "equals", + Type.getType( String.class.getDeclaredMethod( "equals", Object.class ) ).getDescriptor(), + false + ); + + Label ifCheckLabel = new Label(); + methodVisitor.visitJumpInsn( Opcodes.IFEQ, ifCheckLabel ); + + Label returnFieldLabel = new Label(); + methodVisitor.visitLabel( returnFieldLabel ); + methodVisitor.visitVarInsn( Opcodes.ALOAD, 0 ); + methodVisitor.visitMethodInsn( + Opcodes.INVOKEVIRTUAL, + Type.getInternalName( clazz ), + method.getName(), + Type.getMethodDescriptor( method ), + method.getDeclaringClass().isInterface() + ); + if ( method.getReturnType().isPrimitive() ) { + PrimitiveBoxingDelegate.forPrimitive( new TypeDescription.ForLoadedType( method.getReturnType() ) ) + .assignBoxedTo( + TypeDescription.Generic.OBJECT, + ReferenceTypeAwareAssigner.INSTANCE, + Assigner.Typing.STATIC + ) + .apply( methodVisitor, implementationContext ); + } + methodVisitor.visitInsn( Opcodes.ARETURN ); + methodVisitor.visitLabel( ifCheckLabel ); + + index++; + } + + // throw new IllegalArgumentException("No property was found for a given name"); + + methodVisitor.visitFrame( Opcodes.F_SAME, 0, null, 0, null ); + methodVisitor.visitTypeInsn( Opcodes.NEW, Type.getInternalName( IllegalArgumentException.class ) ); + methodVisitor.visitInsn( Opcodes.DUP ); + methodVisitor.visitLdcInsn( "No property was found for a given name" ); + methodVisitor.visitMethodInsn( + Opcodes.INVOKESPECIAL, + Type.getInternalName( IllegalArgumentException.class ), + "", + Type.getType( IllegalArgumentException.class.getDeclaredConstructor( String.class ) ).getDescriptor(), + false + ); + methodVisitor.visitInsn( Opcodes.ATHROW ); + + Label label = new Label(); + methodVisitor.visitLabel( label ); + methodVisitor.visitLocalVariable( + "this", + Type.getDescriptor( clazz ), + null, + contractsPropertyNameCheckLabel, + label, + 0 + ); + methodVisitor.visitLocalVariable( + "name", + Type.getDescriptor( String.class ), + null, + contractsPropertyNameCheckLabel, + label, + 1 + ); + methodVisitor.visitMaxs( 3, 2 ); + + return new Size( 6, instrumentedMethod.getStackSize() ); + } + catch (NoSuchMethodException e) { + throw new IllegalArgumentException( e ); + } + } + } + + + public static class Foo { + private String string; + private Integer num; + private long looooong; + + public Foo() { + this( "test", -1 ); + this.looooong = 100L; + } + + public Foo(String string, Integer num) { + this.string = string; + this.num = num; + } + + public String getMessage() { + return "messssssage"; + } + + public boolean getKey() { + return false; + } + } + + + public static class Bar extends Foo { + private final List strings; + + public Bar() { + super(); + this.strings = Collections.emptyList(); + } + } + + public static final class MyContracts { + public static void assertNotEmpty(String s, String message) { + if ( StringHelper.isNullOrEmptyString( s ) ) { + throw new IllegalArgumentException( message ); + } + } + } + +} diff --git a/pom.xml b/pom.xml index ab7ca38f88..74e3fa92f8 100644 --- a/pom.xml +++ b/pom.xml @@ -153,6 +153,7 @@ 1.0.1 1.1 + 1.2 @@ -172,6 +173,7 @@ 1.0.0.Final 2.9.9.2 2.9.9 + 1.10.1 4.2.0 @@ -363,6 +365,11 @@ moneta ${version.org.javamoney.moneta} + + net.bytebuddy + byte-buddy + ${version.net.bytebuddy.byte-buddy} + org.osgi org.osgi.core From 0e34732f77f529b4c25b658585a45022f4c1aead Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 22 Aug 2019 16:05:44 +0200 Subject: [PATCH 246/393] HV-1680 Prefix the method names to avoid conflicts We want to be able to add these methods to arbitrary code so we'd better prefix their names to avoid conflict with potentially preexisting methods. Also create constants for the names as we will have to generate them so better have proper constants in line with the interface. --- .../engine/HibernateValidatorEnhancedBean.java | 13 +++++++++---- .../properties/javabean/JavaBeanField.java | 2 +- .../properties/javabean/JavaBeanGetter.java | 2 +- .../engine/EnhancedBeanAccessorTest.java | 8 ++++---- .../metadata/bytebuddy/ByteBuddyWrapperTest.java | 16 ++++++++++------ .../test/internal/util/TypeHelperTest.java | 4 ++-- 6 files changed, 27 insertions(+), 18 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/engine/HibernateValidatorEnhancedBean.java b/engine/src/main/java/org/hibernate/validator/engine/HibernateValidatorEnhancedBean.java index fa7d8285ec..6ef26e3096 100644 --- a/engine/src/main/java/org/hibernate/validator/engine/HibernateValidatorEnhancedBean.java +++ b/engine/src/main/java/org/hibernate/validator/engine/HibernateValidatorEnhancedBean.java @@ -8,8 +8,8 @@ /** * Hibernate Validator specific marker interface. Beans implementing this interface - * would use corresponding {@link HibernateValidatorEnhancedBean#getFieldValue(String)} - * and {@link HibernateValidatorEnhancedBean#getGetterValue(String)} methods to retrieve + * would use corresponding {@link HibernateValidatorEnhancedBean#$$_hibernateValidator_getFieldValue(String)} + * and {@link HibernateValidatorEnhancedBean#$$_hibernateValidator_getGetterValue(String)} methods to retrieve * bean property values instead of using reflection or any other means. *

    * It is important to keep in mind that in case of explicit implementation of this interface @@ -21,6 +21,11 @@ * @since 6.1 */ public interface HibernateValidatorEnhancedBean { + + String GET_FIELD_VALUE_METHOD_NAME = "$$_hibernateValidator_getFieldValue"; + + String GET_GETTER_VALUE_METHOD_NAME = "$$_hibernateValidator_getGetterValue"; + /** * @param name the name of a field property of interest. * @@ -28,7 +33,7 @@ public interface HibernateValidatorEnhancedBean { * * @throws IllegalArgumentException in case no field could be found for the given name. */ - Object getFieldValue(String name); + Object $$_hibernateValidator_getFieldValue(String name); /** * @param name the name of a getter of interest. @@ -37,5 +42,5 @@ public interface HibernateValidatorEnhancedBean { * * @throws IllegalArgumentException in case when no getter property could be found for the given name. */ - Object getGetterValue(String name); + Object $$_hibernateValidator_getGetterValue(String name); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java index a08ff8638c..88bc06db46 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanField.java @@ -148,7 +148,7 @@ private EnhancedBeanFieldAccessor(final String name) { @Override public Object getValueFrom(Object bean) { // we don't do an instanceof check here as it should already be applied when the accessor was created. - return ( (HibernateValidatorEnhancedBean) bean ).getFieldValue( name ); + return ( (HibernateValidatorEnhancedBean) bean ).$$_hibernateValidator_getFieldValue( name ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java index f7133e8148..fb83ba3ee5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanGetter.java @@ -129,7 +129,7 @@ private EnhancedBeanGetterAccessor(final String getterFullName) { @Override public Object getValueFrom(Object bean) { // we don't do an instanceof check here as it should already be applied when the accessor was created. - return ( (HibernateValidatorEnhancedBean) bean ).getGetterValue( getterFullName ); + return ( (HibernateValidatorEnhancedBean) bean ).$$_hibernateValidator_getGetterValue( getterFullName ); } } private static class GetterAccessor implements PropertyAccessor { diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/EnhancedBeanAccessorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/EnhancedBeanAccessorTest.java index 6b84d7de72..0671f6feed 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/EnhancedBeanAccessorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/EnhancedBeanAccessorTest.java @@ -59,11 +59,11 @@ private Bar() { } @Override - public Object getFieldValue(String name) { + public Object $$_hibernateValidator_getFieldValue(String name) { if ( "strings".equals( name ) ) { return strings; } - return super.getFieldValue( name ); + return super.$$_hibernateValidator_getFieldValue( name ); } } @@ -96,7 +96,7 @@ public boolean getKey() { } @Override - public Object getFieldValue(String name) { + public Object $$_hibernateValidator_getFieldValue(String name) { if ( "string".equals( name ) ) { return string; } @@ -110,7 +110,7 @@ public Object getFieldValue(String name) { } @Override - public Object getGetterValue(String name) { + public Object $$_hibernateValidator_getGetterValue(String name) { if ( "getKey".equals( name ) ) { return getKey(); } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/bytebuddy/ByteBuddyWrapperTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/bytebuddy/ByteBuddyWrapperTest.java index 59e0058b74..90a5c8a65d 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/bytebuddy/ByteBuddyWrapperTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/bytebuddy/ByteBuddyWrapperTest.java @@ -40,7 +40,6 @@ */ public class ByteBuddyWrapperTest { - @Test public void testByteBuddy() throws Exception { Class clazz = Foo.class; @@ -53,13 +52,13 @@ public void testByteBuddy() throws Exception { Class aClass = new ByteBuddy().rebase( clazz ) .implement( HibernateValidatorEnhancedBean.class ) .method( - named( "getFieldValue" ) + named( HibernateValidatorEnhancedBean.GET_FIELD_VALUE_METHOD_NAME ) .and( ElementMatchers.takesArguments( String.class ) ) .and( ElementMatchers.returns( Object.class ) ) ) .intercept( new Implementation.Simple( new GetFieldValue( clazz ) ) ) .method( - named( "getGetterValue" ) + named( HibernateValidatorEnhancedBean.GET_GETTER_VALUE_METHOD_NAME ) .and( ElementMatchers.takesArguments( String.class ) ) .and( ElementMatchers.returns( Object.class ) ) ) @@ -70,13 +69,13 @@ public void testByteBuddy() throws Exception { Object object = aClass.newInstance(); - Method getFieldValue = aClass.getMethod( "getFieldValue", String.class ); + Method getFieldValue = aClass.getMethod( HibernateValidatorEnhancedBean.GET_FIELD_VALUE_METHOD_NAME, String.class ); assertThat( getFieldValue.invoke( object, "num" ) ).isEqualTo( -1 ); assertThat( getFieldValue.invoke( object, "string" ) ).isEqualTo( "test" ); assertThat( getFieldValue.invoke( object, "looooong" ) ).isEqualTo( 100L ); - Method getGetterValue = aClass.getMethod( "getGetterValue", String.class ); + Method getGetterValue = aClass.getMethod( HibernateValidatorEnhancedBean.GET_GETTER_VALUE_METHOD_NAME, String.class ); assertThat( getGetterValue.invoke( object, "getMessage" ) ).isEqualTo( "messssssage" ); assertThat( getGetterValue.invoke( object, "getKey" ) ).isEqualTo( false ); @@ -84,10 +83,12 @@ public void testByteBuddy() throws Exception { private static class GetFieldValue implements ByteCodeAppender { + @SuppressWarnings("rawtypes") private final Class clazz; private final Field[] fields; + @SuppressWarnings("rawtypes") public GetFieldValue(Class clazz) { this.clazz = clazz; this.fields = clazz.getDeclaredFields(); @@ -204,10 +205,12 @@ public Size apply(MethodVisitor methodVisitor, Implementation.Context implementa private static class GetGetterValue implements ByteCodeAppender { + @SuppressWarnings("rawtypes") private final Class clazz; private final Method[] methods; + @SuppressWarnings("rawtypes") public GetGetterValue(Class clazz) { this.clazz = clazz; this.methods = clazz.getDeclaredMethods(); @@ -324,6 +327,7 @@ public Size apply(MethodVisitor methodVisitor, Implementation.Context implementa } + @SuppressWarnings("unused") public static class Foo { private String string; private Integer num; @@ -348,7 +352,7 @@ public boolean getKey() { } } - + @SuppressWarnings("unused") public static class Bar extends Foo { private final List strings; diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/util/TypeHelperTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/util/TypeHelperTest.java index 0b28f4787f..1e1dcf547a 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/util/TypeHelperTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/util/TypeHelperTest.java @@ -883,12 +883,12 @@ class Foo { } class Bar implements HibernateValidatorEnhancedBean { @Override - public Object getFieldValue(String name) { + public Object $$_hibernateValidator_getFieldValue(String name) { return null; } @Override - public Object getGetterValue(String name) { + public Object $$_hibernateValidator_getGetterValue(String name) { return null; } } From cb6866c98b8f577ea94d64388059eef5dae31abe Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 10 Sep 2019 10:27:07 +0200 Subject: [PATCH 247/393] HV-1680 Mark HibernateValidatorEnhancedBean as @Incubating --- .../validator/engine/HibernateValidatorEnhancedBean.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/engine/src/main/java/org/hibernate/validator/engine/HibernateValidatorEnhancedBean.java b/engine/src/main/java/org/hibernate/validator/engine/HibernateValidatorEnhancedBean.java index 6ef26e3096..d2818b6b92 100644 --- a/engine/src/main/java/org/hibernate/validator/engine/HibernateValidatorEnhancedBean.java +++ b/engine/src/main/java/org/hibernate/validator/engine/HibernateValidatorEnhancedBean.java @@ -6,6 +6,8 @@ */ package org.hibernate.validator.engine; +import org.hibernate.validator.Incubating; + /** * Hibernate Validator specific marker interface. Beans implementing this interface * would use corresponding {@link HibernateValidatorEnhancedBean#$$_hibernateValidator_getFieldValue(String)} @@ -20,6 +22,7 @@ * @author Marko Bekhta * @since 6.1 */ +@Incubating public interface HibernateValidatorEnhancedBean { String GET_FIELD_VALUE_METHOD_NAME = "$$_hibernateValidator_getFieldValue"; From 71a8b6638ff435395f98cc6984176a790a7665eb Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 10 Sep 2019 10:27:29 +0200 Subject: [PATCH 248/393] HV-1680 State that the example in ByteBuddyWrapperTest is not complete --- .../internal/metadata/bytebuddy/ByteBuddyWrapperTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/bytebuddy/ByteBuddyWrapperTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/bytebuddy/ByteBuddyWrapperTest.java index 90a5c8a65d..41bdc52424 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/bytebuddy/ByteBuddyWrapperTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/bytebuddy/ByteBuddyWrapperTest.java @@ -36,6 +36,10 @@ import org.testng.annotations.Test; /** + * Note that this implementation is not complete and is only for testing purposes. + *

    + * It typically doesn't implement the support for instrumented parent classes. + * * @author Marko Bekhta */ public class ByteBuddyWrapperTest { From 9ada45cda2a942f05db3c024d4e9a68a97fa9400 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 16 Sep 2019 12:20:06 +0200 Subject: [PATCH 249/393] HV-1733 Fix locale settings of PredefinedScopeValidatorFactoryTest --- .../predefinedscope/PredefinedScopeValidatorFactoryTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java index d90b239f79..004b60a6a2 100644 --- a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java @@ -211,7 +211,7 @@ public void testBeanMetaDataClassNormalizerNoNormalizer() { ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) .configure() .initializeBeanMetaData( beanMetaDataToInitialize ) - .initializeLocales( Collections.singleton( Locale.ENGLISH ) ) + .initializeLocales( Collections.singleton( Locale.getDefault() ) ) .buildValidatorFactory(); // As we don't have any metadata for BeanProxy, we consider it is not constrained at all. @@ -227,7 +227,7 @@ public void testBeanMetaDataClassNormalizer() { ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) .configure() .initializeBeanMetaData( beanMetaDataToInitialize ) - .initializeLocales( Collections.singleton( Locale.ENGLISH ) ) + .initializeLocales( Collections.singleton( Locale.getDefault() ) ) .beanMetaDataClassNormalizer( new MyProxyInterfaceBeanMetaDataClassNormalizer() ) .buildValidatorFactory(); From 320f711624ad169932dd0a637878ff62421d1de7 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Mon, 5 Aug 2019 15:35:27 +0200 Subject: [PATCH 250/393] HV-1730 Check if generic parameter for executable is present before accessing it In some cases, like with enum constructors, a parameter can be missing in generic parameter list and return false to synthetic and implicit method calls at the same time. --- .../javabean/JavaBeanExecutable.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java index 3e6b90c764..7f688e6fcc 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java @@ -205,21 +205,32 @@ private static List getParameters(Executable executable) { int explicitlyDeclaredParameterIndex = 0; for ( int i = 0; i < parameterArray.length; i++ ) { - if ( parameterArray[i].isSynthetic() || parameterArray[i].isImplicit() ) { - // in this case, the parameter is not present in genericParameterTypes - parameters.add( new JavaBeanParameter( i, parameterArray[i], parameterTypes[i], parameterTypes[i] ) ); - } - else { + if ( explicitlyDeclaredParameterIndex < genericParameterTypes.length // we might already be out of the bounds of generic params array + && isExplicit( parameterArray[i] ) + && parameterTypesMatch( parameterTypes[i], genericParameterTypes[explicitlyDeclaredParameterIndex] ) ) { + // in this case we have a parameter that is present and matches ("most likely") to the one in the generic parameter types list parameters.add( new JavaBeanParameter( i, parameterArray[i], parameterTypes[i], getErasedTypeIfTypeVariable( genericParameterTypes[explicitlyDeclaredParameterIndex] ) ) ); explicitlyDeclaredParameterIndex++; } + else { + // in this case, the parameter is not present in genericParameterTypes, or the types doesn't match + parameters.add( new JavaBeanParameter( i, parameterArray[i], parameterTypes[i], parameterTypes[i] ) ); + } } } return CollectionHelper.toImmutableList( parameters ); } + private static boolean parameterTypesMatch(Class paramType, Type genericParamType) { + return TypeHelper.getErasedType( genericParamType ).equals( paramType ); + } + + private static boolean isExplicit(Parameter parameter) { + return !parameter.isSynthetic() && !parameter.isImplicit(); + } + private static Type getErasedTypeIfTypeVariable(Type genericType) { if ( genericType instanceof TypeVariable ) { return TypeHelper.getErasedType( genericType ); From 8cba8cf1157c0dfbcb956717a96afa9eee2ca348 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Mon, 5 Aug 2019 15:35:27 +0200 Subject: [PATCH 251/393] HV-1730 Test various object types in PredefinedScopeValidatorFactoryTest --- .../PredefinedScopeValidatorFactoryTest.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java index 004b60a6a2..6133fab5e9 100644 --- a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java @@ -13,8 +13,11 @@ import static org.testng.Assert.fail; import java.lang.annotation.ElementType; +import java.util.AbstractCollection; +import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.Iterator; import java.util.Locale; import java.util.Set; @@ -243,6 +246,7 @@ public void validatorSpecificTraversableResolver() { Set> beanMetaDataToInitialize = new HashSet<>(); beanMetaDataToInitialize.add( Bean.class ); beanMetaDataToInitialize.add( AnotherBean.class ); + beanMetaDataToInitialize.add( SomeEnum.class ); ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) .configure() @@ -260,6 +264,23 @@ public void validatorSpecificTraversableResolver() { } } + @Test + public void variousObjectTypes() { + Set> beanMetaDataToInitialize = new HashSet<>(); + beanMetaDataToInitialize.add( Bean.class ); + beanMetaDataToInitialize.add( AnotherBean.class ); + beanMetaDataToInitialize.add( SomeEnum.class ); + beanMetaDataToInitialize.add( Values.Itr.class ); + + ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) + .configure() + .initializeBeanMetaData( beanMetaDataToInitialize ) + .buildValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + validator.validate( new Bean() ); + } + private static Validator getValidator() { Set> beanMetaDataToInitialize = new HashSet<>(); beanMetaDataToInitialize.add( Bean.class ); @@ -286,6 +307,40 @@ private static Validator getValidatorWithInitializedLocale(Locale locale) { return validatorFactory.getValidator(); } + private enum SomeEnum { + VALUE; + } + + final class Values extends AbstractCollection implements Collection { + public Iterator iterator() { + return new Itr( null ); + } + + public int size() { + return 0; + } + + public boolean isEmpty() { + return true; + } + + final class Itr implements Iterator { + private final Iterator iterator; + + Itr(final Iterator iterator) { + this.iterator = iterator; + } + + public boolean hasNext() { + return iterator.hasNext(); + } + + public String next() { + return ""; + } + } + } + private static class Bean { @NotNull From 7094e68918548eb332725ebed4cbf878ceb89374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 8 Oct 2019 15:30:40 +0200 Subject: [PATCH 252/393] HV-1730 Add a warning when resolving generic type information for method parameters with missing implicit/synthetic metadata --- .../javabean/JavaBeanExecutable.java | 23 +++++++++++++++++++ .../validator/internal/util/logging/Log.java | 8 +++++++ 2 files changed, 31 insertions(+) diff --git a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java index 7f688e6fcc..11e84f89d6 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java +++ b/engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java @@ -7,6 +7,7 @@ package org.hibernate.validator.internal.properties.javabean; import java.lang.annotation.Annotation; +import java.lang.invoke.MethodHandles; import java.lang.reflect.AnnotatedType; import java.lang.reflect.Executable; import java.lang.reflect.Method; @@ -24,6 +25,8 @@ import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.ReflectionHelper; import org.hibernate.validator.internal.util.TypeHelper; +import org.hibernate.validator.internal.util.logging.Log; +import org.hibernate.validator.internal.util.logging.LoggerFactory; /** * @author Marko Bekhta @@ -31,6 +34,8 @@ */ public abstract class JavaBeanExecutable implements Callable, JavaBeanAnnotatedConstrainable { + private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); + protected final T executable; private final Type typeForValidatorResolution; private final boolean hasReturnValue; @@ -202,6 +207,15 @@ private static List getParameters(Executable executable) { } else { // in this case, we have synthetic or implicit parameters + + // do we have the information about which parameter is synthetic/implicit? + // (this metadata is only included when classes are compiled with the '-parameters' flag) + boolean hasParameterModifierInfo = isAnyParameterCarryingMetadata( parameterArray ); + + if ( ! hasParameterModifierInfo ) { + LOG.missingParameterMetadataWithSyntheticOrImplicitParameters( executable ); + } + int explicitlyDeclaredParameterIndex = 0; for ( int i = 0; i < parameterArray.length; i++ ) { @@ -223,6 +237,15 @@ && parameterTypesMatch( parameterTypes[i], genericParameterTypes[explicitlyDecla return CollectionHelper.toImmutableList( parameters ); } + private static boolean isAnyParameterCarryingMetadata(Parameter[] parameterArray) { + for ( Parameter parameter : parameterArray ) { + if ( parameter.isSynthetic() || parameter.isImplicit() ) { + return true; + } + } + return false; + } + private static boolean parameterTypesMatch(Class paramType, Type genericParamType) { return TypeHelper.getErasedType( genericParamType ).equals( paramType ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 66efaa85bf..42ec9d4134 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -892,4 +892,12 @@ ConstraintDefinitionException getConstraintValidatorDefinitionConstraintMismatch @Message(id = 253, value = "Unable to instantiate property node name provider class %s.") ValidationException getUnableToInstantiatePropertyNodeNameProviderClassException(String propertyNodeNameProviderClassName, @Cause Exception e); + + @LogMessage(level = WARN) + @Message(id = 254, value = "Missing parameter metadata for %s, which declares implicit or synthetic parameters." + + " Automatic resolution of generic type information for method parameters" + + " may yield incorrect results if multiple parameters have the same erasure." + + " To solve this, compile your code with the '-parameters' flag." + ) + void missingParameterMetadataWithSyntheticOrImplicitParameters(@FormatWith(ExecutableFormatter.class) Executable executable); } From 020538e41a28a4e3086b515d83955ecb5e7b4e36 Mon Sep 17 00:00:00 2001 From: marko-bekhta Date: Sun, 31 Mar 2019 17:41:42 +0200 Subject: [PATCH 253/393] HV-1715 Accumulate validationSuccessful attribute - validationSuccessful attribute was ignored and only a value from the last group was considered. Which could lead HV to proceed to the next group even though there was a violation for one of the inherited groups of the current one. --- .../internal/engine/ValidatorImpl.java | 2 +- .../engine/groups/sequence/SequenceTest.java | 89 +++++++++++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/groups/sequence/SequenceTest.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index 82e006babd..c34c2a7e22 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -471,7 +471,7 @@ private void validateConstraintsForDefaultGroup(BaseBeanValidationContext for ( Group defaultSequenceMember : groupOfGroups ) { validationSuccessful = validateConstraintsForSingleDefaultGroupElement( validationContext, valueContext, validatedInterfaces, clazz, - metaConstraints, defaultSequenceMember ); + metaConstraints, defaultSequenceMember ) && validationSuccessful; } validationContext.markCurrentBeanAsProcessed( valueContext ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/groups/sequence/SequenceTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/groups/sequence/SequenceTest.java new file mode 100644 index 0000000000..e1d11295f6 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/groups/sequence/SequenceTest.java @@ -0,0 +1,89 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.engine.groups.sequence; + +import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; + +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.GroupSequence; +import javax.validation.Validator; +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.testutil.TestForIssue; +import org.hibernate.validator.testutils.ValidatorUtil; + +import org.testng.annotations.Test; + +/** + * @author Marko Bekhta + */ +@TestForIssue( jiraKey = "HV-1715") +public class SequenceTest { + + @Test + public void groupSequenceOfGroupSequences() { + Validator validator = ValidatorUtil.getValidator(); + + Set> violations = validator.validate( new Foo( null, "", null ) ); + + assertThat( violations ).containsOnlyViolations( + violationOf( NotNull.class ).withProperty( "str1" ) + ); + } + + interface Group1 extends Group11, Group12, Group13, Group14, Group15, Group16, Group17, Group18, Group19 { + } + + interface Group11 { + } + + interface Group12 { + } + + interface Group13 { + } + + interface Group14 { + } + + interface Group15 { + } + + interface Group16 { + } + + interface Group17 { + } + + interface Group18 { + } + + interface Group19 { + } + + interface Group2 { + } + + @GroupSequence({ Foo.class, SequenceTest.Group1.class, SequenceTest.Group2.class }) + private static class Foo { + @NotNull(groups = SequenceTest.Group11.class) + private String str1; + @NotNull(groups = SequenceTest.Group12.class) + private String str2; + @NotNull(groups = SequenceTest.Group2.class) + private String str3; + + public Foo(String str1, String str2, String str3) { + this.str1 = str1; + this.str2 = str2; + this.str3 = str3; + } + } +} From 9f005201242d69b0190fe581c83701c00fbb016e Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 16 Oct 2019 09:56:26 +0200 Subject: [PATCH 254/393] HV-1738 Update Jackson test dependency to 2.9.10 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 74e3fa92f8..5e5f2be02a 100644 --- a/pom.xml +++ b/pom.xml @@ -171,8 +171,8 @@ 27.1-jre 4.3.10.RELEASE 1.0.0.Final - 2.9.9.2 - 2.9.9 + 2.9.10 + 2.9.10 1.10.1 From e19652e5ec8becde2cd73c352afba99bf8d03e17 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 31 Jul 2019 18:53:54 +0200 Subject: [PATCH 255/393] HV-1725 Switch to using Jakarta EE artifacts --- .../ap/testutil/CompilerTestHelper.java | 2 +- cdi/pom.xml | 14 ++--- distribution/pom.xml | 18 +++--- distribution/src/main/assembly/dist.xml | 6 +- documentation/pom.xml | 14 ++--- engine/pom.xml | 10 +-- integration/pom.xml | 8 +-- modules/pom.xml | 16 ++--- modules/src/script/setupModules.groovy | 6 +- osgi/felixtest/pom.xml | 17 +++-- osgi/integrationtest/pom.xml | 6 +- .../src/main/features/features.xml | 6 +- performance/pom.xml | 14 +++-- pom.xml | 63 ++++++++++--------- tck-runner/pom.xml | 10 +-- tck-runner/src/test/resources/test.policy | 8 +-- test-utils/pom.xml | 4 +- 17 files changed, 118 insertions(+), 104 deletions(-) diff --git a/annotation-processor/src/test/java/org/hibernate/validator/ap/testutil/CompilerTestHelper.java b/annotation-processor/src/test/java/org/hibernate/validator/ap/testutil/CompilerTestHelper.java index 21f16327fc..36e785deb8 100644 --- a/annotation-processor/src/test/java/org/hibernate/validator/ap/testutil/CompilerTestHelper.java +++ b/annotation-processor/src/test/java/org/hibernate/validator/ap/testutil/CompilerTestHelper.java @@ -50,7 +50,7 @@ public enum Library { HIBERNATE_VALIDATOR( "hibernate-validator.jar" ), - VALIDATION_API( "validation-api.jar" ), + VALIDATION_API( "jakarta.validation-api.jar" ), JODA_TIME( "joda-time.jar" ), diff --git a/cdi/pom.xml b/cdi/pom.xml index 64d7dc2320..8266468aea 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -33,18 +33,18 @@ hibernate-validator - javax.annotation - javax.annotation-api + jakarta.annotation + jakarta.annotation-api provided - org.jboss.spec.javax.interceptor - jboss-interceptors-api_1.2_spec + jakarta.interceptor + jakarta.interceptor-api provided - javax.enterprise - cdi-api + jakarta.enterprise + jakarta.enterprise.cdi-api provided @@ -63,7 +63,7 @@ org.glassfish - javax.el + jakarta.el test diff --git a/distribution/pom.xml b/distribution/pom.xml index 1b573a898c..67809b2d6d 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -45,7 +45,7 @@ org.glassfish - javax.el + jakarta.el @@ -54,8 +54,8 @@ log4j - javax.persistence - javax.persistence-api + jakarta.persistence + jakarta.persistence-api joda-time @@ -74,16 +74,16 @@ paranamer - javax.enterprise - cdi-api + jakarta.enterprise + jakarta.enterprise.cdi-api - org.jboss.spec.javax.interceptor - jboss-interceptors-api_1.2_spec + jakarta.interceptor + jakarta.interceptor-api - javax.annotation - javax.annotation-api + jakarta.annotation + jakarta.annotation-api org.jboss.logging diff --git a/distribution/src/main/assembly/dist.xml b/distribution/src/main/assembly/dist.xml index fa2d71e776..08abb1d44f 100644 --- a/distribution/src/main/assembly/dist.xml +++ b/distribution/src/main/assembly/dist.xml @@ -33,10 +33,10 @@ dist/lib/required - javax.validation:validation-api + jakarta.validation:jakarta.validation-api org.jboss.logging:jboss-logging com.fasterxml:classmate - org.glassfish:javax.el + org.glassfish:jakarta.el @@ -44,7 +44,7 @@ log4j:log4j joda-time:joda-time - javax.persistence:javax.persistence-api + jakarta.persistence:jakarta.persistence-api org.jsoup:jsoup com.thoughtworks.paranamer:paranamer diff --git a/documentation/pom.xml b/documentation/pom.xml index 76e9e2b194..4108236a0e 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -54,7 +54,7 @@ org.glassfish - javax.el + jakarta.el test @@ -63,8 +63,8 @@ test - javax.enterprise - cdi-api + jakarta.enterprise + jakarta.enterprise.cdi-api test @@ -99,8 +99,8 @@ test - javax.annotation - javax.annotation-api + jakarta.annotation + jakarta.annotation-api test @@ -265,10 +265,10 @@ ${asciidoctor.osgi-integrationtest-source-dir} ${project.version} - ${version.javax.validation} + ${version.jakarta.validation-api} ${version.org.jboss.logging.jboss-logging} ${version.com.fasterxml.classmate} - ${version.org.glassfish.javax.el} + ${version.org.glassfish.jakarta.el} ${version.wildfly} ${version.wildfly.secondary} diff --git a/engine/pom.xml b/engine/pom.xml index c9ecf37108..0fc0347cb3 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -36,8 +36,8 @@ Compile time dependencies --> - javax.validation - validation-api + jakarta.validation + jakarta.validation-api org.jboss.logging @@ -53,7 +53,7 @@ --> org.glassfish - javax.el + jakarta.el provided @@ -79,8 +79,8 @@ Optional dependencies --> - javax.persistence - javax.persistence-api + jakarta.persistence + jakarta.persistence-api true diff --git a/integration/pom.xml b/integration/pom.xml index 85364bd54c..e0ac3d07fb 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -93,13 +93,13 @@ test - javax.persistence - javax.persistence-api + jakarta.persistence + jakarta.persistence-api test - org.jboss.spec.javax.ejb - jboss-ejb-api_3.2_spec + jakarta.ejb + jakarta.ejb-api test diff --git a/modules/pom.xml b/modules/pom.xml index 6ca85e82c6..fc57501f3a 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -212,13 +212,13 @@ - javax.validation - validation-api - ${version.javax.validation} + jakarta.validation + jakarta.validation-api + ${version.jakarta.validation-api} false ${wildfly-main.patched.target-dir}/modules/system/layers/base/javax/validation/api/main - validation-api-${version.javax.validation}.jar + jakarta.validation-api-${version.jakarta.validation-api}.jar ${project.groupId} @@ -238,13 +238,13 @@ - javax.validation - validation-api - ${version.javax.validation} + jakarta.validation + jakarta.validation-api + ${version.jakarta.validation-api} false ${wildfly-secondary.patched.target-dir}/modules/system/layers/base/javax/validation/api/main - validation-api-${version.javax.validation}.jar + jakarta.validation-api-${version.jakarta.validation-api}.jar ${project.groupId} diff --git a/modules/src/script/setupModules.groovy b/modules/src/script/setupModules.groovy index 93092db5c0..41a2bd420e 100644 --- a/modules/src/script/setupModules.groovy +++ b/modules/src/script/setupModules.groovy @@ -21,10 +21,10 @@ def removeDependency(File file, String dependencyToRemove) { file.write( file.text.replaceAll( //, '' ) ) } -// BV API +// Jakarta Bean Validation API bvModuleXml = new File( wildflyPatchedTargetDir, 'modules/system/layers/base/javax/validation/api/main/module.xml' ) -def bvArtifactName = 'validation-api-' + project.properties['version.javax.validation'] + '.jar'; -println "[INFO] Using BV version " + bvArtifactName; +def bvArtifactName = 'jakarta.validation-api-' + project.properties['version.jakarta.validation-api'] + '.jar'; +println "[INFO] Using Jakarta Bean Validation version " + bvArtifactName; processFileInplace( bvModuleXml ) { text -> text.replaceAll( /validation-api.*jar/, bvArtifactName ) } diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 55c15d1c8c..47c58cf20c 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -48,13 +48,13 @@ - javax.validation - validation-api + jakarta.validation + jakarta.validation-api provided - javax.enterprise - cdi-api + jakarta.enterprise + jakarta.enterprise.cdi-api provided @@ -165,6 +165,15 @@ hibernate-validator-cdi.jar true + + jakarta.validation + jakarta.validation-api + ${bv.api.version} + jar + ${project.build.directory}/payara5/glassfish/modules + validation-api.jar + true + diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 28ce4576ea..61768b6729 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -31,8 +31,8 @@ - javax.validation - validation-api + jakarta.validation + jakarta.validation-api test @@ -143,7 +143,7 @@ org.glassfish - javax.el + jakarta.el test diff --git a/osgi/karaf-features/src/main/features/features.xml b/osgi/karaf-features/src/main/features/features.xml index 66f5c82a43..a63942a683 100644 --- a/osgi/karaf-features/src/main/features/features.xml +++ b/osgi/karaf-features/src/main/features/features.xml @@ -12,11 +12,11 @@ mvn:org.hibernate.validator/hibernate-validator/${project.version} - mvn:javax.validation/validation-api/${version.javax.validation} + mvn:jakarta.validation/jakarta.validation-api/${version.jakarta.validation-api} mvn:org.jboss.logging/jboss-logging/${version.org.jboss.logging.jboss-logging} mvn:com.fasterxml/classmate/${version.com.fasterxml.classmate} - mvn:org.glassfish/javax.el/${version.org.glassfish.javax.el} + mvn:org.glassfish/jakarta.el/${version.org.glassfish.jakarta.el} hibernate-validator @@ -30,7 +30,7 @@ hibernate-validator mvn:javax.money/money-api/${version.javax.money} mvn:org.javamoney/moneta/${version.org.javamoney.moneta} - mvn:javax.annotation/javax.annotation-api/${version.javax.annotation} + mvn:jakarta.annotation/jakarta.annotation-api/${version.jakarta.annotation-api} hibernate-validator diff --git a/performance/pom.xml b/performance/pom.xml index 847461dfe5..e5c465157f 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -53,8 +53,8 @@ provided - javax.validation - validation-api + jakarta.validation + jakarta.validation-api provided @@ -166,8 +166,8 @@ - javax.validation - validation-api + jakarta.validation + jakarta.validation-api ${project.groupId} @@ -176,7 +176,7 @@ org.glassfish - javax.el + jakarta.el log4j @@ -243,6 +243,7 @@ + 2.0.1.Final Hibernate Validator 6.0.16.Final @@ -250,6 +251,7 @@ javax.validation validation-api + ${validation-api.version} ${project.groupId} @@ -259,6 +261,7 @@ org.glassfish javax.el + 3.0.1-b11 log4j @@ -302,6 +305,7 @@ org.glassfish javax.el + 3.0.1-b11 log4j diff --git a/pom.xml b/pom.xml index 5e5f2be02a..29d04eabf7 100644 --- a/pom.xml +++ b/pom.xml @@ -113,11 +113,11 @@ - 2.0.1.Final - 2.0.4.Final + 2.0.2 + 2.0.5 2.8 - 3.0.1-b09 + 3.0.3 3.3.2.Final 2.1.0.Final @@ -137,18 +137,19 @@ 2.9.7 1.7.22 1.2.17 - 2.2 + 2.2.3 - 2.0.SP1 + 2.0.1 3.1.1.Final 2.2.0.Final - 1.0.2.Final - 1.0.0.Final + 3.2.5 + 1.2.4 + 1.3.5 1.0.1 @@ -321,9 +322,9 @@ zip - javax.validation - validation-api - ${version.javax.validation} + jakarta.validation + jakarta.validation-api + ${version.jakarta.validation-api} org.jboss.logging @@ -342,8 +343,8 @@ org.glassfish - javax.el - ${version.org.glassfish.javax.el} + jakarta.el + ${version.org.glassfish.jakarta.el} com.fasterxml @@ -396,9 +397,9 @@ ${version.org.slf4j} - javax.persistence - javax.persistence-api - ${version.javax.persistence} + jakarta.persistence + jakarta.persistence-api + ${version.jakarta.persistence-api} junit @@ -433,32 +434,32 @@ import - javax.annotation - javax.annotation-api - 1.2 + jakarta.annotation + jakarta.annotation-api + ${version.jakarta.annotation-api} - org.jboss.spec.javax.interceptor - jboss-interceptors-api_1.2_spec - ${version.org.jboss.spec.javax.interceptor.jboss-interceptors-api_1.2_spec} + jakarta.interceptor + jakarta.interceptor-api + ${version.jakarta.interceptor-api} - org.jboss.spec.javax.ejb - jboss-ejb-api_3.2_spec - ${version.org.jboss.spec.javax.ejb.jboss-ejb-api_3.2_spec} + jakarta.ejb + jakarta.ejb-api + ${version.jakarta.ejb-api} - javax.enterprise - cdi-api - ${version.javax.enterprise} + jakarta.enterprise + jakarta.enterprise.cdi-api + ${version.jakarta.enterprise.cdi-api} - javax.interceptor - javax.interceptor-api + jakarta.interceptor + jakarta.interceptor-api - javax.el - javax.el-api + jakarta.el + jakarta.el-api diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index e34ebfc67e..12d2333119 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -31,8 +31,8 @@ - javax.validation - validation-api + jakarta.validation + jakarta.validation-api ${project.groupId} @@ -40,11 +40,11 @@ org.glassfish - javax.el + jakarta.el - javax.persistence - javax.persistence-api + jakarta.persistence + jakarta.persistence-api test diff --git a/tck-runner/src/test/resources/test.policy b/tck-runner/src/test/resources/test.policy index c9026319dc..aae5f1c2d1 100644 --- a/tck-runner/src/test/resources/test.policy +++ b/tck-runner/src/test/resources/test.policy @@ -54,11 +54,11 @@ grant codeBase "file:${localRepository}/org/jboss/logging/jboss-logging/-" { permission java.util.PropertyPermission "org.jboss.logging.locale", "read"; }; -/* =================== */ -/* Bean Validation API */ -/* =================== */ +/* =========================== */ +/* Jakarta Bean Validation API */ +/* =========================== */ -grant codeBase "file:${localRepository}/javax/validation/validation-api/-" { +grant codeBase "file:${localRepository}/jakarta/validation/jakarta.validation-api/-" { permission java.io.FilePermission "<>", "read"; // in some tests this property is accessed by the TCK when the API JAR is on the callstack; the TCK doesn't diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 3b0766e5c7..efc534b51b 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -54,8 +54,8 @@ - javax.validation - validation-api + jakarta.validation + jakarta.validation-api log4j From d71e56f4643aa28b8d2cf900a33fb1748d848591 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 1 Aug 2019 10:39:04 +0200 Subject: [PATCH 256/393] HV-1725 Update pom files for Jakarta move --- engine/pom.xml | 2 +- tck-runner/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/engine/pom.xml b/engine/pom.xml index 0fc0347cb3..eb7667dda7 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -18,7 +18,7 @@ hibernate-validator Hibernate Validator Engine - Hibernate's Bean Validation (JSR-380) reference implementation. + Hibernate's Jakarta Bean Validation reference implementation. .. diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 12d2333119..d139d3ab71 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -18,7 +18,7 @@ hibernate-validator-tck-runner Hibernate Validator TCK Runner - Aggregates dependencies and runs the JSR-380 TCK + Aggregates dependencies and runs the Jakarta Bean Validation TCK ${project.build.directory}/dependency/beanvalidation-tck-tests-suite.xml From cfcbf608d74bd4c5e1601eca2cdc3666be39397e Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 1 Aug 2019 10:39:25 +0200 Subject: [PATCH 257/393] HV-1725 Update documentation for Jakarta move --- documentation/pom.xml | 4 +- documentation/src/main/asciidoc/ch01.asciidoc | 45 ++++++++++--------- documentation/src/main/asciidoc/ch02.asciidoc | 32 ++++++------- documentation/src/main/asciidoc/ch03.asciidoc | 4 +- documentation/src/main/asciidoc/ch04.asciidoc | 14 +++--- documentation/src/main/asciidoc/ch06.asciidoc | 18 ++++---- documentation/src/main/asciidoc/ch07.asciidoc | 6 +-- documentation/src/main/asciidoc/ch08.asciidoc | 12 ++--- documentation/src/main/asciidoc/ch09.asciidoc | 6 +-- documentation/src/main/asciidoc/ch10.asciidoc | 2 +- documentation/src/main/asciidoc/ch11.asciidoc | 26 +++++------ documentation/src/main/asciidoc/ch12.asciidoc | 26 +++++------ documentation/src/main/asciidoc/ch13.asciidoc | 2 +- documentation/src/main/asciidoc/ch14.asciidoc | 6 +-- .../src/main/asciidoc/index.asciidoc | 2 +- documentation/src/main/asciidoc/pr01.asciidoc | 8 ++-- 16 files changed, 107 insertions(+), 106 deletions(-) diff --git a/documentation/pom.xml b/documentation/pom.xml index 4108236a0e..b2b7dfa964 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -31,7 +31,7 @@ ${basedir}/../osgi/integrationtest/src/test/java Hibernate Validator, Annotation based constraints for your domain model - Reference Documentation - hibernate, validator, hibernate validator, validation, bean validation + hibernate, validator, hibernate validator, validation, jakarta bean validation, bean validation validator UA-45270411-3 GTM-NJWS5L @@ -268,7 +268,7 @@ ${version.jakarta.validation-api} ${version.org.jboss.logging.jboss-logging} ${version.com.fasterxml.classmate} - ${version.org.glassfish.jakarta.el} + ${version.org.glassfish.jakarta.el} ${version.wildfly} ${version.wildfly.secondary} diff --git a/documentation/src/main/asciidoc/ch01.asciidoc b/documentation/src/main/asciidoc/ch01.asciidoc index 2465cbc765..8c761fe37f 100644 --- a/documentation/src/main/asciidoc/ch01.asciidoc +++ b/documentation/src/main/asciidoc/ch01.asciidoc @@ -1,7 +1,7 @@ [[validator-gettingstarted]] == Getting started -This chapter will show you how to get started with Hibernate Validator, the reference implementation (RI) of Bean Validation. For the following quick-start you need: +This chapter will show you how to get started with Hibernate Validator, the reference implementation (RI) of Jakarta Bean Validation. For the following quick-start you need: * A JDK 8 * http://maven.apache.org/[Apache Maven] @@ -26,18 +26,18 @@ your __pom.xml__: ---- ==== -This transitively pulls in the dependency to the Bean Validation API -(`javax.validation:validation-api:{bvVersion}`). +This transitively pulls in the dependency to the Jakarta Bean Validation API +(`jakarta.validation:jakarta.validation-api:{bvVersion}`). [[validator-gettingstarted-uel]] ==== Unified EL -Hibernate Validator requires an implementation of the Unified Expression Language -(http://jcp.org/en/jsr/detail?id=341[JSR 341]) for evaluating dynamic expressions in constraint +Hibernate Validator requires an implementation of https://projects.eclipse.org/projects/ee4j.el[Jakarta Expression Language] +for evaluating dynamic expressions in constraint violation messages (see <>). When your application runs in a Java EE container such as JBoss AS, an EL implementation is already provided by the container. In a Java SE environment, however, you have to add an implementation as dependency to your POM file. For instance -you can add the following dependency to use the JSR 341 https://javaee.github.io/uel-ri/[reference +you can add the following dependency to use the Jakarta EL https://github.com/eclipse-ee4j/el-ri[reference implementation]: .Maven dependencies for Unified EL reference implementation @@ -47,8 +47,8 @@ implementation]: ---- org.glassfish - javax.el - {javaxElVersion} + jakarta.el + {jakartaElVersion} ---- ==== @@ -57,14 +57,15 @@ implementation]: ==== For environments where one cannot provide a EL implementation Hibernate Validator is offering a <>. However, the use of this interpolator -is not Bean Validation specification compliant. +is not Jakarta Bean Validation specification compliant. ==== [[section-getting-started-cdi]] ==== CDI -Bean Validation defines integration points with CDI (Contexts and Dependency Injection for Java ^TM^ -EE, http://jcp.org/en/jsr/detail?id=346[JSR 346]). If your application runs in an +Jakarta Bean Validation defines integration points with CDI +(https://projects.eclipse.org/projects/ee4j.cdi[Contexts and Dependency Injection for Jakarta EE]). +If your application runs in an environment which does not provide this integration out of the box, you may use the Hibernate Validator CDI portable extension by adding the following Maven dependency to your POM: @@ -82,14 +83,14 @@ Validator CDI portable extension by adding the following Maven dependency to you ==== Note that adding this dependency is usually not required for applications running on a Java EE -application server. You can learn more about the integration of Bean Validation and CDI in +application server. You can learn more about the integration of Jakarta Bean Validation and CDI in <>. [[section-getting-started-security-manager]] ==== Running with a security manager Hibernate Validator supports running with a {javaTechnotesBaseUrl}/guides/security/index.html[security manager] being enabled. -To do so, you must assign several permissions to the code bases of Hibernate Validator, the Bean Validation API, Classmate and JBoss Logging and also to the code base calling Bean Validation. +To do so, you must assign several permissions to the code bases of Hibernate Validator, the Jakarta Bean Validation API, Classmate and JBoss Logging and also to the code base calling Jakarta Bean Validation. The following shows how to do this via a {javaTechnotesBaseUrl}/guides/security/PolicyFiles.html[policy file] as processed by the Java default policy implementation: .Policy file for using Hibernate Validator with a security manager @@ -108,7 +109,7 @@ grant codeBase "file:path/to/hibernate-validator-{hvVersion}.jar" { permission java.util.PropertyPermission "mapAnyUriToUri", "read"; }; -grant codeBase "file:path/to/validation-api-{bvVersion}.jar" { +grant codeBase "file:path/to/jakarta.validation-api-{bvVersion}.jar" { permission java.io.FilePermission "path/to/hibernate-validator-{hvVersion}.jar", "read"; }; @@ -130,7 +131,7 @@ grant codeBase "file:path/to/validation-caller-x.y.z.jar" { ==== Updating Hibernate Validator in WildFly The http://wildfly.org/[WildFly application server] contains Hibernate Validator out of the box. -In order to update the server modules for Bean Validation API and Hibernate Validator to the latest and greatest, the patch mechanism of WildFly can be used. +In order to update the server modules for Jakarta Bean Validation API and Hibernate Validator to the latest and greatest, the patch mechanism of WildFly can be used. You can download the patch file from http://sourceforge.net/projects/hibernate/files/hibernate-validator[SourceForge] or from Maven Central using the following dependency: @@ -198,7 +199,7 @@ There are no JPMS module descriptors provided yet, but Hibernate Validator is us These are the module names as declared using the `Automatic-Module-Name` header: -* Bean Validation API: `java.validation` +* Jakarta Bean Validation API: `java.validation` * Hibernate Validator core: `org.hibernate.validator` * Hibernate Validator CDI extension: `org.hibernate.validator.cdi` * Hibernate Validator test utilities: `org.hibernate.validator.testutils` @@ -209,14 +210,14 @@ These module names are preliminary and may be changed when providing real module [WARNING] ==== When using Hibernate Validator with CDI, be careful to not enable the `java.xml.ws.annotation` module of the JDK. -This module contains a subset of the JSR 250 API ("Commons Annotations"), but some annotations such as `javax.annotation.Priority` are missing. +This module contains a subset of Jakarta Annotations, but some annotations such as `javax.annotation.Priority` are missing. This causes the method validation interceptor of Hibernate Validator to not be registered, i.e. method validation won't work. -Instead, add the full JSR 250 API to the unnamed module (i.e. the classpath), e.g. by pulling in the _javax.annotation:javax.annotation-api_ dependency -(there already is a transitive dependency to the JSR 250 API when depending on _org.hibernate.validator:hibernate-validator-cdi_). +Instead, add the full Jakarta Annotations API to the unnamed module (i.e. the classpath), e.g. by pulling in the _jakarta.annotation:jakarta.annotation-api_ dependency +(there already is a transitive dependency to the Jakarta Annotations API when depending on _org.hibernate.validator:hibernate-validator-cdi_). If you need to enable the `java.xml.ws.annotation` module for some reason, you should patch it with the contents of the full API -by appending `--patch-module java.xml.ws.annotation=/path/to/complete-jsr250-api.jar` to your _java_ invocation. +by appending `--patch-module java.xml.ws.annotation=/path/to/complete-jakarta.annotation-api.jar` to your _java_ invocation. ==== [[validator-gettingstarted-createmodel]] @@ -284,11 +285,11 @@ code. [[validator-gettingstarted-whatsnext]] === Where to go next? -That concludes the 5 minutes tour through the world of Hibernate Validator and Bean Validation. +That concludes the 5 minutes tour through the world of Hibernate Validator and Jakarta Bean Validation. Continue exploring the code examples or look at further examples referenced in <>. To learn more about the validation of beans and properties, just continue reading -<>. If you are interested in using Bean Validation for the validation of +<>. If you are interested in using Jakarta Bean Validation for the validation of method pre- and postcondition refer to <>. In case your application has specific validation requirements have a look at <>. diff --git a/documentation/src/main/asciidoc/ch02.asciidoc b/documentation/src/main/asciidoc/ch02.asciidoc index 591af81796..db1f7773f4 100644 --- a/documentation/src/main/asciidoc/ch02.asciidoc +++ b/documentation/src/main/asciidoc/ch02.asciidoc @@ -12,7 +12,7 @@ If you are interested in applying constraints to method parameters and return va [[section-declaring-bean-constraints]] === Declaring bean constraints -Constraints in Bean Validation are expressed via Java annotations. In this section you will learn +Constraints in Jakarta Bean Validation are expressed via Java annotations. In this section you will learn how to enhance an object model with these annotations. There are four types of bean constraints: * field constraints @@ -23,7 +23,7 @@ how to enhance an object model with these annotations. There are four types of b [NOTE] ==== Not all constraints can be placed on all of these levels. In fact, none of the default constraints -defined by Bean Validation can be placed at class level. The `java.lang.annotation.Target` annotation +defined by Jakarta Bean Validation can be placed at class level. The `java.lang.annotation.Target` annotation in the constraint annotation itself determines on which elements a constraint can be placed. See <> for more information. ==== @@ -95,7 +95,7 @@ It is possible to specify constraints directly on the type argument of a parameterized type: these constraints are called container element constraints. This requires that `ElementType.TYPE_USE` is specified via `@Target` -in the constraint definition. As of Bean Validation 2.0, built-in Bean Validation as well as +in the constraint definition. As of Jakarta Bean Validation 2.0, built-in Jakarta Bean Validation as well as Hibernate Validator specific constraints specify `ElementType.TYPE_USE` and can be used directly in this context. @@ -332,7 +332,7 @@ evaluated in addition to the `@NotNull` constraint from the superclass. [[section-object-graph-validation]] ==== Object graphs -The Bean Validation API does not only allow to validate single class instances but also complete +The Jakarta Bean Validation API does not only allow to validate single class instances but also complete object graphs (cascaded validation). To do so, just annotate a field or property representing a reference to another object with `@Valid` as demonstrated in <>. @@ -410,7 +410,7 @@ as it is more expressive. [[section-validating-bean-constraints]] === Validating bean constraints -The `Validator` interface is the most important object in Bean Validation. The next section shows how +The `Validator` interface is the most important object in Jakarta Bean Validation. The next section shows how to obtain a `Validator` instance. Afterwards you'll learn how to use the different methods of the `Validator` interface. @@ -496,7 +496,7 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter02/validation ==== -`Validator#validateProperty()` is for example used in the integration of Bean Validation into JSF 2 +`Validator#validateProperty()` is for example used in the integration of Jakarta Bean Validation into JSF 2 (see <>) to perform a validation of the values entered into a form before they are propagated to the model. @@ -539,28 +539,28 @@ The returned `Path` is composed of ``Node``s describing the path to the element. More information about the structure of the `Path` and the various types of ``Node``s can be found in {bvSpecUrl}#validationapi-constraintviolation[the `ConstraintViolation` section] of the -Bean Validation specification. +Jakarta Bean Validation specification. [[section-builtin-constraints]] === Built-in constraints Hibernate Validator comprises a basic set of commonly used constraints. These are foremost the -constraints defined by the Bean Validation specification (see <>). +constraints defined by the Jakarta Bean Validation specification (see <>). Additionally, Hibernate Validator provides useful custom constraints (see <>). [[validator-defineconstraints-spec]] -==== Bean Validation constraints +==== Jakarta Bean Validation constraints -Below you can find a list of all constraints specified in the Bean Validation API. -All these constraints apply to the field/property level, there are no class-level constraints defined in the Bean Validation specification. +Below you can find a list of all constraints specified in the Jakarta Bean Validation API. +All these constraints apply to the field/property level, there are no class-level constraints defined in the Jakarta Bean Validation specification. If you are using the Hibernate object-relational mapper, some of the constraints are taken into account when creating the DDL for your model (see "Hibernate metadata impact"). [NOTE] ==== Hibernate Validator allows some constraints to be applied to more data types than required by the -Bean Validation specification (e.g. `@Max` can be applied to strings). Relying on this feature can -impact portability of your application between Bean Validation providers. +Jakarta Bean Validation specification (e.g. `@Max` can be applied to strings). Relying on this feature can +impact portability of your application between Jakarta Bean Validation providers. ==== `@AssertFalse`:: Checks that the annotated element is false @@ -654,13 +654,13 @@ impact portability of your application between Bean Validation providers. [NOTE] ==== On top of the parameters listed above each constraint has the parameters -message, groups and payload. This is a requirement of the Bean Validation specification. +message, groups and payload. This is a requirement of the Jakarta Bean Validation specification. ==== [[validator-defineconstraints-hv-constraints]] ==== Additional constraints -In addition to the constraints defined by the Bean Validation API, Hibernate Validator provides several useful custom constraints which are listed below. +In addition to the constraints defined by the Jakarta Bean Validation API, Hibernate Validator provides several useful custom constraints which are listed below. With one exception also these constraints apply to the field/property level, only `@ScriptAssert` is a class-level constraint. `@CreditCardNumber(ignoreNonDigitCharacters=)`:: Checks that the annotated character sequence passes the Luhn checksum test. Note, this validation aims to check for user mistakes, not credit card validity! See also http://www.dirigodev.com/blog/ecommerce/anatomy-of-a-credit-card-number/[Anatomy of a credit card number]. `ignoreNonDigitCharacters` allows to ignore non digit characters. The default is `false`. @@ -771,7 +771,7 @@ Hibernate Validator! [TIP] ==== -In some cases neither the Bean Validation constraints nor the custom constraints provided by +In some cases neither the Jakarta Bean Validation constraints nor the custom constraints provided by Hibernate Validator will fulfill your requirements. In this case you can easily write your own constraint. You can find more information in <>. ==== diff --git a/documentation/src/main/asciidoc/ch03.asciidoc b/documentation/src/main/asciidoc/ch03.asciidoc index bf334a4133..7df828b782 100644 --- a/documentation/src/main/asciidoc/ch03.asciidoc +++ b/documentation/src/main/asciidoc/ch03.asciidoc @@ -3,7 +3,7 @@ As of Bean Validation 1.1, constraints can not only be applied to JavaBeans and their properties, but also to the parameters and return values of the methods and constructors of any Java type. That -way Bean Validation constraints can be used to specify +way Jakarta Bean Validation constraints can be used to specify * the preconditions that must be satisfied by the caller before a method or constructor may be invoked (by applying constraints to the parameters of an executable) @@ -232,7 +232,7 @@ fail to satisfy these preconditions as is not aware of them. The rules of behavi also known as the http://en.wikipedia.org/wiki/Liskov_substitution_principle[Liskov substitution principle]. -The Bean Validation specification implements the first rule by disallowing parameter constraints on +The Jakarta Bean Validation specification implements the first rule by disallowing parameter constraints on methods which override or implement a method declared in a supertype (superclass or interface). <> shows a violation of this rule. diff --git a/documentation/src/main/asciidoc/ch04.asciidoc b/documentation/src/main/asciidoc/ch04.asciidoc index 1267a9cf21..7ab337396f 100644 --- a/documentation/src/main/asciidoc/ch04.asciidoc +++ b/documentation/src/main/asciidoc/ch04.asciidoc @@ -1,7 +1,7 @@ [[chapter-message-interpolation]] == Interpolating constraint error messages -Message interpolation is the process of creating error messages for violated Bean Validation +Message interpolation is the process of creating error messages for violated Jakarta Bean Validation constraints. In this chapter you will learn how such messages are defined and resolved and how you can plug in custom message interpolators in case the default algorithm is not sufficient for your requirements. @@ -42,7 +42,7 @@ this bundle, such as _$$ValidationMessages_en_US.properties$$_. By default, the (`Locale#getDefault()`) will be used when looking up messages in the bundle. . Resolve any message parameters by using them as key for a resource bundle containing the standard -error messages for the built-in constraints as defined in Appendix B of the Bean Validation +error messages for the built-in constraints as defined in Appendix B of the Jakarta Bean Validation specification. In the case of Hibernate Validator, this bundle is named `org.hibernate.validator.ValidationMessages`. If this step triggers a replacement, step 1 is executed again, otherwise step 3 is applied. @@ -61,7 +61,7 @@ Unified EL in error messages. ==== You can find the formal definition of the interpolation algorithm in section {bvSpecUrl}#validationapi-message-defaultmessageinterpolation-resolutionalgorithm[6.3.1.1] -of the Bean Validation specification. +of the Jakarta Bean Validation specification. ==== [[section-special-characters]] @@ -79,8 +79,8 @@ escaped if you want to use them literally. The following rules apply: [[section-interpolation-with-message-expressions]] ==== Interpolation with message expressions -As of Hibernate Validator 5 (Bean Validation 1.1) it is possible to use the Unified Expression -Language (as defined by link:http://jcp.org/en/jsr/detail?id=341[JSR 341]) in constraint +As of Hibernate Validator 5 (Bean Validation 1.1) it is possible to use the +https://projects.eclipse.org/projects/ee4j.el[Jakarta Expression Language] in constraint violation messages. This allows to define error messages based on conditional logic and also enables advanced formatting options. The validation engine makes the following objects available in the EL context: @@ -111,7 +111,7 @@ Validating an invalid `Car` instance yields constraint violations with the messa assertions in <>: * the `@NotNull` constraint on the `manufacturer` field causes the error message "must not be null", as -this is the default message defined by the Bean Validation specification and no specific descriptor +this is the default message defined by the Jakarta Bean Validation specification and no specific descriptor is given in the message attribute * the `@Size` constraint on the `licensePlate` field shows the interpolation of message parameters @@ -157,7 +157,7 @@ final implementation to the default interpolator, which can be obtained via `Configuration#getDefaultMessageInterpolator()`. In order to use a custom message interpolator it must be registered either by configuring it in the -Bean Validation XML descriptor _META-INF/validation.xml_ (see +Jakarta Bean Validation XML descriptor _META-INF/validation.xml_ (see <>) or by passing it when bootstrapping a `ValidatorFactory` or `Validator` (see <> and <>, respectively). diff --git a/documentation/src/main/asciidoc/ch06.asciidoc b/documentation/src/main/asciidoc/ch06.asciidoc index afb53c4b5a..a3ca32e39a 100644 --- a/documentation/src/main/asciidoc/ch06.asciidoc +++ b/documentation/src/main/asciidoc/ch06.asciidoc @@ -1,7 +1,7 @@ [[validator-customconstraints]] == Creating custom constraints -The Bean Validation API defines a whole set of standard constraint annotations such as `@NotNull`, +The Jakarta Bean Validation API defines a whole set of standard constraint annotations such as `@NotNull`, `@Size` etc. In cases where these built-in constraints are not sufficient, you can easily create custom constraints tailored to your specific validation requirements. @@ -46,7 +46,7 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter06/CheckCase. ==== An annotation type is defined using the `@interface` keyword. All attributes of an annotation type are -declared in a method-like manner. The specification of the Bean Validation API demands, that any +declared in a method-like manner. The specification of the Jakarta Bean Validation API demands, that any constraint annotation defines: * an attribute `message` that returns the default key for creating error messages in case the @@ -55,7 +55,7 @@ constraint is violated * an attribute `groups` that allows the specification of validation groups, to which this constraint belongs (see <>). This must default to an empty array of type Class. -* an attribute `payload` that can be used by clients of the Bean Validation API to assign custom +* an attribute `payload` that can be used by clients of the Jakarta Bean Validation API to assign custom payload objects to a constraint. This attribute is not used by the API itself. An example for a custom payload could be the definition of a severity: + @@ -109,14 +109,14 @@ same place, usually with a different configuration. `List` is the containing ann This containing annotation type named `List` is also shown in the example. It allows to specify several `@CheckCase` annotations on the same element, e.g. with different validation groups and messages. -While another name could be used, the Bean Validation specification recommends to use the name +While another name could be used, the Jakarta Bean Validation specification recommends to use the name `List` and make the annotation an inner annotation of the corresponding constraint type. [[section-constraint-validator]] ==== The constraint validator Having defined the annotation, you need to create a constraint validator, which is able to validate -elements with a `@CheckCase` annotation. To do so, implement the Bean Validation interface `ConstraintValidator` +elements with a `@CheckCase` annotation. To do so, implement the Jakarta Bean Validation interface `ConstraintValidator` as shown below: [[example-constraint-validator]] @@ -140,7 +140,7 @@ validator as shown in the example. The `isValid()` method contains the actual validation logic. For `@CheckCase` this is the check whether a given string is either completely lower case or upper case, depending on the case mode retrieved -in `initialize()`. Note that the Bean Validation specification recommends to consider null values as +in `initialize()`. Note that the Jakarta Bean Validation specification recommends to consider null values as being valid. If `null` is not a valid value for an element, it should be annotated with `@NotNull` explicitly. @@ -183,7 +183,7 @@ sensitive data. If you need to integrate user input, you should: - * either escape it by using the http://beanvalidation.org/2.0/spec/#validationapi-message-defaultmessageinterpolation[Bean Validation message interpolation escaping rules]; + * either escape it by using the http://beanvalidation.org/2.0/spec/#validationapi-message-defaultmessageinterpolation[Jakarta Bean Validation message interpolation escaping rules]; * or, even better, <> by unwrapping the context to `HibernateConstraintValidatorContext`. ==== @@ -206,7 +206,7 @@ The `initialize()` method of `HibernateConstraintValidator` takes two parameters information, such as the clock provider or the temporal validation tolerance. This extension is marked as incubating so it might be subject to change. -The plan is to standardize it and to include it in Bean Validation in the future. +The plan is to standardize it and to include it in Jakarta Bean Validation in the future. The example below shows how to base your validators on `HibernateConstraintValidator`: @@ -384,7 +384,7 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter06/custompath [[section-cross-parameter-constraints]] === Cross-parameter constraints -Bean Validation distinguishes between two different kinds of constraints. +Jakarta Bean Validation distinguishes between two different kinds of constraints. Generic constraints (which have been discussed so far) apply to the annotated element, e.g. a type, field, container element, method parameter or return value etc. diff --git a/documentation/src/main/asciidoc/ch07.asciidoc b/documentation/src/main/asciidoc/ch07.asciidoc index 39ccf0bad5..bfdcacc9f2 100644 --- a/documentation/src/main/asciidoc/ch07.asciidoc +++ b/documentation/src/main/asciidoc/ch07.asciidoc @@ -27,7 +27,7 @@ Built-in value extractors are present for all the following container types: The complete list of built-in value extractors with all the details on how they behave can be found in the -{bvSpecUrl}#valueextractordefinition-builtinvalueextractors[Bean Validation specification]. +{bvSpecUrl}#valueextractordefinition-builtinvalueextractors[Jakarta Bean Validation specification]. === Implementing a `ValueExtractor` @@ -178,7 +178,7 @@ annotation allows to provide this information to the validation engine. Then you have to tell the validation engine that the `Min` constraint you want to add to the `OptionalInt` property relates to the wrapped value and not the wrapper. -Bean Validation provides the `Unwrapping.Unwrap` payload for this situation: +Jakarta Bean Validation provides the `Unwrapping.Unwrap` payload for this situation: [[example-valueextraction-optionalint-unwrapping]] .Using `Unwrapping.Unwrap` payload @@ -319,7 +319,7 @@ given at lower priorities. In most cases, you should not have to worry about this but, if you are overriding existing value extractors, you can find a detailed description of the value -extractors resolution algorithms in the Bean Validation specification: +extractors resolution algorithms in the Jakarta Bean Validation specification: * for {bvSpecUrl}#constraintdeclarationvalidationprocess-validationroutine-valueextractorresolution-algorithm-constraints[container element constraints], * for {bvSpecUrl}#constraintdeclarationvalidationprocess-validationroutine-valueextractorresolution-algorithm-cascaded[cascaded validation], diff --git a/documentation/src/main/asciidoc/ch08.asciidoc b/documentation/src/main/asciidoc/ch08.asciidoc index f535060684..e3e190c890 100644 --- a/documentation/src/main/asciidoc/ch08.asciidoc +++ b/documentation/src/main/asciidoc/ch08.asciidoc @@ -1,9 +1,9 @@ [[chapter-xml-configuration]] == Configuring via XML -So far we have used the default configuration source for Bean Validation, namely annotations. +So far we have used the default configuration source for Jakarta Bean Validation, namely annotations. However, there also exist two kinds of XML descriptors allowing configuration via XML. The first -descriptor describes general Bean Validation behaviour and is provided as _META-INF/validation.xml_. +descriptor describes general Jakarta Bean Validation behaviour and is provided as _META-INF/validation.xml_. The second one describes constraint declarations and closely matches the constraint declaration approach via annotations. Let's have a look at these two document types. @@ -14,7 +14,7 @@ http://xmlns.jcp.org/xml/ns/validation/configuration and http://xmlns.jcp.org/xml/ns/validation/mapping. More information about the XML schemas can be found on the -http://beanvalidation.org/xml/ns/validation/[Bean Validation website]. +http://beanvalidation.org/xml/ns/validation/[Jakarta Bean Validation website]. ==== [[section-configuration-validation-xml]] @@ -51,7 +51,7 @@ There must only be one file named _META-INF/validation.xml_ on the classpath. If found an exception is thrown. ==== -The node `default-provider` allows to choose the Bean Validation provider. This is useful if there is +The node `default-provider` allows to choose the Jakarta Bean Validation provider. This is useful if there is more than one provider on the classpath. `message-interpolator`, `traversable-resolver`, `constraint-validator-factory`, `parameter-name-provider` and `clock-provider` allow to customize the used implementations for the interfaces `MessageInterpolator`, `TraversableResolver`, @@ -64,7 +64,7 @@ interfaces. container types or to override the built-in value extractors. See <> for more information about how to implement `javax.validation.valueextraction.ValueExtractor`. -`executable-validation` and its subnodes define defaults for method validation. The Bean Validation +`executable-validation` and its subnodes define defaults for method validation. The Jakarta Bean Validation specification defines constructor and non getter methods as defaults. The enabled attribute acts as global switch to turn method validation on and off (see also <>). @@ -136,7 +136,7 @@ The nodes `class`, `field`, `getter`, `container-element-type`, `constructor` an The `valid` node is used to enable cascaded validation and the `constraint` node to add a constraint on the corresponding level. Each constraint definition must define the class via the `annotation` attribute. -The constraint attributes required by the Bean Validation specification (`message`, `groups` and +The constraint attributes required by the Jakarta Bean Validation specification (`message`, `groups` and `payload`) have dedicated nodes. All other constraint specific attributes are configured using the `element` node. diff --git a/documentation/src/main/asciidoc/ch09.asciidoc b/documentation/src/main/asciidoc/ch09.asciidoc index 71bd211202..2c26d41a63 100644 --- a/documentation/src/main/asciidoc/ch09.asciidoc +++ b/documentation/src/main/asciidoc/ch09.asciidoc @@ -30,7 +30,7 @@ Hibernate Validator uses the factory as context for caching constraint metadata work with one factory instance within an application. ==== -Bean Validation supports working with several providers such as Hibernate Validator within one +Jakarta Bean Validation supports working with several providers such as Hibernate Validator within one application. If more than one provider is present on the classpath, it is not guaranteed which one is chosen when creating a factory via `buildDefaultValidatorFactory()`. @@ -71,7 +71,7 @@ If a `ValidatorFactory` instance is no longer in use, it should be disposed by c [[section-validation-provider-resolver]] ==== `ValidationProviderResolver` -By default, available Bean Validation providers are discovered using the +By default, available Jakarta Bean Validation providers are discovered using the {javaTechnotesBaseUrl}/guides/jar/jar.html#Service_Provider[Java Service Provider] mechanism. @@ -114,7 +114,7 @@ If you want to disable the XML based configuration, you can do so by invoking The different values of the XML configuration can be accessed via `Configuration#getBootstrapConfiguration()`. This can for instance be helpful if you want to integrate -Bean Validation into a managed environment and want to create managed instances of the objects +Jakarta Bean Validation into a managed environment and want to create managed instances of the objects configured via XML. Using the fluent configuration API, you can override one or more of the settings when bootstrapping diff --git a/documentation/src/main/asciidoc/ch10.asciidoc b/documentation/src/main/asciidoc/ch10.asciidoc index 6bd9a6fd24..12c13e31b9 100644 --- a/documentation/src/main/asciidoc/ch10.asciidoc +++ b/documentation/src/main/asciidoc/ch10.asciidoc @@ -1,7 +1,7 @@ [[validator-metadata-api]] == Using constraint metadata -The Bean Validation specification provides not only a validation engine, but also an API for +The Jakarta Bean Validation specification provides not only a validation engine, but also an API for retrieving constraint metadata in a uniform way, no matter whether the constraints are declared using annotations or via XML mappings. Read this chapter to learn more about this API and its possibilities. You can find all the metadata API types in the package `javax.validation.metadata`. diff --git a/documentation/src/main/asciidoc/ch11.asciidoc b/documentation/src/main/asciidoc/ch11.asciidoc index 9bf9cf4ece..0ed5b3a502 100644 --- a/documentation/src/main/asciidoc/ch11.asciidoc +++ b/documentation/src/main/asciidoc/ch11.asciidoc @@ -98,7 +98,7 @@ configuration in _hibernate.cfg.xml_: ==== JPA If you are using JPA 2 and Hibernate Validator is in the classpath, the JPA2 specification requires -that Bean Validation gets enabled. The properties `javax.persistence.validation.group.pre-persist`, +that Jakarta Bean Validation gets enabled. The properties `javax.persistence.validation.group.pre-persist`, `javax.persistence.validation.group.pre-update` and `javax.persistence.validation.group.pre-remove` as described in <> can in this case be configured in _persistence.xml_. _persistence.xml_ also defines a node validation-mode which can be set to `AUTO`, @@ -108,7 +108,7 @@ _persistence.xml_. _persistence.xml_ also defines a node validation-mode which c === JSF & Seam -When working with JSF2 or JBoss Seam and Hibernate Validator (Bean Validation) is present in the +When working with JSF2 or JBoss Seam and Hibernate Validator (Jakarta Bean Validation) is present in the runtime environment, validation is triggered for every field in the application. <> shows an example of the `f:validateBean` tag in a JSF page. The `validationGroups` attribute is optional and can be used to specify a comma separated list of validation groups. The default is @@ -117,7 +117,7 @@ specification. [[example-jsf2]] -.Usage of Bean Validation within JSF2 +.Usage of Jakarta Bean Validation within JSF2 ==== [source, XML] ---- @@ -137,12 +137,12 @@ specification. [TIP] ==== -The integration between JSF 2 and Bean Validation is described in the "Bean Validation Integration" +The integration between JSF 2 and Jakarta Bean Validation is described in the "Jakarta Bean Validation Integration" chapter of http://jcp.org/en/jsr/detail?id=314[JSR-314]. It is interesting to know that JSF 2 implements a custom `MessageInterpolator` to ensure proper localization. To encourage the use -of the Bean Validation message facility, JSF 2 will per default only display the generated Bean +of the Jakarta Bean Validation message facility, JSF 2 will per default only display the generated Bean Validation message. This can, however, be configured via the application resource bundle by -providing the following configuration (`{0}` is replaced with the Bean Validation message and `{1}` is +providing the following configuration (`{0}` is replaced with the Jakarta Bean Validation message and `{1}` is replaced with the JSF component label): ---- @@ -160,8 +160,8 @@ javax.faces.validator.BeanValidator.MESSAGE={0} [[section-integration-with-cdi]] === CDI -As of version 1.1, Bean Validation is integrated with CDI (Contexts and Dependency Injection for -Java^TM^ EE). +As of version 1.1, Bean Validation (and therefore Jakarta Bean Validation) is integrated with CDI +(Contexts and Dependency Injection for Jakarta EE). This integration provides CDI managed beans for `Validator` and `ValidatorFactory` and enables dependency injection in constraint validators as well as custom message interpolators, traversable @@ -192,10 +192,10 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter11/cdi/valida ==== The injected beans are the default validator factory and validator instances. In order to configure -them - e.g. to use a custom message interpolator - you can use the Bean Validation XML descriptors +them - e.g. to use a custom message interpolator - you can use the Jakarta Bean Validation XML descriptors as discussed in <>. -If you are working with several Bean Validation providers, you can make sure that factory and +If you are working with several Jakarta Bean Validation providers, you can make sure that factory and validator from Hibernate Validator are injected by annotating the injection points with the `@HibernateValidator` qualifier which is demonstrated in <>. @@ -217,7 +217,7 @@ used for selecting Hibernate Validator when working with the bootstrapping API ( <>). ==== -Via `@Inject` you also can inject dependencies into constraint validators and other Bean Validation +Via `@Inject` you also can inject dependencies into constraint validators and other Jakarta Bean Validation objects such as `MessageInterpolator` implementations etc. <> @@ -237,7 +237,7 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter11/cdi/inject ==== Method validation -The method interception facilities of CDI allow for a very tight integration with Bean Validation's +The method interception facilities of CDI allow for a very tight integration with Jakarta Bean Validation's method validation functionality. Just put constraint annotations to the parameters and return values of the executables of your CDI beans and they will be validated automatically before (parameter constraints) and after (return value constraints) a method or constructor is invoked. @@ -283,7 +283,7 @@ value is marked with `@Valid`. ===== Validated executable types -Bean Validation allows for a fine-grained control of the executable types which are automatically +Jakarta Bean Validation allows for a fine-grained control of the executable types which are automatically validated. By default, constraints on constructors and non-getter methods are validated. Therefore the `@NotNull` constraint on the method `RentalStation#getAvailableCars()` in <> does not get validated when the method is invoked. diff --git a/documentation/src/main/asciidoc/ch12.asciidoc b/documentation/src/main/asciidoc/ch12.asciidoc index 27960a4043..6d6e205f68 100644 --- a/documentation/src/main/asciidoc/ch12.asciidoc +++ b/documentation/src/main/asciidoc/ch12.asciidoc @@ -2,7 +2,7 @@ == Hibernate Validator Specifics In this chapter you will learn how to make use of several features provided by Hibernate Validator -in addition to the functionality defined by the Bean Validation specification. This includes the +in addition to the functionality defined by the Jakarta Bean Validation specification. This includes the fail fast mode, the API for programmatic constraint configuration and the boolean composition of constraints. @@ -16,7 +16,7 @@ Validator. [NOTE] ==== Using the features described in the following sections may result in application code which is not -portable between Bean Validation providers. +portable between Jakarta Bean Validation providers. ==== === Public API @@ -25,13 +25,13 @@ Let's start, however, with a look at the public API of Hibernate Validator. Belo Note that when a package is part of the public API this is not necessarily true for its sub-packages. `org.hibernate.validator`:: - Classes used by the Bean Validation bootstrap mechanism (eg. validation provider, configuration class); for more details see <>. + Classes used by the Jakarta Bean Validation bootstrap mechanism (eg. validation provider, configuration class); for more details see <>. `org.hibernate.validator.cfg`, `org.hibernate.validator.cfg.context`, `org.hibernate.validator.cfg.defs`, `org.hibernate.validator.spi.cfg`:: Hibernate Validator's fluent API for constraint declaration; in `org.hibernate.validator.cfg` you will find the `ConstraintMapping` interface, in `org.hibernate.validator.cfg.defs` all constraint definitions and in `org.hibernate.validator.spi.cfg` a callback for using the API for configuring the default validator factory. Refer to <> for the details. `org.hibernate.validator.constraints`, `org.hibernate.validator.constraints.br`, `org.hibernate.validator.constraints.pl`:: - Some useful custom constraints provided by Hibernate Validator in addition to the built-in constraints defined by the Bean Validation specification; the constraints are described in detail in <>. + Some useful custom constraints provided by Hibernate Validator in addition to the built-in constraints defined by the Jakarta Bean Validation specification; the constraints are described in detail in <>. `org.hibernate.validator.constraintvalidation`:: Extended constraint validator context which allows to set custom attributes for message interpolation. <> describes how to make use of that feature. @@ -107,13 +107,13 @@ fail fast mode when bootstrapping a validator. [[section-method-validation-prerequisite-relaxation]] === Relaxation of requirements for method validation in class hierarchies -The Bean Validation specification defines a set of preconditions which apply when defining +The Jakarta Bean Validation specification defines a set of preconditions which apply when defining constraints on methods within class hierarchies. These preconditions are defined in {bvSpecUrl}#constraintdeclarationvalidationprocess-methodlevelconstraints-inheritance[section 5.6.5] -of the Bean Validation 2.0 specification. See also <> +of the Jakarta Bean Validation 2.0 specification. See also <> in this guide. -As per specification, a Bean Validation provider is allowed to relax these preconditions. +As per specification, a Jakarta Bean Validation provider is allowed to relax these preconditions. With Hibernate Validator you can do this in one of two ways. First you can use the configuration properties _hibernate.validator.allow_parameter_constraint_override_, @@ -154,7 +154,7 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/relaxation ==== By default, all of these properties are false, implementing the default behavior as defined in the -Bean Validation specification. +Jakarta Bean Validation specification. [WARNING] ==== @@ -166,7 +166,7 @@ requires changes to the default behaviour. [[section-programmatic-api]] === Programmatic constraint definition and declaration -As per the Bean Validation specification, you can define and declare constraints using Java annotations and XML +As per the Jakarta Bean Validation specification, you can define and declare constraints using Java annotations and XML based constraint mappings. In addition, Hibernate Validator provides a fluent API which allows for the programmatic @@ -333,7 +333,7 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/purelycomp [[section-boolean-constraint-composition]] ==== Boolean composition of constraints -Bean Validation specifies that the constraints of a composed constraint (see +Jakarta Bean Validation specifies that the constraints of a composed constraint (see <>) are all combined via a logical _AND_. This means all of the composing constraints need to return true to obtain an overall successful validation. @@ -421,7 +421,7 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/dynamicpay Hibernate Validator requires per default an implementation of the Unified EL (see <>) to be available. This is needed to allow the interpolation -of constraint error messages using EL expressions as defined by the Bean Validation specification. +of constraint error messages using EL expressions as defined by the Jakarta Bean Validation specification. For environments where you cannot or do not want to provide an EL implementation, Hibernate Validator offers a non EL based message interpolator - `org.hibernate.validator.messageinterpolation.ParameterMessageInterpolator`. @@ -445,7 +445,7 @@ interpolation algorithm as defined by the specification. Refer to === Custom contexts -The Bean Validation specification offers at several points in its API the possibility to unwrap a +The Jakarta Bean Validation specification offers at several points in its API the possibility to unwrap a given interface to an implementor specific subtype. In the case of constraint violation creation in `ConstraintValidator` implementations as well as message interpolation in `MessageInterpolator` instances, there exist `unwrap()` methods for the provided context instances - @@ -546,7 +546,7 @@ Alternatively you can specify a `Paranamer` implementation of your choice when c [[section-constraint-definition-contribution]] === Providing constraint definitions -Bean Validation allows to (re-)define constraint definitions via XML in its constraint mapping +Jakarta Bean Validation allows to (re-)define constraint definitions via XML in its constraint mapping files. See <> for more information and <> for an example. While this approach is sufficient for many use cases, it has its shortcomings in others. Imagine for example a constraint library wanting to contribute constraint diff --git a/documentation/src/main/asciidoc/ch13.asciidoc b/documentation/src/main/asciidoc/ch13.asciidoc index c352b8c4bf..34901b6eb7 100644 --- a/documentation/src/main/asciidoc/ch13.asciidoc +++ b/documentation/src/main/asciidoc/ch13.asciidoc @@ -57,7 +57,7 @@ The behavior of the Hibernate Validator Annotation Processor can be controlled u `methodConstraintsSupported`:: Controls whether constraints are allowed at methods of any kind. Must be set to `true` when working with method level constraints as supported by Hibernate Validator. Can be set to `false` to allow constraints only at - JavaBeans getter methods as defined by the Bean Validation API. Defaults to `true`. + JavaBeans getter methods as defined by the Jakarta Bean Validation API. Defaults to `true`. `verbose`:: Controls whether detailed processing information shall be displayed or not, useful for debugging purposes. Must be either diff --git a/documentation/src/main/asciidoc/ch14.asciidoc b/documentation/src/main/asciidoc/ch14.asciidoc index 3e3127a821..3d53eb087a 100644 --- a/documentation/src/main/asciidoc/ch14.asciidoc +++ b/documentation/src/main/asciidoc/ch14.asciidoc @@ -3,11 +3,11 @@ Last but not least, a few pointers to further information. -A great source for examples is the Bean Validation TCK which is available for anonymous access on +A great source for examples is the Jakarta Bean Validation TCK which is available for anonymous access on https://github.com/beanvalidation/beanvalidation-tck/[GitHub]. In particular the TCK's https://github.com/beanvalidation/beanvalidation-tck/tree/master/tests[tests] might be -of interest. {bvSpecUrl}[The JSR 380] specification itself -is also a great way to deepen your understanding of Bean Validation and Hibernate Validator. +of interest. {bvSpecUrl}[The Jakarta Bean Validation] specification itself +is also a great way to deepen your understanding of Jakarta Bean Validation and Hibernate Validator. If you have any further questions about Hibernate Validator or want to share some of your use cases, have a look at the http://community.jboss.org/en/hibernate/validator[Hibernate Validator diff --git a/documentation/src/main/asciidoc/index.asciidoc b/documentation/src/main/asciidoc/index.asciidoc index 372e1fc27b..369db481d9 100644 --- a/documentation/src/main/asciidoc/index.asciidoc +++ b/documentation/src/main/asciidoc/index.asciidoc @@ -1,4 +1,4 @@ -= Hibernate Validator {hvVersion} - JSR 380 Reference Implementation: Reference Guide += Hibernate Validator {hvVersion} - Jakarta Bean Validation Reference Implementation: Reference Guide Hardy Ferentschik; Gunnar Morling; Guillaume Smet :doctype: book :revdate: {docdate} diff --git a/documentation/src/main/asciidoc/pr01.asciidoc b/documentation/src/main/asciidoc/pr01.asciidoc index acb4bdfc85..16712c068c 100644 --- a/documentation/src/main/asciidoc/pr01.asciidoc +++ b/documentation/src/main/asciidoc/pr01.asciidoc @@ -11,7 +11,7 @@ code which is really metadata about the class itself. image::application-layers.png[] -JSR 380 - Bean Validation 2.0 - defines a metadata model and API for entity and method validation. +Jakarta Bean Validation 2.0 - defines a metadata model and API for entity and method validation. The default metadata source are annotations, with the ability to override and extend the meta-data through the use of XML. The API is not tied to a specific application tier nor programming model. It is specifically not tied to either web or persistence tier, and is available for both server-side @@ -19,8 +19,8 @@ application programming, as well as rich client Swing application developers. image::application-layers2.png[] -Hibernate Validator is the reference implementation of this JSR 380. The implementation itself as -well as the Bean Validation API and TCK are all provided and distributed under the +Hibernate Validator is the reference implementation of Jakarta Bean Validation. The implementation itself as +well as the Jakarta Bean Validation API and TCK are all provided and distributed under the http://www.apache.org/licenses/LICENSE-2.0[Apache Software License 2.0]. -Hibernate Validator 6 and Bean Validation 2.0 require Java 8 or later. +Hibernate Validator 6 and Jakarta Bean Validation 2.0 require Java 8 or later. From 40e1f681122721fce34278542c7c97efe43b0a9e Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 1 Aug 2019 11:33:19 +0200 Subject: [PATCH 258/393] HV-1725 Update README.md for Jakarta --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7a3eedae70..6282652ea7 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ ## What is it? -This is the reference implementation of [JSR-380 - Bean Validation 2.0](http://beanvalidation.org/). -Bean Validation defines a metadata model and API for JavaBean as well as method validation. +This is the reference implementation of [Jakarta Bean Validation 2.0](http://beanvalidation.org/). +Jakarta Bean Validation defines a metadata model and API for JavaBean as well as method validation. The default metadata source are annotations, with the ability to override and extend the metadata through the use of XML validation descriptors. @@ -47,7 +47,7 @@ Logging will delegate any log requests to that provider. 3.0.1-b09 -* Bean Validation defines integration points with [CDI](http://jcp.org/en/jsr/detail?id=346). If your application runs +* Jakarta Bean Validation defines integration points with [CDI](http://jcp.org/en/jsr/detail?id=346). If your application runs in an environment which does not provide this integration out of the box, you may use the Hibernate Validator CDI portable extension by adding the following dependency: @@ -63,7 +63,7 @@ documentation](https://docs.jboss.org/hibernate/stable/validator/reference/en-US ## Licensing -Hibernate Validator itself as well as the Bean Validation API and TCK are all provided and distributed under +Hibernate Validator itself as well as the Jakarta Bean Validation API and TCK are all provided and distributed under the Apache Software License 2.0. Refer to license.txt for more information. ## Build from Source @@ -84,7 +84,7 @@ We provide a `.travis.yml` file so that you can enable CI for your GitHub fork b ## Hibernate Validator URLs * [Home Page](http://hibernate.org/validator/) -* [Bean Validation Home](http://beanvalidation.org/) +* [Jakarta Bean Validation Home](http://beanvalidation.org/) * [Downloads](http://hibernate.org/validator/downloads/) * [Mailing Lists](http://hibernate.org/community/) * [Issue Tracking](https://hibernate.atlassian.net/browse/HV) From a263a0cc6db60ad8e79df15fc3860933e336e793 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 1 Aug 2019 12:17:08 +0200 Subject: [PATCH 259/393] HV-1725 Update the Specification-Title to Jakarta Bean Validation --- cdi/pom.xml | 2 +- engine/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cdi/pom.xml b/cdi/pom.xml index 8266468aea..3c015a0119 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -152,7 +152,7 @@ ${project.build.outputDirectory}/META-INF/MANIFEST.MF - Bean Validation + Jakarta Bean Validation 2.0 ${hibernate-validator-cdi.module-name} diff --git a/engine/pom.xml b/engine/pom.xml index eb7667dda7..96a5042933 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -207,7 +207,7 @@ ${project.build.outputDirectory}/META-INF/MANIFEST.MF - Bean Validation + Jakarta Bean Validation 2.0 ${hibernate-validator.module-name} From a5506a14c3c00aac366ac6b980805c69e6bd371f Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 1 Aug 2019 12:17:44 +0200 Subject: [PATCH 260/393] HV-1725 Update some javadoc referencing the JSR or Bean Validation --- .../internal/engine/MethodValidationConfiguration.java | 6 +++--- .../hibernate/validator/internal/engine/package-info.java | 2 +- engine/src/main/java/org/hibernate/validator/overview.html | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/MethodValidationConfiguration.java b/engine/src/main/java/org/hibernate/validator/internal/engine/MethodValidationConfiguration.java index 5a04e4bfc7..b9f945fdaf 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/MethodValidationConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/MethodValidationConfiguration.java @@ -21,7 +21,7 @@ import org.hibernate.validator.internal.util.stereotypes.Immutable; /** - * These properties modify the behavior of the {@code Validator} with respect to the Bean Validation + * These properties modify the behavior of the {@code Validator} with respect to the Jakarta Bean Validation * specification section 5.6.5. In particular: *

      * "Out of the box, a conforming Bean Validation provider must throw a
    @@ -164,7 +164,7 @@ public Builder(MethodValidationConfiguration template) {
     		 * Define whether overriding methods that override constraints should throw a {@code ConstraintDefinitionException}.
     		 * The default value is {@code false}, i.e. do not allow.
     		 *
    -		 * See Section 5.6.5 of the JSR-380 Specification, specifically
    +		 * See Section 5.6.5 of the Jakarta Bean Validation Specification, specifically
     		 * 
     		 * "In sub types (be it sub classes/interfaces or interface implementations), no parameter constraints may
     		 * be declared on overridden or implemented methods, nor may parameters be marked for cascaded validation.
    @@ -202,7 +202,7 @@ public Builder allowMultipleCascadedValidationOnReturnValues(boolean allow) {
     		 * Define whether parallel methods that define constraints should throw a {@code ConstraintDefinitionException}. The
     		 * default value is {@code false}, i.e. do not allow.
     		 *
    -		 * See Section 5.6.5 of the JSR-380 Specification, specifically
    +		 * See Section 5.6.5 of the Jakarta Bean Validation Specification, specifically
     		 * "If a sub type overrides/implements a method originally defined in several parallel types of the hierarchy
     		 * (e.g. two interfaces not extending each other, or a class and an interface not implemented by said class),
     		 * no parameter constraints may be declared for that method at all nor parameters be marked for cascaded validation.
    diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/package-info.java b/engine/src/main/java/org/hibernate/validator/internal/engine/package-info.java
    index eda64a88af..d154589477 100644
    --- a/engine/src/main/java/org/hibernate/validator/internal/engine/package-info.java
    +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/package-info.java
    @@ -6,6 +6,6 @@
      */
     
     /**
    - * Implementations for the core interfaces of JSR-380.
    + * Implementations for the core interfaces of Jakarta Bean Validation.
      */
     package org.hibernate.validator.internal.engine;
    diff --git a/engine/src/main/java/org/hibernate/validator/overview.html b/engine/src/main/java/org/hibernate/validator/overview.html
    index c5a8036ebd..af6ef29a56 100644
    --- a/engine/src/main/java/org/hibernate/validator/overview.html
    +++ b/engine/src/main/java/org/hibernate/validator/overview.html
    @@ -10,7 +10,7 @@
     
     
     

    This is the Hibernate Validator API documentation. Hibernate Validator is the reference implementation of - Bean Validation 2.0 - JSR-380 + https://projects.eclipse.org/projects/ee4j.bean-validation[Jakarta Bean Validation 2.0].

    All classes fall into three categories: From 77c2a792c5bc1f0fa79697efa348786ba02a809d Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 1 Aug 2019 12:18:07 +0200 Subject: [PATCH 261/393] HV-1725 Update messages referencing Bean Validation --- .../validator/ap/ValidationProcessorMessages.properties | 2 +- .../org/hibernate/validator/internal/util/logging/Messages.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/annotation-processor/src/main/resources/org/hibernate/validator/ap/ValidationProcessorMessages.properties b/annotation-processor/src/main/resources/org/hibernate/validator/ap/ValidationProcessorMessages.properties index 9988c9eab4..cec98220cd 100644 --- a/annotation-processor/src/main/resources/org/hibernate/validator/ap/ValidationProcessorMessages.properties +++ b/annotation-processor/src/main/resources/org/hibernate/validator/ap/ValidationProcessorMessages.properties @@ -48,6 +48,6 @@ INVALID_GROUP_SEQUENCE_VALUE_NOT_INTERFACES=Invalid @GroupSequence configuration INVALID_GROUP_SEQUENCE_VALUE_CYCLIC_DEFINITION=Invalid @GroupSequence configuration. The defined group sequence should be expandable (no cyclic definition). INVALID_GROUP_SEQUENCE_VALUE_MISSING_HOSTING_BEAN_DECLARATION=Invalid default group sequence redefinition. The value should contain the hosting bean class. INVALID_GROUP_SEQUENCE_VALUE_MULTIPLE_DECLARATIONS_OF_THE_SAME_INTERFACE=Invalid @GroupSequence configuration. {0} was already declared in this group sequence. -INVALID_GROUP_SEQUENCE_EXTEND_INTERFACES=Having group sequences extending other interfaces is discouraged by the Bean Validation specification. +INVALID_GROUP_SEQUENCE_EXTEND_INTERFACES=Having group sequences extending other interfaces is discouraged by the Jakarta Bean Validation specification. MIXED_LIST_AND_DIRECT_ANNOTATION_DECLARATION=Constraint @{0} is declared both directly and as a list. Which is not allowed. INVALID_PAYLOAD_UNWRAPPING_VALUE_ANNOTATION_PARAMETERS=Having both Unwrapping.Unwrap and Unwrapping.Skip in the payload is not allowed. diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Messages.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Messages.java index f03e6102ee..5ae9361a3d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Messages.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Messages.java @@ -86,7 +86,7 @@ public interface Messages { "This can happen most notably in a Google App Engine environment or when running Hibernate Validator as Java 9 named module. " + "A PlatformResourceBundleLocator without bundle aggregation was created. " + "This only affects you in case you are using multiple ConstraintDefinitionContributor JARs. " + - "ConstraintDefinitionContributors are a Hibernate Validator specific feature. All Bean Validation " + + "ConstraintDefinitionContributors are a Hibernate Validator specific feature. All Jakarta Bean Validation " + "features work as expected. See also https://hibernate.atlassian.net/browse/HV-1023.") String unableToUseResourceBundleAggregation(); From fdfa7cef6c315f5c3c7318a352f7c47c9f11f713 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 18 Oct 2019 12:57:57 +0200 Subject: [PATCH 262/393] HV-1725 Explicitly ban javax dependencies --- cdi/pom.xml | 22 ++++++++++++++++++++++ engine/pom.xml | 12 ++++++++++++ integration/pom.xml | 34 ++++++++++++++++++++++++++++++++++ osgi/integrationtest/pom.xml | 12 ++++++++++++ pom.xml | 10 ++++++++++ 5 files changed, 90 insertions(+) diff --git a/cdi/pom.xml b/cdi/pom.xml index 3c015a0119..9d4172f7ad 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -90,6 +90,28 @@ org.jboss.weld weld-core-impl test + + + javax.enterprise + cdi-api + + + org.jboss.spec.javax.el + jboss-el-api_3.0_spec + + + org.jboss.spec.javax.interceptor + + jboss-interceptors-api_1.2_spec + + + + org.jboss.spec.javax.annotation + + jboss-annotations-api_1.3_spec + + + org.jboss.shrinkwrap.resolver diff --git a/engine/pom.xml b/engine/pom.xml index 96a5042933..d5a8abde8f 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -146,6 +146,18 @@ org.javamoney moneta test + + + javax.annotation + javax.annotation-api + + + + + + jakarta.annotation + jakarta.annotation-api + test com.fasterxml.jackson.core diff --git a/integration/pom.xml b/integration/pom.xml index e0ac3d07fb..1cc7e971b3 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -76,6 +76,18 @@ org.javamoney moneta test + + + javax.annotation + javax.annotation-api + + + + + + jakarta.annotation + jakarta.annotation-api + test org.jboss.arquillian.testng @@ -91,6 +103,28 @@ org.jboss.weld weld-core-impl test + + + org.jboss.spec.javax.interceptor + + jboss-interceptors-api_1.2_spec + + + + javax.enterprise + cdi-api + + + + + jakarta.interceptor + jakarta.interceptor-api + test + + + jakarta.enterprise + jakarta.enterprise.cdi-api + test jakarta.persistence diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 61768b6729..c767009832 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -64,6 +64,18 @@ org.javamoney moneta test + + + javax.annotation + javax.annotation-api + + + + + + jakarta.annotation + jakarta.annotation-api + test diff --git a/pom.xml b/pom.xml index 29d04eabf7..d516786b1b 100644 --- a/pom.xml +++ b/pom.xml @@ -536,6 +536,16 @@ ${maven.min.version} + + + javax.validation:validation-api + org.glassfish:javax.el + javax.annotation:javax.annotation-api + org.jboss.spec.javax.interceptor:jboss-interceptors-api_1.2_spec + javax.enterprise:cdi-api + javax.persistence:javax.persistence-api + + From b115bb6d6b581beca9535dda49cba078c66472b0 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 18 Oct 2019 12:58:18 +0200 Subject: [PATCH 263/393] HV-1725 Fix a few remaining things in the README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6282652ea7..47700eca4b 100644 --- a/README.md +++ b/README.md @@ -39,12 +39,12 @@ Logging will delegate any log requests to that provider. You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. - In an EE environment they are often already provided. + In a Jakarta EE environment, they are often already provided. org.glassfish - javax.el - 3.0.1-b09 + jakarta.el + 3.0.3 * Jakarta Bean Validation defines integration points with [CDI](http://jcp.org/en/jsr/detail?id=346). If your application runs From ce6c698d886b7118900a3d8406927a36239426a9 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 18 Oct 2019 16:07:06 +0200 Subject: [PATCH 264/393] HV-1741 Upgrade ByteBuddy test dependency to 1.10.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d516786b1b..8b26acc1ea 100644 --- a/pom.xml +++ b/pom.xml @@ -174,7 +174,7 @@ 1.0.0.Final 2.9.10 2.9.10 - 1.10.1 + 1.10.2 4.2.0 From 8b92994c55308f45d7e9e9bafec020668edac2f1 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 18 Oct 2019 16:28:50 +0200 Subject: [PATCH 265/393] HV-1742 Upgrade to WildFly 18.0.0.Final --- modules/src/script/setupModules.groovy | 4 ++-- pom.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/src/script/setupModules.groovy b/modules/src/script/setupModules.groovy index 41a2bd420e..dbc2d2ea48 100644 --- a/modules/src/script/setupModules.groovy +++ b/modules/src/script/setupModules.groovy @@ -26,10 +26,10 @@ bvModuleXml = new File( wildflyPatchedTargetDir, 'modules/system/layers/base/jav def bvArtifactName = 'jakarta.validation-api-' + project.properties['version.jakarta.validation-api'] + '.jar'; println "[INFO] Using Jakarta Bean Validation version " + bvArtifactName; processFileInplace( bvModuleXml ) { text -> - text.replaceAll( /validation-api.*jar/, bvArtifactName ) + text.replaceAll( /2.1.0.Final - 17.0.1.Final + 18.0.0.Final - 16.0.0.Final + 17.0.1.Final ${version.wildfly} From 2687d3353990b869d7aaeddcdcba17ec5daf158d Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 18 Oct 2019 16:31:43 +0200 Subject: [PATCH 266/393] HV-1743 Upgrade maven-compiler-plugin to 3.8.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8db3ee1f88..20ba8f1094 100644 --- a/pom.xml +++ b/pom.xml @@ -208,7 +208,7 @@ 3.5.0 3.0.0 3.0.0 - 3.7.0 + 3.8.1 0.0.6 3.0.2 1.4.0 From 124b7dd6d9a4ad24d4d49f74701f05a13e56ceee Mon Sep 17 00:00:00 2001 From: Davide D'Alto Date: Fri, 18 Oct 2019 16:45:20 +0200 Subject: [PATCH 267/393] HV-1739 Fix CVE-2019-10219 Security issue with @SafeHtml --- .../hv/SafeHtmlValidator.java | 10 ++--- .../hv/SafeHtmlValidatorTest.java | 38 +++++++++++++++++++ 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/SafeHtmlValidator.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/SafeHtmlValidator.java index 89dd07f438..ebefed7d2c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/SafeHtmlValidator.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/SafeHtmlValidator.java @@ -6,7 +6,7 @@ */ package org.hibernate.validator.internal.constraintvalidators.hv; -import java.util.Iterator; +import java.util.List; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; @@ -14,7 +14,7 @@ import org.hibernate.validator.constraints.SafeHtml; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; +import org.jsoup.nodes.Node; import org.jsoup.parser.Parser; import org.jsoup.safety.Cleaner; import org.jsoup.safety.Whitelist; @@ -91,9 +91,9 @@ private Document getFragmentAsDocument(CharSequence value) { Document document = Document.createShell( baseURI ); // add the fragment's nodes to the body of resulting document - Iterator nodes = fragment.children().iterator(); - while ( nodes.hasNext() ) { - document.body().appendChild( nodes.next() ); + List childNodes = fragment.childNodes(); + for ( Node node : childNodes ) { + document.body().appendChild( node.clone() ); } return document; diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/SafeHtmlValidatorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/SafeHtmlValidatorTest.java index 7eb9e31737..45e6f031da 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/SafeHtmlValidatorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/SafeHtmlValidatorTest.java @@ -57,6 +57,44 @@ public void testInvalidScriptTagIncluded() throws Exception { assertFalse( getSafeHtmlValidator().isValid( "HelloWorld !", null ) ); } + @Test + // A "downlevel revealed" conditional 'comment' is not an (X)HTML comment at all, + // despite the misleading name, it is default Microsoft syntax. + // The tag is unrecognized by therefore executed + public void testDownlevelRevealedConditionalComment() throws Exception { + descriptorBuilder.setAttribute( "whitelistType", WhiteListType.BASIC ); + + assertFalse( getSafeHtmlValidator().isValid( "\n\n", null ) ); + } + + @Test + public void testDownlevelHiddenConditionalComment() throws Exception { + descriptorBuilder.setAttribute( "whitelistType", WhiteListType.BASIC ); + + assertFalse( getSafeHtmlValidator().isValid( "", null ) ); + } + + @Test + public void testSimpleComment() throws Exception { + descriptorBuilder.setAttribute( "whitelistType", WhiteListType.BASIC ); + + assertFalse( getSafeHtmlValidator().isValid( "", null ) ); + } + + @Test + public void testServerSideIncludesSSI() throws Exception { + descriptorBuilder.setAttribute( "whitelistType", WhiteListType.BASIC ); + + assertFalse( getSafeHtmlValidator().isValid( "alert{\"XSS\"}'}; ?>", null ) ); + } + + @Test + public void testPHPScript() throws Exception { + descriptorBuilder.setAttribute( "whitelistType", WhiteListType.BASIC ); + + assertFalse( getSafeHtmlValidator().isValid( "alert{\"XSS\"}'}; ?>", null ) ); + } + @Test public void testInvalidIncompleteImgTagWithScriptIncluded() { descriptorBuilder.setAttribute( "whitelistType", WhiteListType.BASIC ); From 4194b025e062f2fc03af1bcd0fa63e8ac67e84c1 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 18 Oct 2019 16:47:54 +0200 Subject: [PATCH 268/393] HV-1740 Deprecate @SafeHtml for planned future removal --- .../main/java/org/hibernate/validator/cfg/defs/SafeHtmlDef.java | 2 ++ .../main/java/org/hibernate/validator/constraints/SafeHtml.java | 2 ++ .../internal/constraintvalidators/hv/SafeHtmlValidator.java | 2 ++ 3 files changed, 6 insertions(+) diff --git a/engine/src/main/java/org/hibernate/validator/cfg/defs/SafeHtmlDef.java b/engine/src/main/java/org/hibernate/validator/cfg/defs/SafeHtmlDef.java index a12569741a..1f04b6dbbb 100644 --- a/engine/src/main/java/org/hibernate/validator/cfg/defs/SafeHtmlDef.java +++ b/engine/src/main/java/org/hibernate/validator/cfg/defs/SafeHtmlDef.java @@ -12,7 +12,9 @@ /** * @author Marko Bekta + * @deprecated {@code @SafeHtml} support will be removed in a future version */ +@Deprecated public class SafeHtmlDef extends ConstraintDef { public SafeHtmlDef() { diff --git a/engine/src/main/java/org/hibernate/validator/constraints/SafeHtml.java b/engine/src/main/java/org/hibernate/validator/constraints/SafeHtml.java index fa08e2fa81..86d7848cec 100644 --- a/engine/src/main/java/org/hibernate/validator/constraints/SafeHtml.java +++ b/engine/src/main/java/org/hibernate/validator/constraints/SafeHtml.java @@ -34,12 +34,14 @@ * {@code body} tags to the used whitelist as required. * * @author George Gastaldi + * @deprecated {@code @SafeHtml} support will be removed in a future version */ @Documented @Constraint(validatedBy = { }) @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) @Retention(RUNTIME) @Repeatable(List.class) +@Deprecated public @interface SafeHtml { String message() default "{org.hibernate.validator.constraints.SafeHtml.message}"; diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/SafeHtmlValidator.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/SafeHtmlValidator.java index ebefed7d2c..3949aedc51 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/SafeHtmlValidator.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/SafeHtmlValidator.java @@ -27,7 +27,9 @@ * @author George Gastaldi * @author Hardy Ferentschik * @author Marko Bekhta + * @deprecated {@code @SafeHtml} support will be removed in a future version */ +@Deprecated public class SafeHtmlValidator implements ConstraintValidator { private Whitelist whitelist; From 77c9ca3a1d7e8d2c774827f83afa9225acbde76d Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 25 Oct 2019 08:42:21 +0000 Subject: [PATCH 269/393] [Jenkins release job] README.md updated by release build 6.1.0.Final --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 47700eca4b..977b7886d9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hibernate Validator -*Version: 6.1.0.Alpha6 - 19-07-2019* +*Version: 6.1.0.Final - 25-10-2019* ## What is it? @@ -35,7 +35,7 @@ Logging will delegate any log requests to that provider. org.hibernate.validator hibernate-validator - 6.1.0.Alpha6 + 6.1.0.Final You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. @@ -54,7 +54,7 @@ extension by adding the following dependency: org.hibernate.validator hibernate-validator-cdi - 6.1.0.Alpha6 + 6.1.0.Final * _hibernate-validator-annotation-processor-<version>.jar_ is an optional jar which can be integrated with your build From 7ff5803b2cb8ab4d426ef569b2c41ddca859f253 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 25 Oct 2019 08:42:21 +0000 Subject: [PATCH 270/393] [Jenkins release job] changelog.txt updated by release build 6.1.0.Final --- changelog.txt | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/changelog.txt b/changelog.txt index 516e64432f..442ca8bf83 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,32 @@ Hibernate Validator Changelog ============================= +6.1.0.Final (25-10-2019) +------------------------- + +** Bug + * HV-1730 - engine - JavaBeanExecutable fails to initialize for enum type + * HV-1715 - engine - Validation can sometimes proceed to the next group in sequence even after one of the constraints generated a violation + +** Improvement + * HV-1729 - performance - Skip allocation of an action for each need to access the context classloader + +** Task + * HV-1743 - build - Upgrade maven-compiler-plugin to 3.8.1 + * HV-1742 - build - Upgrade to WildFly 18.0.0.Final + * HV-1741 - build - Upgrade ByteBuddy test dependency to 1.10.2 + * HV-1740 - engine - Deprecate @SafeHtml + * HV-1739 - engine - CVE-2019-10219 Security issue with @SafeHtml + * HV-1738 - build - Update Jackson test dependency to 2.9.10 + * HV-1733 - tests - Fix locale settings of PredefinedScopeValidatorFactoryTest + * HV-1732 - build - Change tarLongFileMode to posix for assembly building + * HV-1731 - tck-runner - Move TCK signature check to tck-runner module + * HV-1728 - build - Upgrade to WildFly 17.0.1.Final + * HV-1727 - build - Update Jackson Databind test dependency to 2.9.9.2 + * HV-1725 - build - Switch to using Jakarta EE artifacts + * HV-1724 - build - Update to OpenJFX 11.0.2 + * HV-1680 - engine - Avoid reflection by using instrumentation - build the enhancer + 6.1.0.Alpha6 (19-07-2019) ------------------------- From 713964afeb36a3852a5d7a97f7303fa9d56457a4 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 25 Oct 2019 08:42:26 +0000 Subject: [PATCH 271/393] [Jenkins release job] Preparing release 6.1.0.Final --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 6b70540803..0268ca502b 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Final ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 021058c8f5..9bd35cdaaa 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Final ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index 9d4172f7ad..b6f3816ddc 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Final ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index 67809b2d6d..66be577bd4 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Final ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index b2b7dfa964..9288290f95 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Final ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index d5a8abde8f..c1bd260b60 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Final ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 1cc7e971b3..f4cb25af56 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Final ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index fc57501f3a..889c31ea79 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Final 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 47c58cf20c..812ae75546 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Final ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index c767009832..416d3debcd 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Final ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 1b9ec9f304..e5c86e6e0f 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0-SNAPSHOT + 6.1.0.Final ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index fc4f7e3a85..6ae150336c 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Final ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index e5c465157f..0c8c109bd0 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Final ../pom.xml diff --git a/pom.xml b/pom.xml index 20ba8f1094..e9f8fbcfb0 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Final pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 3f99228d35..f644d1b57d 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Final org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index acc9a54560..42d5fd83f5 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Final org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index d793ee6b6e..97eef3e08b 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Final org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index c2eba20d47..6c0cfdb01d 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0-SNAPSHOT + 6.1.0.Final org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 6516654b3f..c4809bfa57 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Final hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index d139d3ab71..3cf0080231 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Final ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index efc534b51b..412b792a82 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0-SNAPSHOT + 6.1.0.Final hibernate-validator-test-utils From cdb6ba975e23a9ade5d2841fea21dd34f47dc371 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 25 Oct 2019 08:45:26 +0000 Subject: [PATCH 272/393] [Jenkins release job] Preparing next development iteration --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 0268ca502b..bc53a92a6d 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Final + 6.1.1-SNAPSHOT ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 9bd35cdaaa..a84f213f07 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Final + 6.1.1-SNAPSHOT ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index b6f3816ddc..db2f0c498a 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Final + 6.1.1-SNAPSHOT ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index 66be577bd4..283808852a 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Final + 6.1.1-SNAPSHOT ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 9288290f95..4d2e61af5b 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Final + 6.1.1-SNAPSHOT ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index c1bd260b60..9bd8de005c 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Final + 6.1.1-SNAPSHOT ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index f4cb25af56..74dec81c99 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Final + 6.1.1-SNAPSHOT ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index 889c31ea79..b7a5093fd8 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Final + 6.1.1-SNAPSHOT 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 812ae75546..87b8b34cca 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Final + 6.1.1-SNAPSHOT ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 416d3debcd..888b34bc8d 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Final + 6.1.1-SNAPSHOT ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index e5c86e6e0f..38f0eb0529 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.0.Final + 6.1.1-SNAPSHOT ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index 6ae150336c..14fb8b0246 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Final + 6.1.1-SNAPSHOT ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index 0c8c109bd0..f862e203fc 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Final + 6.1.1-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index e9f8fbcfb0..ac127bb5e8 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Final + 6.1.1-SNAPSHOT pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index f644d1b57d..5e34d4d0bb 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Final + 6.1.1-SNAPSHOT org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index 42d5fd83f5..8f0f893f60 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Final + 6.1.1-SNAPSHOT org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index 97eef3e08b..3af71ba584 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Final + 6.1.1-SNAPSHOT org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index 6c0cfdb01d..dda823ffb3 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.0.Final + 6.1.1-SNAPSHOT org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index c4809bfa57..59c0224b5d 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Final + 6.1.1-SNAPSHOT hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 3cf0080231..53d079d516 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Final + 6.1.1-SNAPSHOT ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 412b792a82..e86476ec26 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.0.Final + 6.1.1-SNAPSHOT hibernate-validator-test-utils From ffddde54de83e06a80a0ef94a7535aeac1d086c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Thu, 31 Oct 2019 16:32:44 +0100 Subject: [PATCH 273/393] HV-1744 Upgrade to Hibernate Asciidoctor theme 1.0.3.Final --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ac127bb5e8..8150626602 100644 --- a/pom.xml +++ b/pom.xml @@ -194,7 +194,7 @@ 1.5.6 - 1.0.2.Final + 1.0.3.Final 1.0.3.Final 9.1.15.0 1.6.0-alpha.5 From e799ff9695bf0b430a75060fda69537581c3b92c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Thu, 31 Oct 2019 12:45:46 +0100 Subject: [PATCH 274/393] HV-1744 Make the TOC auto-expand in the HTML documentation using tocbot https://github.com/junit-team/junit5/commit/fa7c2b197378c83797edca0e45fdc342b5a4cd51 https://github.com/asciidoctor/asciidoctor/issues/699#issuecomment-321066006 --- documentation/pom.xml | 15 +++++++++++++++ documentation/src/main/asciidoc/index.asciidoc | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/documentation/pom.xml b/documentation/pom.xml index 4d2e61af5b..80da806fba 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -203,6 +203,21 @@ ${asciidoctor.base-output-dir}/html_single/css/ + + copy-script-to-html-output + generate-resources + + copy-resources + + + + + ${asciidoctor.aggregated-resources-dir}/script/ + + + ${asciidoctor.base-output-dir}/html_single/script/ + + copy-images-to-html-output generate-resources diff --git a/documentation/src/main/asciidoc/index.asciidoc b/documentation/src/main/asciidoc/index.asciidoc index 369db481d9..9018c1434a 100644 --- a/documentation/src/main/asciidoc/index.asciidoc +++ b/documentation/src/main/asciidoc/index.asciidoc @@ -6,10 +6,10 @@ Hardy Ferentschik; Gunnar Morling; Guillaume Smet :xrefstyle: full :anchor: :toc: left -:toclevels: 3 +:toclevels: 4 :sectnumlevels: 5 :docinfodir: {docinfodir} -:docinfo: +:docinfo: shared,private :title-logo-image: image:hibernate_logo_a.png[align=left,pdfwidth=33%] include::pr01.asciidoc[] From 615828b4a2b149a31c6882a2a7cae4663492d41f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2019 09:57:35 +0000 Subject: [PATCH 275/393] HV-1745 Bump jackson-databind from 2.9.10 to 2.9.10.1 Bumps [jackson-databind](https://github.com/FasterXML/jackson) from 2.9.10 to 2.9.10.1. - [Release notes](https://github.com/FasterXML/jackson/releases) - [Commits](https://github.com/FasterXML/jackson/commits) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8150626602..d00e7e06ce 100644 --- a/pom.xml +++ b/pom.xml @@ -172,7 +172,7 @@ 27.1-jre 4.3.10.RELEASE 1.0.0.Final - 2.9.10 + 2.9.10.1 2.9.10 1.10.2 From c1b39a6a5de3d5185e2a68c2d14f543ca49d3ead Mon Sep 17 00:00:00 2001 From: Felipe Moraes Date: Fri, 27 Dec 2019 10:34:32 +0100 Subject: [PATCH 276/393] Fix Typo in @CNPJ and @CPF annotations doc. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Jurídica and Física was misspelled. --- documentation/src/main/asciidoc/ch02.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/src/main/asciidoc/ch02.asciidoc b/documentation/src/main/asciidoc/ch02.asciidoc index db1f7773f4..391d464e48 100644 --- a/documentation/src/main/asciidoc/ch02.asciidoc +++ b/documentation/src/main/asciidoc/ch02.asciidoc @@ -739,12 +739,12 @@ If you have to implement a country specific constraint, consider making it a con Hibernate Validator! ==== -`@CNPJ`:: Checks that the annotated character sequence represents a Brazilian corporate tax payer registry number (Cadastro de Pessoa Juríeddica) +`@CNPJ`:: Checks that the annotated character sequence represents a Brazilian corporate tax payer registry number (Cadastro de Pessoa Jurídica) Supported data types::: `CharSequence` Hibernate metadata impact::: None Country::: Brazil -`@CPF`:: Checks that the annotated character sequence represents a Brazilian individual taxpayer registry number (Cadastro de Pessoa Fídsica) +`@CPF`:: Checks that the annotated character sequence represents a Brazilian individual taxpayer registry number (Cadastro de Pessoa Física) Supported data types::: `CharSequence` Hibernate metadata impact::: None Country::: Brazil From 2743eb819c17e6b6af3b57d1df09f1f6038f3a75 Mon Sep 17 00:00:00 2001 From: Kai33 Date: Tue, 7 Jan 2020 10:28:27 +0800 Subject: [PATCH 277/393] HV-1750 Add debug message when expression factory has failed to load --- .../messageinterpolation/ResourceBundleMessageInterpolator.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java index d69c88eb2f..7a805f6f5d 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java @@ -170,6 +170,8 @@ private static boolean canLoadExpressionFactory() { return true; } catch (Throwable e) { + LOG.debugv( e, "Failed to load expression factory via classloader {0}", + Thread.currentThread().getContextClassLoader() ); return false; } } From e98de84536e5b14bfec6cd2deac1bbb4d4bdc6d9 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 14 Jan 2020 13:46:21 +0100 Subject: [PATCH 278/393] HV-1750 Use a privileged action to get the context class loader --- .../messageinterpolation/ResourceBundleMessageInterpolator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java index 7a805f6f5d..e015fa2581 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java @@ -171,7 +171,7 @@ private static boolean canLoadExpressionFactory() { } catch (Throwable e) { LOG.debugv( e, "Failed to load expression factory via classloader {0}", - Thread.currentThread().getContextClassLoader() ); + run( GetClassLoader.fromContext() ) ); return false; } } From 1b17b69f95f6df75a436988ddadcfc95b6536c60 Mon Sep 17 00:00:00 2001 From: Irena Kezic Date: Mon, 16 Dec 2019 15:15:22 +0100 Subject: [PATCH 279/393] HV-1747 Allow overriding the message interpolator in PredefinedScopeValidatorFactory context --- .../internal/engine/PredefinedScopeValidatorContextImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorContextImpl.java index 6951658a47..9c84651d9e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorContextImpl.java @@ -34,7 +34,8 @@ public PredefinedScopeValidatorContextImpl(PredefinedScopeValidatorFactoryImpl v @Override public HibernateValidatorContext messageInterpolator(MessageInterpolator messageInterpolator) { - throw new IllegalStateException( "Defining a Validator-specific message interpolator is not supported by the predefined scope ValidatorFactory." ); + validatorFactoryScopedContextBuilder.setMessageInterpolator( messageInterpolator ); + return this; } @Override From a9c46f485b8825858d7e2b0846f9394670cde4ba Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 20 Dec 2019 12:12:48 +0100 Subject: [PATCH 280/393] HV-1748 Improve localization support - Make the default locale configurable - Always initialize the default locale for the predefined scope VF --- engine/pom.xml | 1 + .../BaseHibernateValidatorConfiguration.java | 11 +++ .../engine/AbstractConfigurationImpl.java | 33 +++++--- .../PredefinedScopeConfigurationImpl.java | 28 ++++++- .../AbstractMessageInterpolator.java | 59 ++++++++------ .../ParameterMessageInterpolator.java | 11 ++- .../ResourceBundleMessageInterpolator.java | 63 +++++++++++---- ...DefaultLocaleMessageInterpolationTest.java | 76 +++++++++++++++++++ .../PredefinedScopeValidatorFactoryTest.java | 26 ++++++- 9 files changed, 252 insertions(+), 56 deletions(-) create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/DefaultLocaleMessageInterpolationTest.java diff --git a/engine/pom.xml b/engine/pom.xml index 9bd8de005c..b20f6c015b 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -22,6 +22,7 @@ .. + -Duser.language=en diff --git a/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java index b3347414aa..7ed303aca3 100644 --- a/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java @@ -7,6 +7,7 @@ package org.hibernate.validator; import java.time.Duration; +import java.util.Locale; import java.util.Set; import javax.validation.Configuration; @@ -360,4 +361,14 @@ public interface BaseHibernateValidatorConfiguration + * If not set, defaults to the system locale obtained via {@link Locale#getDefault()}. + * + * @since 6.1.1 + */ + @Incubating + S defaultLocale(Locale defaultLocale); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java index 9c1e28bde6..bcee4bbe09 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java @@ -113,8 +113,8 @@ public abstract class AbstractConfigurationImpl localesToInitialize = Collections.emptySet(); + // the default locale + private Locale defaultLocale = Locale.getDefault(); protected AbstractConfigurationImpl(BootstrapState state) { this(); @@ -325,6 +325,14 @@ public T getterPropertySelectionStrategy(GetterPropertySelectionStrategy getterP return thisAsT(); } + @Override + public T defaultLocale(Locale defaultLocale) { + Contracts.assertNotNull( defaultLocale, MESSAGES.parameterMustNotBeNull( "defaultLocale" ) ); + + this.defaultLocale = defaultLocale; + return thisAsT(); + } + public boolean isAllowParallelMethodsDefineParameterConstraints() { return this.methodValidationConfigurationBuilder.isAllowParallelMethodsDefineParameterConstraints(); } @@ -518,7 +526,8 @@ public ClassLoader getExternalClassLoader() { @Override public final MessageInterpolator getDefaultMessageInterpolator() { if ( defaultMessageInterpolator == null ) { - defaultMessageInterpolator = new ResourceBundleMessageInterpolator( getDefaultResourceBundleLocator(), localesToInitialize ); + defaultMessageInterpolator = new ResourceBundleMessageInterpolator( getDefaultResourceBundleLocator(), getAllLocalesToInitialize(), + defaultLocale ); } return defaultMessageInterpolator; @@ -538,7 +547,7 @@ public final ConstraintValidatorFactory getDefaultConstraintValidatorFactory() { public final ResourceBundleLocator getDefaultResourceBundleLocator() { if ( defaultResourceBundleLocator == null ) { defaultResourceBundleLocator = new PlatformResourceBundleLocator( - ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, localesToInitialize ); + ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, getAllLocalesToInitialize() ); } return defaultResourceBundleLocator; @@ -688,12 +697,12 @@ private MessageInterpolator getDefaultMessageInterpolatorConfiguredWithClassLoad if ( externalClassLoader != null ) { PlatformResourceBundleLocator userResourceBundleLocator = new PlatformResourceBundleLocator( ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, - localesToInitialize, + getAllLocalesToInitialize(), externalClassLoader ); PlatformResourceBundleLocator contributorResourceBundleLocator = new PlatformResourceBundleLocator( ResourceBundleMessageInterpolator.CONTRIBUTOR_VALIDATION_MESSAGES, - localesToInitialize, + getAllLocalesToInitialize(), externalClassLoader, true ); @@ -707,7 +716,8 @@ private MessageInterpolator getDefaultMessageInterpolatorConfiguredWithClassLoad return new ResourceBundleMessageInterpolator( userResourceBundleLocator, contributorResourceBundleLocator, - localesToInitialize + getAllLocalesToInitialize(), + defaultLocale ); } finally { @@ -719,8 +729,13 @@ private MessageInterpolator getDefaultMessageInterpolatorConfiguredWithClassLoad } } - protected void setLocalesToInitialize(Set localesToInitialize) { - this.localesToInitialize = localesToInitialize; + protected final Locale getDefaultLocale() { + return defaultLocale; + } + + protected Set getAllLocalesToInitialize() { + // By default, we return an empty set meaning that we will dynamically initialize the locales. + return Collections.emptySet(); } @SuppressWarnings("unchecked") diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java index 8d8b53a986..03585920d8 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java @@ -6,6 +6,9 @@ */ package org.hibernate.validator.internal.engine; +import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES; + +import java.util.Collections; import java.util.Locale; import java.util.Set; @@ -15,6 +18,7 @@ import org.hibernate.validator.PredefinedScopeHibernateValidatorConfiguration; import org.hibernate.validator.internal.util.CollectionHelper; +import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; /** @@ -27,6 +31,13 @@ public class PredefinedScopeConfigurationImpl extends AbstractConfigurationImpl< private BeanMetaDataClassNormalizer beanMetaDataClassNormalizer; + /** + * Locales to initialize eagerly. + *

    + * We will always include the default locale in the final list. + */ + private Set localesToInitialize = Collections.emptySet(); + public PredefinedScopeConfigurationImpl(BootstrapState state) { super( state ); } @@ -46,8 +57,9 @@ public Set> getBeanClassesToInitialize() { } @Override - public PredefinedScopeHibernateValidatorConfiguration initializeLocales(Set locales) { - setLocalesToInitialize( CollectionHelper.toImmutableSet( locales ) ); + public PredefinedScopeHibernateValidatorConfiguration initializeLocales(Set localesToInitialize) { + Contracts.assertNotNull( localesToInitialize, MESSAGES.parameterMustNotBeNull( "localesToInitialize" ) ); + this.localesToInitialize = localesToInitialize; return thisAsT(); } @@ -60,4 +72,16 @@ public PredefinedScopeHibernateValidatorConfiguration beanMetaDataClassNormalize public BeanMetaDataClassNormalizer getBeanMetaDataClassNormalizer() { return beanMetaDataClassNormalizer; } + + @Override + protected Set getAllLocalesToInitialize() { + if ( localesToInitialize.isEmpty() ) { + return Collections.singleton( getDefaultLocale() ); + } + + Set allLocales = CollectionHelper.newHashSet( localesToInitialize.size() + 1 ); + allLocales.addAll( localesToInitialize ); + allLocales.add( getDefaultLocale() ); + return Collections.unmodifiableSet( allLocales ); + } } diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java index 39aa6a0f71..69b1029368 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java @@ -7,6 +7,7 @@ package org.hibernate.validator.messageinterpolation; import static org.hibernate.validator.internal.util.ConcurrentReferenceHashMap.ReferenceType.SOFT; +import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES; import java.lang.invoke.MethodHandles; import java.util.Collections; @@ -20,8 +21,8 @@ import java.util.regex.Pattern; import javax.validation.MessageInterpolator; -import javax.validation.ValidationException; +import org.hibernate.validator.Incubating; import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTermType; import org.hibernate.validator.internal.engine.messageinterpolation.LocalizedMessage; import org.hibernate.validator.internal.engine.messageinterpolation.parser.MessageDescriptorFormatException; @@ -29,6 +30,7 @@ import org.hibernate.validator.internal.engine.messageinterpolation.parser.TokenCollector; import org.hibernate.validator.internal.engine.messageinterpolation.parser.TokenIterator; import org.hibernate.validator.internal.util.ConcurrentReferenceHashMap; +import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.resourceloading.PlatformResourceBundleLocator; @@ -131,7 +133,7 @@ public abstract class AbstractMessageInterpolator implements MessageInterpolator * {@code MessageInterpolator} using the default resource bundle locators. */ public AbstractMessageInterpolator() { - this( Collections.emptySet() ); + this( Collections.emptySet(), Locale.getDefault() ); } /** @@ -140,7 +142,7 @@ public AbstractMessageInterpolator() { * @param userResourceBundleLocator {@code ResourceBundleLocator} used to load user provided resource bundle */ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator) { - this( userResourceBundleLocator, Collections.emptySet() ); + this( userResourceBundleLocator, Collections.emptySet(), Locale.getDefault() ); } /** @@ -152,7 +154,7 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat */ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator) { - this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet() ); + this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault() ); } /** @@ -166,30 +168,34 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator, boolean cacheMessages) { - this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), cacheMessages ); + this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), cacheMessages ); } /** * {@code MessageInterpolator} using the default resource bundle locators. * - * @param localesToInitialize The set of locales to initialize at bootstrap. + * @param localesToInitialize the set of locales to initialize at bootstrap + * @param defaultLocale the default locale * - * @since 6.1 + * @since 6.1.1 */ - public AbstractMessageInterpolator(Set localesToInitialize) { - this( null, localesToInitialize ); + @Incubating + public AbstractMessageInterpolator(Set localesToInitialize, Locale defaultLocale) { + this( null, localesToInitialize, defaultLocale ); } /** * {@code MessageInterpolator} taking a resource bundle locator. * * @param userResourceBundleLocator {@code ResourceBundleLocator} used to load user provided resource bundle - * @param localesToInitialize The set of locales to initialize at bootstrap. + * @param localesToInitialize the set of locales to initialize at bootstrap + * @param defaultLocale the default locale * - * @since 6.1 + * @since 6.1.1 */ - public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, Set localesToInitialize) { - this( userResourceBundleLocator, null, localesToInitialize ); + @Incubating + public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, Set localesToInitialize, Locale defaultLocale) { + this( userResourceBundleLocator, null, localesToInitialize, defaultLocale ); } /** @@ -197,13 +203,16 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat * * @param userResourceBundleLocator {@code ResourceBundleLocator} used to load user provided resource bundle * @param contributorResourceBundleLocator {@code ResourceBundleLocator} used to load resource bundle of constraint contributor - * @param localesToInitialize The set of locales to initialize at bootstrap. + * @param localesToInitialize the set of locales to initialize at bootstrap + * @param defaultLocale the default locale * - * @since 6.1 + * @since 6.1.1 */ + @Incubating public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, - ResourceBundleLocator contributorResourceBundleLocator, Set localesToInitialize) { - this( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize, true ); + ResourceBundleLocator contributorResourceBundleLocator, Set localesToInitialize, + Locale defaultLocale) { + this( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize, defaultLocale, true ); } /** @@ -211,16 +220,22 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat * * @param userResourceBundleLocator {@code ResourceBundleLocator} used to load user provided resource bundle * @param contributorResourceBundleLocator {@code ResourceBundleLocator} used to load resource bundle of constraint contributor - * @param localesToInitialize The set of locales to initialize at bootstrap. - * @param cacheMessages Whether resolved messages should be cached or not. + * @param localesToInitialize the set of locales to initialize at bootstrap + * @param defaultLocale the default locale + * @param cacheMessages whether resolved messages should be cached or not * - * @since 6.1 + * @since 6.1.1 */ + @Incubating public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator, Set localesToInitialize, + Locale defaultLocale, boolean cacheMessages) { - defaultLocale = Locale.getDefault(); + Contracts.assertNotNull( localesToInitialize, MESSAGES.parameterMustNotBeNull( "localesToInitialize" ) ); + Contracts.assertNotNull( defaultLocale, MESSAGES.parameterMustNotBeNull( "defaultLocale" ) ); + + this.defaultLocale = defaultLocale; if ( userResourceBundleLocator == null ) { this.userResourceBundleLocator = new PlatformResourceBundleLocator( USER_VALIDATION_MESSAGES, localesToInitialize ); @@ -297,7 +312,7 @@ public String interpolate(String message, Context context, Locale locale) { try { interpolatedMessage = interpolateMessage( message, context, locale ); } - catch (ValidationException e) { + catch (MessageDescriptorFormatException e) { LOG.warn( e.getMessage() ); } return interpolatedMessage; diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java index ba260bab17..1b9497e1a7 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java @@ -11,6 +11,7 @@ import java.util.Locale; import java.util.Set; +import org.hibernate.validator.Incubating; import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTerm; import org.hibernate.validator.internal.engine.messageinterpolation.ParameterTermResolver; import org.hibernate.validator.internal.util.logging.Log; @@ -28,11 +29,15 @@ public class ParameterMessageInterpolator extends AbstractMessageInterpolator { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); public ParameterMessageInterpolator() { - this( Collections.emptySet() ); + this( Collections.emptySet(), Locale.getDefault() ); } - public ParameterMessageInterpolator(Set localesToInitialize) { - super( localesToInitialize ); + /** + * @since 6.1.1 + */ + @Incubating + public ParameterMessageInterpolator(Set localesToInitialize, Locale defaultLocale) { + super( localesToInitialize, defaultLocale ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java index e015fa2581..1b97418c3c 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java @@ -16,6 +16,7 @@ import javax.el.ELManager; import javax.el.ExpressionFactory; +import org.hibernate.validator.Incubating; import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTerm; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; @@ -40,69 +41,99 @@ public class ResourceBundleMessageInterpolator extends AbstractMessageInterpolat private final ExpressionFactory expressionFactory; public ResourceBundleMessageInterpolator() { - this( Collections.emptySet() ); + this( Collections.emptySet(), Locale.getDefault() ); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator) { - this( userResourceBundleLocator, Collections.emptySet() ); + this( userResourceBundleLocator, Collections.emptySet(), Locale.getDefault() ); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator) { - this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet() ); + this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault() ); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator, boolean cachingEnabled) { - this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), cachingEnabled ); + this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), cachingEnabled ); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, boolean cachingEnabled) { - this( userResourceBundleLocator, null, Collections.emptySet(), cachingEnabled ); + this( userResourceBundleLocator, null, Collections.emptySet(), Locale.getDefault(), cachingEnabled ); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, boolean cachingEnabled, ExpressionFactory expressionFactory) { - this( userResourceBundleLocator, null, Collections.emptySet(), cachingEnabled ); + this( userResourceBundleLocator, null, Collections.emptySet(), Locale.getDefault(), cachingEnabled ); } - public ResourceBundleMessageInterpolator(Set localesToInitialize) { - super( localesToInitialize ); + /** + * @since 6.1.1 + */ + @Incubating + public ResourceBundleMessageInterpolator(Set localesToInitialize, Locale defaultLocale) { + super( localesToInitialize, defaultLocale ); this.expressionFactory = buildExpressionFactory(); } - public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, Set localesToInitialize) { - super( userResourceBundleLocator, localesToInitialize ); + /** + * @since 6.1.1 + */ + @Incubating + public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, Set localesToInitialize, Locale defaultLocale) { + super( userResourceBundleLocator, localesToInitialize, defaultLocale ); this.expressionFactory = buildExpressionFactory(); } + /** + * @since 6.1.1 + */ + @Incubating public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator, - Set localesToInitialize) { - super( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize ); + Set localesToInitialize, + Locale defaultLocale) { + super( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize, defaultLocale ); this.expressionFactory = buildExpressionFactory(); } + /** + * @since 6.1.1 + */ + @Incubating public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator, Set localesToInitialize, + Locale defaultLocale, boolean cachingEnabled) { - super( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize, cachingEnabled ); + super( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize, defaultLocale, cachingEnabled ); this.expressionFactory = buildExpressionFactory(); } - public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, Set localesToInitialize, boolean cachingEnabled) { - super( userResourceBundleLocator, null, localesToInitialize, cachingEnabled ); + /** + * @since 6.1.1 + */ + @Incubating + public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, + Set localesToInitialize, + Locale defaultLocale, + boolean cachingEnabled) { + super( userResourceBundleLocator, null, localesToInitialize, defaultLocale, cachingEnabled ); this.expressionFactory = buildExpressionFactory(); } + /** + * @since 6.1.1 + */ + @Incubating public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, Set localesToInitialize, + Locale defaultLocale, boolean cachingEnabled, ExpressionFactory expressionFactory) { - super( userResourceBundleLocator, null, localesToInitialize, cachingEnabled ); + super( userResourceBundleLocator, null, localesToInitialize, defaultLocale, cachingEnabled ); this.expressionFactory = expressionFactory; } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/DefaultLocaleMessageInterpolationTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/DefaultLocaleMessageInterpolationTest.java new file mode 100644 index 0000000000..b72dc9236d --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/DefaultLocaleMessageInterpolationTest.java @@ -0,0 +1,76 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.engine.messageinterpolation; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Locale; + +import javax.validation.MessageInterpolator; +import javax.validation.Validation; +import javax.validation.ValidatorFactory; +import javax.validation.metadata.ConstraintDescriptor; + +import org.hibernate.validator.HibernateValidator; +import org.testng.annotations.Test; + +public class DefaultLocaleMessageInterpolationTest { + + @Test + public void testNoDefaultLocaleDefinedStillWorking() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .buildValidatorFactory(); + + MessageInterpolator messageInterpolator = validatorFactory.getMessageInterpolator(); + + assertThat( messageInterpolator.interpolate( "{javax.validation.constraints.AssertFalse.message}", new TestContext() ) ) + .isEqualTo( "must be false" ); + } + + @Test + public void testDefaultLocaleHonored() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .defaultLocale( Locale.FRANCE ) + .buildValidatorFactory(); + + MessageInterpolator messageInterpolator = validatorFactory.getMessageInterpolator(); + + assertThat( messageInterpolator.interpolate( "{javax.validation.constraints.AssertFalse.message}", new TestContext() ) ) + .isEqualTo( "doit avoir la valeur faux" ); + + validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .defaultLocale( Locale.ITALY ) + .buildValidatorFactory(); + + messageInterpolator = validatorFactory.getMessageInterpolator(); + + assertThat( messageInterpolator.interpolate( "{javax.validation.constraints.AssertFalse.message}", new TestContext() ) ) + .isEqualTo( "deve essere false" ); + } + + private static class TestContext implements MessageInterpolator.Context { + + @Override + public ConstraintDescriptor getConstraintDescriptor() { + return null; + } + + @Override + public Object getValidatedValue() { + return null; + } + + @SuppressWarnings("unchecked") + @Override + public T unwrap(Class type) { + return (T) this; + } + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java index 6133fab5e9..588e187f8d 100644 --- a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java @@ -22,6 +22,7 @@ import java.util.Set; import javax.validation.ConstraintViolation; +import javax.validation.MessageInterpolator; import javax.validation.Path; import javax.validation.Path.Node; import javax.validation.TraversableResolver; @@ -189,7 +190,22 @@ public void testUninitializedLocale() { try { Locale.setDefault( Locale.FRANCE ); - Validator validator = getValidatorWithInitializedLocale( Locale.ENGLISH ); + ValidatorFactory validatorFactory = getValidatorFactoryWithInitializedLocale( Locale.ENGLISH ); + + Validator validator = validatorFactory + .usingContext() + .messageInterpolator( new MessageInterpolator() { + + @Override + public String interpolate(String messageTemplate, Context context, Locale locale) { + return validatorFactory.getMessageInterpolator().interpolate( messageTemplate, context, locale ); + } + + @Override + public String interpolate(String messageTemplate, Context context) { + return validatorFactory.getMessageInterpolator().interpolate( messageTemplate, context, Locale.GERMAN ); + } + } ).getValidator(); Set> violations = validator.validate( new Bean( "", "invalid" ) ); assertThat( violations ).containsOnlyViolations( @@ -294,17 +310,19 @@ private static Validator getValidator() { return validatorFactory.getValidator(); } - private static Validator getValidatorWithInitializedLocale(Locale locale) { + private static ValidatorFactory getValidatorFactoryWithInitializedLocale(Locale locale) { Set> beanMetaDataToInitialize = new HashSet<>(); beanMetaDataToInitialize.add( Bean.class ); - ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) + return Validation.byProvider( PredefinedScopeHibernateValidator.class ) .configure() .initializeBeanMetaData( beanMetaDataToInitialize ) .initializeLocales( Collections.singleton( locale ) ) .buildValidatorFactory(); + } - return validatorFactory.getValidator(); + private static Validator getValidatorWithInitializedLocale(Locale locale) { + return getValidatorFactoryWithInitializedLocale( locale ).getValidator(); } private enum SomeEnum { From 2312530bb3473c7c5d84b7c582c79d97e8c8c0ab Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 20 Dec 2019 15:28:29 +0100 Subject: [PATCH 281/393] HV-1747 Add test --- .../PredefinedScopeValidatorFactoryTest.java | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java index 588e187f8d..7ad9e400c0 100644 --- a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java @@ -297,17 +297,45 @@ public void variousObjectTypes() { validator.validate( new Bean() ); } - private static Validator getValidator() { + @Test + public void customizingMessageInterpolator() { + ValidatorFactory validatorFactory = getValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + Set> violations = validator.validate( new Bean( null, null ) ); + assertThat( violations ).containsOnlyViolations( violationOf( NotNull.class ).withMessage( "must not be null" ) ); + + validator = validatorFactory.usingContext() + .messageInterpolator( new MessageInterpolator() { + + @Override + public String interpolate(String messageTemplate, Context context, Locale locale) { + return "another string"; + } + + @Override + public String interpolate(String messageTemplate, Context context) { + return "another string"; + } + } ).getValidator(); + + violations = validator.validate( new Bean( null, null ) ); + assertThat( violations ).containsOnlyViolations( violationOf( NotNull.class ).withMessage( "another string" ) ); + } + + private static ValidatorFactory getValidatorFactory() { Set> beanMetaDataToInitialize = new HashSet<>(); beanMetaDataToInitialize.add( Bean.class ); beanMetaDataToInitialize.add( AnotherBean.class ); - ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) + return Validation.byProvider( PredefinedScopeHibernateValidator.class ) .configure() .initializeBeanMetaData( beanMetaDataToInitialize ) .buildValidatorFactory(); + } - return validatorFactory.getValidator(); + private static Validator getValidator() { + return getValidatorFactory().getValidator(); } private static ValidatorFactory getValidatorFactoryWithInitializedLocale(Locale locale) { From 2c43b799e5493845e21fa8a028afda168a7c451b Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 24 Dec 2019 12:38:16 +0100 Subject: [PATCH 282/393] HV-1749 Introduce a LocaleResolver contract --- .../BaseHibernateValidatorConfiguration.java | 22 +++ .../engine/AbstractConfigurationImpl.java | 26 +++- .../PredefinedScopeValidatorFactoryImpl.java | 2 +- .../ValidatorFactoryConfigurationHelper.java | 28 ++++ .../DefaultLocaleResolver.java | 20 +++ .../DefaultLocaleResolverContext.java | 34 +++++ .../validator/internal/util/logging/Log.java | 8 ++ .../AbstractMessageInterpolator.java | 52 +++++-- .../ParameterMessageInterpolator.java | 15 +- .../ResourceBundleMessageInterpolator.java | 40 ++++-- .../messageinterpolation/LocaleResolver.java | 31 ++++ .../LocaleResolverContext.java | 26 ++++ .../LocaleResolverTest.java | 100 +++++++++++++ .../predefinedscope/LocaleResolverTest.java | 136 ++++++++++++++++++ .../locale-resolver-validation.xml | 16 +++ 15 files changed, 519 insertions(+), 37 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/DefaultLocaleResolver.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/DefaultLocaleResolverContext.java create mode 100644 engine/src/main/java/org/hibernate/validator/spi/messageinterpolation/LocaleResolver.java create mode 100644 engine/src/main/java/org/hibernate/validator/spi/messageinterpolation/LocaleResolverContext.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/LocaleResolverTest.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/predefinedscope/LocaleResolverTest.java create mode 100644 engine/src/test/resources/org/hibernate/validator/test/internal/engine/messageinterpolation/locale-resolver-validation.xml diff --git a/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java index 7ed303aca3..f1154f797e 100644 --- a/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java @@ -22,6 +22,7 @@ import org.hibernate.validator.cfg.ConstraintMapping; import org.hibernate.validator.constraints.ParameterScriptAssert; import org.hibernate.validator.constraints.ScriptAssert; +import org.hibernate.validator.spi.messageinterpolation.LocaleResolver; import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider; import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; @@ -131,6 +132,15 @@ public interface BaseHibernateValidatorConfiguration * Returns the {@link ResourceBundleLocator} used by the @@ -371,4 +381,16 @@ public interface BaseHibernateValidatorConfiguration extractor) { Contracts.assertNotNull( extractor, MESSAGES.parameterMustNotBeNull( "extractor" ) ); @@ -489,6 +502,10 @@ public PropertyNodeNameProvider getPropertyNodeNameProvider() { return validationBootstrapParameters.getPropertyNodeNameProvider(); } + public LocaleResolver getLocaleResolver() { + return localeResolver; + } + public ScriptEvaluatorFactory getScriptEvaluatorFactory() { return scriptEvaluatorFactory; } @@ -527,7 +544,7 @@ public ClassLoader getExternalClassLoader() { public final MessageInterpolator getDefaultMessageInterpolator() { if ( defaultMessageInterpolator == null ) { defaultMessageInterpolator = new ResourceBundleMessageInterpolator( getDefaultResourceBundleLocator(), getAllLocalesToInitialize(), - defaultLocale ); + defaultLocale, ValidatorFactoryConfigurationHelper.determineLocaleResolver( this, this.getProperties(), externalClassLoader ) ); } return defaultMessageInterpolator; @@ -717,7 +734,8 @@ private MessageInterpolator getDefaultMessageInterpolatorConfiguredWithClassLoad userResourceBundleLocator, contributorResourceBundleLocator, getAllLocalesToInitialize(), - defaultLocale + defaultLocale, + ValidatorFactoryConfigurationHelper.determineLocaleResolver( this, this.getProperties(), externalClassLoader ) ); } finally { diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java index 03cbdb8962..8785843e17 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java @@ -9,6 +9,7 @@ import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowMultipleCascadedValidationOnReturnValues; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowOverridingMethodAlterParameterConstraint; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowParallelMethodsDefineParameterConstraints; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineBeanMetaDataClassNormalizer; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineConstraintMappings; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineConstraintValidatorPayload; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineExternalClassLoader; @@ -18,7 +19,6 @@ import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineTraversableResolverResultCacheEnabled; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.logValidatorFactoryScopedConfiguration; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.registerCustomConstraintValidators; -import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineBeanMetaDataClassNormalizer; import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; import java.lang.invoke.MethodHandles; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java index 635d6a61bb..aa90ad5e1e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java @@ -25,6 +25,7 @@ import org.hibernate.validator.cfg.ConstraintMapping; import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping; import org.hibernate.validator.internal.engine.constraintdefinition.ConstraintDefinitionContribution; +import org.hibernate.validator.internal.engine.messageinterpolation.DefaultLocaleResolver; import org.hibernate.validator.internal.engine.scripting.DefaultScriptEvaluatorFactory; import org.hibernate.validator.internal.metadata.DefaultBeanMetaDataClassNormalizer; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; @@ -39,6 +40,7 @@ import org.hibernate.validator.internal.util.privilegedactions.NewInstance; import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; import org.hibernate.validator.spi.cfg.ConstraintMappingContributor; +import org.hibernate.validator.spi.messageinterpolation.LocaleResolver; import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider; import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; @@ -318,6 +320,32 @@ static PropertyNodeNameProvider determinePropertyNodeNameProvider(AbstractConfig return new DefaultPropertyNodeNameProvider(); } + static LocaleResolver determineLocaleResolver(AbstractConfigurationImpl hibernateSpecificConfig, Map properties, + ClassLoader externalClassLoader) { + if ( hibernateSpecificConfig.getLocaleResolver() != null ) { + LOG.usingLocaleResolver( hibernateSpecificConfig.getLocaleResolver().getClass() ); + + return hibernateSpecificConfig.getLocaleResolver(); + } + + String localeResolverFqcn = properties.get( HibernateValidatorConfiguration.LOCALE_RESOLVER_CLASSNAME ); + if ( localeResolverFqcn != null ) { + try { + @SuppressWarnings("unchecked") + Class clazz = (Class) run( LoadClass.action( localeResolverFqcn, externalClassLoader ) ); + LocaleResolver localeResolver = run( NewInstance.action( clazz, "locale resolver class" ) ); + LOG.usingLocaleResolver( clazz ); + + return localeResolver; + } + catch (Exception e) { + throw LOG.getUnableToInstantiateLocaleResolverClassException( localeResolverFqcn, e ); + } + } + + return new DefaultLocaleResolver(); + } + static void registerCustomConstraintValidators(Set constraintMappings, ConstraintHelper constraintHelper) { Set> definedConstraints = newHashSet(); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/DefaultLocaleResolver.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/DefaultLocaleResolver.java new file mode 100644 index 0000000000..d4d1e6462a --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/DefaultLocaleResolver.java @@ -0,0 +1,20 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.messageinterpolation; + +import java.util.Locale; + +import org.hibernate.validator.spi.messageinterpolation.LocaleResolver; +import org.hibernate.validator.spi.messageinterpolation.LocaleResolverContext; + +public class DefaultLocaleResolver implements LocaleResolver { + + @Override + public Locale resolve(LocaleResolverContext context) { + return context.getDefaultLocale(); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/DefaultLocaleResolverContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/DefaultLocaleResolverContext.java new file mode 100644 index 0000000000..ae88636b6c --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/DefaultLocaleResolverContext.java @@ -0,0 +1,34 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.messageinterpolation; + +import java.util.Locale; +import java.util.Set; + +import org.hibernate.validator.spi.messageinterpolation.LocaleResolverContext; + +public class DefaultLocaleResolverContext implements LocaleResolverContext { + + private final Set supportedLocales; + + private final Locale defaultLocale; + + public DefaultLocaleResolverContext(Set supportedLocales, Locale defaultLocale) { + this.supportedLocales = supportedLocales; + this.defaultLocale = defaultLocale; + } + + @Override + public Set getSupportedLocales() { + return supportedLocales; + } + + @Override + public Locale getDefaultLocale() { + return defaultLocale; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 42ec9d4134..8e3a7ec9ca 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -63,6 +63,7 @@ import org.hibernate.validator.internal.util.logging.formatter.ObjectArrayFormatter; import org.hibernate.validator.internal.util.logging.formatter.TypeFormatter; import org.hibernate.validator.internal.xml.mapping.ContainerElementTypePath; +import org.hibernate.validator.spi.messageinterpolation.LocaleResolver; import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider; import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; import org.hibernate.validator.spi.scripting.ScriptEvaluationException; @@ -900,4 +901,11 @@ ConstraintDefinitionException getConstraintValidatorDefinitionConstraintMismatch + " To solve this, compile your code with the '-parameters' flag." ) void missingParameterMetadataWithSyntheticOrImplicitParameters(@FormatWith(ExecutableFormatter.class) Executable executable); + + @LogMessage(level = DEBUG) + @Message(id = 255, value = "Using %s as locale resolver.") + void usingLocaleResolver(@FormatWith(ClassObjectFormatter.class) Class localeResolverClass); + + @Message(id = 256, value = "Unable to instantiate locale resolver class %s.") + ValidationException getUnableToInstantiateLocaleResolverClassException(String localeResolverClassName, @Cause Exception e); } diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java index 69b1029368..e53d73e7ae 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java @@ -23,6 +23,8 @@ import javax.validation.MessageInterpolator; import org.hibernate.validator.Incubating; +import org.hibernate.validator.internal.engine.messageinterpolation.DefaultLocaleResolver; +import org.hibernate.validator.internal.engine.messageinterpolation.DefaultLocaleResolverContext; import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTermType; import org.hibernate.validator.internal.engine.messageinterpolation.LocalizedMessage; import org.hibernate.validator.internal.engine.messageinterpolation.parser.MessageDescriptorFormatException; @@ -34,6 +36,8 @@ import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.resourceloading.PlatformResourceBundleLocator; +import org.hibernate.validator.spi.messageinterpolation.LocaleResolver; +import org.hibernate.validator.spi.messageinterpolation.LocaleResolverContext; import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; /** @@ -85,9 +89,14 @@ public abstract class AbstractMessageInterpolator implements MessageInterpolator public static final String CONTRIBUTOR_VALIDATION_MESSAGES = "ContributorValidationMessages"; /** - * The default locale in the current JVM. + * The locale resolver. */ - private final Locale defaultLocale; + private final LocaleResolver localeResolver; + + /** + * The execution context of the locale resolver. + */ + private final LocaleResolverContext localeResolverContext; /** * Loads user-specified resource bundles. @@ -133,7 +142,7 @@ public abstract class AbstractMessageInterpolator implements MessageInterpolator * {@code MessageInterpolator} using the default resource bundle locators. */ public AbstractMessageInterpolator() { - this( Collections.emptySet(), Locale.getDefault() ); + this( Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver() ); } /** @@ -142,7 +151,7 @@ public AbstractMessageInterpolator() { * @param userResourceBundleLocator {@code ResourceBundleLocator} used to load user provided resource bundle */ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator) { - this( userResourceBundleLocator, Collections.emptySet(), Locale.getDefault() ); + this( userResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver() ); } /** @@ -154,7 +163,7 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat */ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator) { - this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault() ); + this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver() ); } /** @@ -168,7 +177,8 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator, boolean cacheMessages) { - this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), cacheMessages ); + this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), + cacheMessages ); } /** @@ -176,12 +186,13 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat * * @param localesToInitialize the set of locales to initialize at bootstrap * @param defaultLocale the default locale + * @param localeResolver the locale resolver * * @since 6.1.1 */ @Incubating - public AbstractMessageInterpolator(Set localesToInitialize, Locale defaultLocale) { - this( null, localesToInitialize, defaultLocale ); + public AbstractMessageInterpolator(Set localesToInitialize, Locale defaultLocale, LocaleResolver localeResolver) { + this( null, localesToInitialize, defaultLocale, localeResolver ); } /** @@ -190,12 +201,16 @@ public AbstractMessageInterpolator(Set localesToInitialize, Locale defau * @param userResourceBundleLocator {@code ResourceBundleLocator} used to load user provided resource bundle * @param localesToInitialize the set of locales to initialize at bootstrap * @param defaultLocale the default locale + * @param localeResolver the locale resolver * * @since 6.1.1 */ @Incubating - public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, Set localesToInitialize, Locale defaultLocale) { - this( userResourceBundleLocator, null, localesToInitialize, defaultLocale ); + public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, + Set localesToInitialize, + Locale defaultLocale, + LocaleResolver localeResolver) { + this( userResourceBundleLocator, null, localesToInitialize, defaultLocale, localeResolver ); } /** @@ -205,14 +220,17 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat * @param contributorResourceBundleLocator {@code ResourceBundleLocator} used to load resource bundle of constraint contributor * @param localesToInitialize the set of locales to initialize at bootstrap * @param defaultLocale the default locale + * @param localeResolver the locale resolver * * @since 6.1.1 */ @Incubating public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, - ResourceBundleLocator contributorResourceBundleLocator, Set localesToInitialize, - Locale defaultLocale) { - this( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize, defaultLocale, true ); + ResourceBundleLocator contributorResourceBundleLocator, + Set localesToInitialize, + Locale defaultLocale, + LocaleResolver localeResolver) { + this( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize, defaultLocale, localeResolver, true ); } /** @@ -223,6 +241,7 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat * @param localesToInitialize the set of locales to initialize at bootstrap * @param defaultLocale the default locale * @param cacheMessages whether resolved messages should be cached or not + * @param localeResolver the locale resolver * * @since 6.1.1 */ @@ -231,11 +250,14 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat ResourceBundleLocator contributorResourceBundleLocator, Set localesToInitialize, Locale defaultLocale, + LocaleResolver localeResolver, boolean cacheMessages) { Contracts.assertNotNull( localesToInitialize, MESSAGES.parameterMustNotBeNull( "localesToInitialize" ) ); Contracts.assertNotNull( defaultLocale, MESSAGES.parameterMustNotBeNull( "defaultLocale" ) ); + Contracts.assertNotNull( localeResolver, MESSAGES.parameterMustNotBeNull( "localeResolver" ) ); - this.defaultLocale = defaultLocale; + this.localeResolverContext = new DefaultLocaleResolverContext( localesToInitialize, defaultLocale ); + this.localeResolver = localeResolver; if ( userResourceBundleLocator == null ) { this.userResourceBundleLocator = new PlatformResourceBundleLocator( USER_VALIDATION_MESSAGES, localesToInitialize ); @@ -298,7 +320,7 @@ public String interpolate(String message, Context context) { // is immutable and uniquely built per Validation definition, the comparison has to be based on == and not equals though String interpolatedMessage = message; try { - interpolatedMessage = interpolateMessage( message, context, defaultLocale ); + interpolatedMessage = interpolateMessage( message, context, localeResolver.resolve( localeResolverContext ) ); } catch (MessageDescriptorFormatException e) { LOG.warn( e.getMessage() ); diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java index 1b9497e1a7..759b545d91 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java @@ -12,16 +12,19 @@ import java.util.Set; import org.hibernate.validator.Incubating; +import org.hibernate.validator.internal.engine.messageinterpolation.DefaultLocaleResolver; import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTerm; import org.hibernate.validator.internal.engine.messageinterpolation.ParameterTermResolver; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.spi.messageinterpolation.LocaleResolver; /** * Resource bundle message interpolator, it does not support EL expression * and does support parameter value expression * * @author Adam Stawicki + * @author Guillaume Smet * @since 5.2 */ public class ParameterMessageInterpolator extends AbstractMessageInterpolator { @@ -29,7 +32,7 @@ public class ParameterMessageInterpolator extends AbstractMessageInterpolator { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); public ParameterMessageInterpolator() { - this( Collections.emptySet(), Locale.getDefault() ); + this( Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver() ); } /** @@ -37,7 +40,15 @@ public ParameterMessageInterpolator() { */ @Incubating public ParameterMessageInterpolator(Set localesToInitialize, Locale defaultLocale) { - super( localesToInitialize, defaultLocale ); + this( localesToInitialize, defaultLocale, new DefaultLocaleResolver() ); + } + + /** + * @since 6.1.1 + */ + @Incubating + public ParameterMessageInterpolator(Set localesToInitialize, Locale defaultLocale, LocaleResolver localeResolver) { + super( localesToInitialize, defaultLocale, localeResolver ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java index 1b97418c3c..87c5ed329f 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java @@ -17,11 +17,13 @@ import javax.el.ExpressionFactory; import org.hibernate.validator.Incubating; +import org.hibernate.validator.internal.engine.messageinterpolation.DefaultLocaleResolver; import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTerm; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader; import org.hibernate.validator.internal.util.privilegedactions.SetContextClassLoader; +import org.hibernate.validator.spi.messageinterpolation.LocaleResolver; import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; /** @@ -41,40 +43,41 @@ public class ResourceBundleMessageInterpolator extends AbstractMessageInterpolat private final ExpressionFactory expressionFactory; public ResourceBundleMessageInterpolator() { - this( Collections.emptySet(), Locale.getDefault() ); + this( Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver() ); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator) { - this( userResourceBundleLocator, Collections.emptySet(), Locale.getDefault() ); + this( userResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver() ); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator) { - this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault() ); + this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver() ); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator, boolean cachingEnabled) { - this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), cachingEnabled ); + this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), + cachingEnabled ); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, boolean cachingEnabled) { - this( userResourceBundleLocator, null, Collections.emptySet(), Locale.getDefault(), cachingEnabled ); + this( userResourceBundleLocator, null, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), cachingEnabled ); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, boolean cachingEnabled, ExpressionFactory expressionFactory) { - this( userResourceBundleLocator, null, Collections.emptySet(), Locale.getDefault(), cachingEnabled ); + this( userResourceBundleLocator, null, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), cachingEnabled ); } /** * @since 6.1.1 */ @Incubating - public ResourceBundleMessageInterpolator(Set localesToInitialize, Locale defaultLocale) { - super( localesToInitialize, defaultLocale ); + public ResourceBundleMessageInterpolator(Set localesToInitialize, Locale defaultLocale, LocaleResolver localeResolver) { + super( localesToInitialize, defaultLocale, localeResolver ); this.expressionFactory = buildExpressionFactory(); } @@ -82,8 +85,11 @@ public ResourceBundleMessageInterpolator(Set localesToInitialize, Locale * @since 6.1.1 */ @Incubating - public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, Set localesToInitialize, Locale defaultLocale) { - super( userResourceBundleLocator, localesToInitialize, defaultLocale ); + public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, + Set localesToInitialize, + Locale defaultLocale, + LocaleResolver localeResolver) { + super( userResourceBundleLocator, localesToInitialize, defaultLocale, localeResolver ); this.expressionFactory = buildExpressionFactory(); } @@ -94,8 +100,9 @@ public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundl public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator, Set localesToInitialize, - Locale defaultLocale) { - super( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize, defaultLocale ); + Locale defaultLocale, + LocaleResolver localeResolver) { + super( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize, defaultLocale, localeResolver ); this.expressionFactory = buildExpressionFactory(); } @@ -107,8 +114,9 @@ public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundl ResourceBundleLocator contributorResourceBundleLocator, Set localesToInitialize, Locale defaultLocale, + LocaleResolver localeResolver, boolean cachingEnabled) { - super( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize, defaultLocale, cachingEnabled ); + super( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize, defaultLocale, localeResolver, cachingEnabled ); this.expressionFactory = buildExpressionFactory(); } @@ -119,8 +127,9 @@ public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundl public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, Set localesToInitialize, Locale defaultLocale, + LocaleResolver localeResolver, boolean cachingEnabled) { - super( userResourceBundleLocator, null, localesToInitialize, defaultLocale, cachingEnabled ); + super( userResourceBundleLocator, null, localesToInitialize, defaultLocale, localeResolver, cachingEnabled ); this.expressionFactory = buildExpressionFactory(); } @@ -131,9 +140,10 @@ public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundl public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, Set localesToInitialize, Locale defaultLocale, + LocaleResolver localeResolver, boolean cachingEnabled, ExpressionFactory expressionFactory) { - super( userResourceBundleLocator, null, localesToInitialize, defaultLocale, cachingEnabled ); + super( userResourceBundleLocator, null, localesToInitialize, defaultLocale, localeResolver, cachingEnabled ); this.expressionFactory = expressionFactory; } diff --git a/engine/src/main/java/org/hibernate/validator/spi/messageinterpolation/LocaleResolver.java b/engine/src/main/java/org/hibernate/validator/spi/messageinterpolation/LocaleResolver.java new file mode 100644 index 0000000000..15f8e2c7f7 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/spi/messageinterpolation/LocaleResolver.java @@ -0,0 +1,31 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.spi.messageinterpolation; + +import java.util.Locale; + +import org.hibernate.validator.Incubating; + +/** + * Define the strategy used to resolve the locale user for message interpolation when no locale is defined from the list + * of supported locales. + * + * @author Guillaume Smet + * @since 6.1.1 + */ +@Incubating +public interface LocaleResolver { + + /** + * Returns the locale used for message interpolation when no locale is defined. + * + * @param context the context + * + * @return the locale to use for message interpolation, never null + */ + Locale resolve(LocaleResolverContext context); +} diff --git a/engine/src/main/java/org/hibernate/validator/spi/messageinterpolation/LocaleResolverContext.java b/engine/src/main/java/org/hibernate/validator/spi/messageinterpolation/LocaleResolverContext.java new file mode 100644 index 0000000000..742fb40fe5 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/spi/messageinterpolation/LocaleResolverContext.java @@ -0,0 +1,26 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.spi.messageinterpolation; + +import java.util.Locale; +import java.util.Set; + +import org.hibernate.validator.Incubating; + +/** + * Context used for locale resolution. + * + * @author Guillaume Smet + * @since 6.1.1 + */ +@Incubating +public interface LocaleResolverContext { + + Set getSupportedLocales(); + + Locale getDefaultLocale(); +} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/LocaleResolverTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/LocaleResolverTest.java new file mode 100644 index 0000000000..2083e3f9b1 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/LocaleResolverTest.java @@ -0,0 +1,100 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.engine.messageinterpolation; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Locale; + +import javax.validation.MessageInterpolator; +import javax.validation.Validation; +import javax.validation.ValidatorFactory; +import javax.validation.metadata.ConstraintDescriptor; + +import org.hibernate.validator.HibernateValidator; +import org.hibernate.validator.spi.messageinterpolation.LocaleResolver; +import org.hibernate.validator.spi.messageinterpolation.LocaleResolverContext; +import org.hibernate.validator.testutil.TestForIssue; +import org.hibernate.validator.testutil.ValidationXmlTestHelper; +import org.testng.annotations.Test; + +@TestForIssue(jiraKey = "HV-1749") +public class LocaleResolverTest { + + @Test + public void testLocaleResolver() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .localeResolver( new StaticFieldLocaleResolver() ) + .buildValidatorFactory(); + MessageInterpolator messageInterpolator = validatorFactory.getMessageInterpolator(); + + StaticFieldLocaleResolver.resolvedLocale = Locale.FRANCE; + assertThat( messageInterpolator.interpolate( "{javax.validation.constraints.AssertFalse.message}", new TestContext() ) ) + .isEqualTo( "doit avoir la valeur faux" ); + + StaticFieldLocaleResolver.resolvedLocale = Locale.ITALY; + assertThat( messageInterpolator.interpolate( "{javax.validation.constraints.AssertFalse.message}", new TestContext() ) ) + .isEqualTo( "deve essere false" ); + } + + @Test + public void shouldApplyLocaleResolverConfiguredInValidationXml() { + runWithCustomValidationXml( "locale-resolver-validation.xml", new Runnable() { + + @Override + public void run() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .buildValidatorFactory(); + MessageInterpolator messageInterpolator = validatorFactory.getMessageInterpolator(); + + StaticFieldLocaleResolver.resolvedLocale = Locale.FRANCE; + assertThat( messageInterpolator.interpolate( "{javax.validation.constraints.AssertFalse.message}", new TestContext() ) ) + .isEqualTo( "doit avoir la valeur faux" ); + + StaticFieldLocaleResolver.resolvedLocale = Locale.ITALY; + assertThat( messageInterpolator.interpolate( "{javax.validation.constraints.AssertFalse.message}", new TestContext() ) ) + .isEqualTo( "deve essere false" ); + } + } ); + } + + private void runWithCustomValidationXml(String validationXmlName, Runnable runnable) { + new ValidationXmlTestHelper( LocaleResolverTest.class ). + runWithCustomValidationXml( validationXmlName, runnable ); + } + + public static class StaticFieldLocaleResolver implements LocaleResolver { + + private static Locale resolvedLocale = Locale.FRANCE; + + @Override + public Locale resolve(LocaleResolverContext context) { + return resolvedLocale; + } + } + + private static class TestContext implements MessageInterpolator.Context { + + @Override + public ConstraintDescriptor getConstraintDescriptor() { + return null; + } + + @Override + public Object getValidatedValue() { + return null; + } + + @SuppressWarnings("unchecked") + @Override + public T unwrap(Class type) { + return (T) this; + } + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/LocaleResolverTest.java b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/LocaleResolverTest.java new file mode 100644 index 0000000000..a3aa187008 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/LocaleResolverTest.java @@ -0,0 +1,136 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.predefinedscope; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Locale.LanguageRange; + +import javax.validation.MessageInterpolator; +import javax.validation.Validation; +import javax.validation.ValidatorFactory; +import javax.validation.metadata.ConstraintDescriptor; + +import org.hibernate.validator.PredefinedScopeHibernateValidator; +import org.hibernate.validator.spi.messageinterpolation.LocaleResolver; +import org.hibernate.validator.spi.messageinterpolation.LocaleResolverContext; +import org.hibernate.validator.testutil.TestForIssue; +import org.testng.annotations.Test; + +@TestForIssue(jiraKey = "HV-1749") +public class LocaleResolverTest { + + @Test + public void testLanguageRangeSupport() throws NoSuchMethodException, SecurityException { + ValidatorFactory validatorFactory = getValidatorFactoryWithInitializedLocales( Locale.FRANCE, new Locale( "es", "ES" ) ); + MessageInterpolator messageInterpolator = validatorFactory.getMessageInterpolator(); + + StaticFieldLocaleResolver.acceptLanguage = "fr-FR,fr;q=0.9"; + + assertThat( messageInterpolator.interpolate( "{javax.validation.constraints.AssertFalse.message}", new TestContext() ) ) + .isEqualTo( "doit avoir la valeur faux" ); + } + + @Test + public void testCascadePriorities() { + ValidatorFactory validatorFactory = getValidatorFactoryWithInitializedLocales( Locale.FRANCE, Locale.forLanguageTag( "es" ) ); + MessageInterpolator messageInterpolator = validatorFactory.getMessageInterpolator(); + + StaticFieldLocaleResolver.acceptLanguage = "hr-HR,hr;q=0.9,es;q=0.7"; + + assertThat( messageInterpolator.interpolate( "{javax.validation.constraints.AssertFalse.message}", new TestContext() ) ) + .isEqualTo( "debe ser falso" ); + } + + @Test + public void testFallbackToDefault() throws NoSuchMethodException, SecurityException { + // Defaults to en when we don't define a default as we launch Surefire with the en locale + ValidatorFactory validatorFactory = getValidatorFactoryWithInitializedLocales( new Locale( "es", "ES" ) ); + MessageInterpolator messageInterpolator = validatorFactory.getMessageInterpolator(); + + StaticFieldLocaleResolver.acceptLanguage = "hr-HR,hr;q=0.9"; + + assertThat( messageInterpolator.interpolate( "{javax.validation.constraints.AssertFalse.message}", new TestContext() ) ) + .isEqualTo( "must be false" ); + + // Defaults to fr_FR if we define it as the default locale + validatorFactory = getValidatorFactoryWithDefaultLocaleAndInitializedLocales( Locale.FRANCE, Locale.forLanguageTag( "es_ES" ) ); + messageInterpolator = validatorFactory.getMessageInterpolator(); + + assertThat( messageInterpolator.interpolate( "{javax.validation.constraints.AssertFalse.message}", new TestContext() ) ) + .isEqualTo( "doit avoir la valeur faux" ); + } + + private static ValidatorFactory getValidatorFactoryWithInitializedLocales(Locale... locales) { + ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) + .configure() + .localeResolver( new StaticFieldLocaleResolver() ) + .initializeLocales( new HashSet<>( Arrays.asList( locales ) ) ) + .initializeBeanMetaData( new HashSet<>( Arrays.asList( Bean.class ) ) ) + .buildValidatorFactory(); + + return validatorFactory; + } + + private static ValidatorFactory getValidatorFactoryWithDefaultLocaleAndInitializedLocales(Locale defaultLocale, Locale... locales) { + ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) + .configure() + .localeResolver( new StaticFieldLocaleResolver() ) + .initializeLocales( new HashSet<>( Arrays.asList( locales ) ) ) + .defaultLocale( defaultLocale ) + .initializeBeanMetaData( new HashSet<>( Arrays.asList( Bean.class ) ) ) + .buildValidatorFactory(); + + return validatorFactory; + } + + private static class Bean { + } + + private static class StaticFieldLocaleResolver implements LocaleResolver { + + private static String acceptLanguage; + + @Override + public Locale resolve(LocaleResolverContext context) { + List localePriorities = LanguageRange.parse( acceptLanguage ); + if ( localePriorities.isEmpty() ) { + return context.getDefaultLocale(); + } + + List resolvedLocales = Locale.filter( localePriorities, context.getSupportedLocales() ); + if ( resolvedLocales.size() > 0 ) { + return resolvedLocales.get( 0 ); + } + + return context.getDefaultLocale(); + } + } + + private static class TestContext implements MessageInterpolator.Context { + + @Override + public ConstraintDescriptor getConstraintDescriptor() { + return null; + } + + @Override + public Object getValidatedValue() { + return null; + } + + @SuppressWarnings("unchecked") + @Override + public T unwrap(Class type) { + return (T) this; + } + } +} diff --git a/engine/src/test/resources/org/hibernate/validator/test/internal/engine/messageinterpolation/locale-resolver-validation.xml b/engine/src/test/resources/org/hibernate/validator/test/internal/engine/messageinterpolation/locale-resolver-validation.xml new file mode 100644 index 0000000000..46c9c62df7 --- /dev/null +++ b/engine/src/test/resources/org/hibernate/validator/test/internal/engine/messageinterpolation/locale-resolver-validation.xml @@ -0,0 +1,16 @@ + + + + + org.hibernate.validator.test.internal.engine.messageinterpolation.LocaleResolverTest$StaticFieldLocaleResolver + From c4dfc46b9c9f851b634f2a679c06eedfc3b02fcb Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 30 Dec 2019 22:53:51 +0100 Subject: [PATCH 283/393] HV-1748 Generalize the ability to define the supported locales While not used to initialize the resource bundles, it can be used for advanced locale resolution via Locale.LanguageRange. --- .../BaseHibernateValidatorConfiguration.java | 30 ++++++++ ...dScopeHibernateValidatorConfiguration.java | 4 ++ .../engine/AbstractConfigurationImpl.java | 48 +++++++++---- .../internal/engine/ConfigurationImpl.java | 6 ++ .../PredefinedScopeConfigurationImpl.java | 21 +----- .../AbstractMessageInterpolator.java | 72 +++++++++++++------ .../ParameterMessageInterpolator.java | 10 +-- .../ResourceBundleMessageInterpolator.java | 46 ++++++------ .../AggregateResourceBundleLocator.java | 43 +++++++---- .../PlatformResourceBundleLocator.java | 48 ++++++++----- .../PredefinedScopeValidatorFactoryTest.java | 6 +- 11 files changed, 224 insertions(+), 110 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java index f1154f797e..d2f2c7030a 100644 --- a/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java @@ -7,6 +7,8 @@ package org.hibernate.validator; import java.time.Duration; +import java.util.Arrays; +import java.util.HashSet; import java.util.Locale; import java.util.Set; @@ -372,6 +374,34 @@ public interface BaseHibernateValidatorConfiguration + * Can be used for advanced locale resolution and/or to force the initialization of the resource bundles at + * bootstrap. + *

    + * If not set, defaults to a singleton containing {@link Locale#getDefault()}. + * + * @since 6.1.1 + */ + @Incubating + S locales(Set locales); + + /** + * Allows setting the list of the locales supported by this ValidatorFactory. + *

    + * Can be used for advanced locale resolution and/or to force the initialization of the resource bundles at + * bootstrap. + *

    + * If not set, defaults to a singleton containing {@link Locale#getDefault()}. + * + * @since 6.1.1 + */ + @Incubating + default S locales(Locale... locales) { + return locales( new HashSet<>( Arrays.asList( locales ) ) ); + } + /** * Allows setting the default locale used to interpolate the constraint violation messages. *

    diff --git a/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java index ff8a7ac33d..50be18cc58 100644 --- a/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java @@ -25,7 +25,11 @@ public interface PredefinedScopeHibernateValidatorConfiguration extends BaseHibe @Incubating PredefinedScopeHibernateValidatorConfiguration initializeBeanMetaData(Set> beanClassesToInitialize); + /** + * @deprecated Planned for removal, use {@link BaseHibernateValidatorConfiguration#locales(Set)} instead. + */ @Incubating + @Deprecated PredefinedScopeHibernateValidatorConfiguration initializeLocales(Set locales); @Incubating diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java index c86c4e5777..e1996ff504 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java @@ -46,6 +46,7 @@ import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorManager; import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; import org.hibernate.validator.internal.properties.javabean.JavaBeanHelper; +import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.Version; import org.hibernate.validator.internal.util.logging.Log; @@ -71,6 +72,7 @@ * @author Gunnar Morling * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI * @author Chris Beckey <cbeckey@paypal.com> + * @author Guillaume Smet */ public abstract class AbstractConfigurationImpl> implements BaseHibernateValidatorConfiguration, ConfigurationState { @@ -113,6 +115,7 @@ public abstract class AbstractConfigurationImpl locales = Collections.emptySet(); private Locale defaultLocale = Locale.getDefault(); private LocaleResolver localeResolver; @@ -338,6 +341,14 @@ public T getterPropertySelectionStrategy(GetterPropertySelectionStrategy getterP return thisAsT(); } + @Override + public T locales(Set locales) { + Contracts.assertNotNull( defaultLocale, MESSAGES.parameterMustNotBeNull( "locales" ) ); + + this.locales = locales; + return thisAsT(); + } + @Override public T defaultLocale(Locale defaultLocale) { Contracts.assertNotNull( defaultLocale, MESSAGES.parameterMustNotBeNull( "defaultLocale" ) ); @@ -543,8 +554,9 @@ public ClassLoader getExternalClassLoader() { @Override public final MessageInterpolator getDefaultMessageInterpolator() { if ( defaultMessageInterpolator == null ) { - defaultMessageInterpolator = new ResourceBundleMessageInterpolator( getDefaultResourceBundleLocator(), getAllLocalesToInitialize(), - defaultLocale, ValidatorFactoryConfigurationHelper.determineLocaleResolver( this, this.getProperties(), externalClassLoader ) ); + defaultMessageInterpolator = new ResourceBundleMessageInterpolator( getDefaultResourceBundleLocator(), getAllSupportedLocales(), + defaultLocale, ValidatorFactoryConfigurationHelper.determineLocaleResolver( this, this.getProperties(), externalClassLoader ), + preloadResourceBundles() ); } return defaultMessageInterpolator; @@ -564,7 +576,7 @@ public final ConstraintValidatorFactory getDefaultConstraintValidatorFactory() { public final ResourceBundleLocator getDefaultResourceBundleLocator() { if ( defaultResourceBundleLocator == null ) { defaultResourceBundleLocator = new PlatformResourceBundleLocator( - ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, getAllLocalesToInitialize() ); + ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, preloadResourceBundles(), getAllSupportedLocales() ); } return defaultResourceBundleLocator; @@ -714,12 +726,14 @@ private MessageInterpolator getDefaultMessageInterpolatorConfiguredWithClassLoad if ( externalClassLoader != null ) { PlatformResourceBundleLocator userResourceBundleLocator = new PlatformResourceBundleLocator( ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, - getAllLocalesToInitialize(), + preloadResourceBundles(), + getAllSupportedLocales(), externalClassLoader ); PlatformResourceBundleLocator contributorResourceBundleLocator = new PlatformResourceBundleLocator( ResourceBundleMessageInterpolator.CONTRIBUTOR_VALIDATION_MESSAGES, - getAllLocalesToInitialize(), + preloadResourceBundles(), + getAllSupportedLocales(), externalClassLoader, true ); @@ -733,9 +747,10 @@ private MessageInterpolator getDefaultMessageInterpolatorConfiguredWithClassLoad return new ResourceBundleMessageInterpolator( userResourceBundleLocator, contributorResourceBundleLocator, - getAllLocalesToInitialize(), + getAllSupportedLocales(), defaultLocale, - ValidatorFactoryConfigurationHelper.determineLocaleResolver( this, this.getProperties(), externalClassLoader ) + ValidatorFactoryConfigurationHelper.determineLocaleResolver( this, this.getProperties(), externalClassLoader ), + preloadResourceBundles() ); } finally { @@ -747,15 +762,22 @@ private MessageInterpolator getDefaultMessageInterpolatorConfiguredWithClassLoad } } - protected final Locale getDefaultLocale() { - return defaultLocale; - } + private Set getAllSupportedLocales() { + if ( locales.isEmpty() ) { + return Collections.singleton( defaultLocale ); + } + if ( locales.contains( defaultLocale ) ) { + return locales; + } - protected Set getAllLocalesToInitialize() { - // By default, we return an empty set meaning that we will dynamically initialize the locales. - return Collections.emptySet(); + Set allLocales = CollectionHelper.newHashSet( locales.size() + 1 ); + allLocales.addAll( locales ); + allLocales.add( defaultLocale ); + return allLocales; } + protected abstract boolean preloadResourceBundles(); + @SuppressWarnings("unchecked") protected T thisAsT() { return (T) this; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java index f6292695e8..71b3f21d4e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java @@ -20,6 +20,7 @@ * @author Gunnar Morling * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI * @author Chris Beckey <cbeckey@paypal.com> + * @author Guillaume Smet */ public class ConfigurationImpl extends AbstractConfigurationImpl implements HibernateValidatorConfiguration, ConfigurationState { @@ -30,4 +31,9 @@ public ConfigurationImpl(BootstrapState state) { public ConfigurationImpl(ValidationProvider provider) { super( provider ); } + + @Override + protected boolean preloadResourceBundles() { + return false; + } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java index 03585920d8..7c8be7fa88 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java @@ -8,7 +8,6 @@ import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES; -import java.util.Collections; import java.util.Locale; import java.util.Set; @@ -31,13 +30,6 @@ public class PredefinedScopeConfigurationImpl extends AbstractConfigurationImpl< private BeanMetaDataClassNormalizer beanMetaDataClassNormalizer; - /** - * Locales to initialize eagerly. - *

    - * We will always include the default locale in the final list. - */ - private Set localesToInitialize = Collections.emptySet(); - public PredefinedScopeConfigurationImpl(BootstrapState state) { super( state ); } @@ -59,7 +51,7 @@ public Set> getBeanClassesToInitialize() { @Override public PredefinedScopeHibernateValidatorConfiguration initializeLocales(Set localesToInitialize) { Contracts.assertNotNull( localesToInitialize, MESSAGES.parameterMustNotBeNull( "localesToInitialize" ) ); - this.localesToInitialize = localesToInitialize; + locales( localesToInitialize ); return thisAsT(); } @@ -74,14 +66,7 @@ public BeanMetaDataClassNormalizer getBeanMetaDataClassNormalizer() { } @Override - protected Set getAllLocalesToInitialize() { - if ( localesToInitialize.isEmpty() ) { - return Collections.singleton( getDefaultLocale() ); - } - - Set allLocales = CollectionHelper.newHashSet( localesToInitialize.size() + 1 ); - allLocales.addAll( localesToInitialize ); - allLocales.add( getDefaultLocale() ); - return Collections.unmodifiableSet( allLocales ); + protected boolean preloadResourceBundles() { + return true; } } diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java index e53d73e7ae..c11da82c84 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java @@ -12,6 +12,7 @@ import java.lang.invoke.MethodHandles; import java.util.Collections; import java.util.EnumSet; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.MissingResourceException; @@ -23,6 +24,7 @@ import javax.validation.MessageInterpolator; import org.hibernate.validator.Incubating; +import org.hibernate.validator.internal.engine.PredefinedScopeValidatorFactoryImpl; import org.hibernate.validator.internal.engine.messageinterpolation.DefaultLocaleResolver; import org.hibernate.validator.internal.engine.messageinterpolation.DefaultLocaleResolverContext; import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTermType; @@ -31,6 +33,7 @@ import org.hibernate.validator.internal.engine.messageinterpolation.parser.Token; import org.hibernate.validator.internal.engine.messageinterpolation.parser.TokenCollector; import org.hibernate.validator.internal.engine.messageinterpolation.parser.TokenIterator; +import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.ConcurrentReferenceHashMap; import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.logging.Log; @@ -142,7 +145,7 @@ public abstract class AbstractMessageInterpolator implements MessageInterpolator * {@code MessageInterpolator} using the default resource bundle locators. */ public AbstractMessageInterpolator() { - this( Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver() ); + this( Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), false ); } /** @@ -151,7 +154,7 @@ public AbstractMessageInterpolator() { * @param userResourceBundleLocator {@code ResourceBundleLocator} used to load user provided resource bundle */ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator) { - this( userResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver() ); + this( userResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), false ); } /** @@ -163,7 +166,7 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat */ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator) { - this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver() ); + this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), false ); } /** @@ -184,33 +187,38 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat /** * {@code MessageInterpolator} using the default resource bundle locators. * - * @param localesToInitialize the set of locales to initialize at bootstrap + * @param locales the set of locales to initialize at bootstrap * @param defaultLocale the default locale * @param localeResolver the locale resolver + * @param preloadResourceBundles if the resource bundled should be initialized at initialization time, this is useful in the case of a + * {@link PredefinedScopeValidatorFactoryImpl} * * @since 6.1.1 */ @Incubating - public AbstractMessageInterpolator(Set localesToInitialize, Locale defaultLocale, LocaleResolver localeResolver) { - this( null, localesToInitialize, defaultLocale, localeResolver ); + public AbstractMessageInterpolator(Set locales, Locale defaultLocale, LocaleResolver localeResolver, boolean preloadResourceBundles) { + this( null, locales, defaultLocale, localeResolver, preloadResourceBundles ); } /** * {@code MessageInterpolator} taking a resource bundle locator. * * @param userResourceBundleLocator {@code ResourceBundleLocator} used to load user provided resource bundle - * @param localesToInitialize the set of locales to initialize at bootstrap + * @param locales the set of locales to initialize at bootstrap * @param defaultLocale the default locale * @param localeResolver the locale resolver + * @param preloadResourceBundles if the resource bundled should be initialized at initialization time, this is useful in the case of a + * {@link PredefinedScopeValidatorFactoryImpl} * * @since 6.1.1 */ @Incubating public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, - Set localesToInitialize, + Set locales, Locale defaultLocale, - LocaleResolver localeResolver) { - this( userResourceBundleLocator, null, localesToInitialize, defaultLocale, localeResolver ); + LocaleResolver localeResolver, + boolean preloadResourceBundles) { + this( userResourceBundleLocator, null, locales, defaultLocale, localeResolver, preloadResourceBundles ); } /** @@ -221,6 +229,8 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat * @param localesToInitialize the set of locales to initialize at bootstrap * @param defaultLocale the default locale * @param localeResolver the locale resolver + * @param preloadResourceBundles if the resource bundled should be initialized at initialization time, this is useful in the case of a + * {@link PredefinedScopeValidatorFactoryImpl} * * @since 6.1.1 */ @@ -229,38 +239,48 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat ResourceBundleLocator contributorResourceBundleLocator, Set localesToInitialize, Locale defaultLocale, - LocaleResolver localeResolver) { - this( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize, defaultLocale, localeResolver, true ); + LocaleResolver localeResolver, + boolean preloadResourceBundles) { + this( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize, defaultLocale, localeResolver, preloadResourceBundles, true ); } /** * {@code MessageInterpolator} taking two resource bundle locators. * * @param userResourceBundleLocator {@code ResourceBundleLocator} used to load user provided resource bundle - * @param contributorResourceBundleLocator {@code ResourceBundleLocator} used to load resource bundle of constraint contributor - * @param localesToInitialize the set of locales to initialize at bootstrap + * @param contributorResourceBundleLocator {@code ResourceBundleLocator} used to load resource bundle of constraint + * contributor + * @param locales the set of locales to initialize at bootstrap * @param defaultLocale the default locale * @param cacheMessages whether resolved messages should be cached or not * @param localeResolver the locale resolver + * @param preloadResourceBundles if the resource bundled should be initialized at initialization time, this is useful in the case of a + * {@link PredefinedScopeValidatorFactoryImpl} * * @since 6.1.1 */ @Incubating public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator, - Set localesToInitialize, + Set locales, Locale defaultLocale, LocaleResolver localeResolver, + boolean preloadResourceBundles, boolean cacheMessages) { - Contracts.assertNotNull( localesToInitialize, MESSAGES.parameterMustNotBeNull( "localesToInitialize" ) ); + Contracts.assertNotNull( locales, MESSAGES.parameterMustNotBeNull( "localesToInitialize" ) ); Contracts.assertNotNull( defaultLocale, MESSAGES.parameterMustNotBeNull( "defaultLocale" ) ); Contracts.assertNotNull( localeResolver, MESSAGES.parameterMustNotBeNull( "localeResolver" ) ); - this.localeResolverContext = new DefaultLocaleResolverContext( localesToInitialize, defaultLocale ); + Set allLocales = CollectionHelper.toImmutableSet( getAllLocales( locales, defaultLocale ) ); + + this.localeResolverContext = new DefaultLocaleResolverContext( allLocales, defaultLocale ); this.localeResolver = localeResolver; + Set allLocalesToInitialize = preloadResourceBundles ? allLocales : Collections.emptySet(); + if ( userResourceBundleLocator == null ) { - this.userResourceBundleLocator = new PlatformResourceBundleLocator( USER_VALIDATION_MESSAGES, localesToInitialize ); + this.userResourceBundleLocator = new PlatformResourceBundleLocator( USER_VALIDATION_MESSAGES, + preloadResourceBundles, allLocalesToInitialize ); } else { this.userResourceBundleLocator = userResourceBundleLocator; @@ -269,7 +289,8 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat if ( contributorResourceBundleLocator == null ) { this.contributorResourceBundleLocator = new PlatformResourceBundleLocator( CONTRIBUTOR_VALIDATION_MESSAGES, - localesToInitialize, + preloadResourceBundles, + allLocalesToInitialize, null, true ); @@ -278,7 +299,7 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat this.contributorResourceBundleLocator = contributorResourceBundleLocator; } - this.defaultResourceBundleLocator = new PlatformResourceBundleLocator( DEFAULT_VALIDATION_MESSAGES, localesToInitialize ); + this.defaultResourceBundleLocator = new PlatformResourceBundleLocator( DEFAULT_VALIDATION_MESSAGES, preloadResourceBundles, allLocalesToInitialize ); this.cachingEnabled = cacheMessages; if ( cachingEnabled ) { @@ -340,6 +361,17 @@ public String interpolate(String message, Context context, Locale locale) { return interpolatedMessage; } + private Set getAllLocales(Set localesToInitialize, Locale defaultLocale) { + if ( localesToInitialize.contains( defaultLocale ) ) { + return localesToInitialize; + } + + Set allLocales = new HashSet<>( localesToInitialize.size() + 1 ); + allLocales.addAll( localesToInitialize ); + allLocales.add( defaultLocale ); + return allLocales; + } + /** * Runs the message interpolation according to algorithm specified in the Bean Validation specification. *

    diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java index 759b545d91..41c24e9cd5 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java @@ -32,23 +32,23 @@ public class ParameterMessageInterpolator extends AbstractMessageInterpolator { private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); public ParameterMessageInterpolator() { - this( Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver() ); + this( Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), false ); } /** * @since 6.1.1 */ @Incubating - public ParameterMessageInterpolator(Set localesToInitialize, Locale defaultLocale) { - this( localesToInitialize, defaultLocale, new DefaultLocaleResolver() ); + public ParameterMessageInterpolator(Set locales, Locale defaultLocale, boolean preloadResourceBundles) { + this( locales, defaultLocale, new DefaultLocaleResolver(), preloadResourceBundles ); } /** * @since 6.1.1 */ @Incubating - public ParameterMessageInterpolator(Set localesToInitialize, Locale defaultLocale, LocaleResolver localeResolver) { - super( localesToInitialize, defaultLocale, localeResolver ); + public ParameterMessageInterpolator(Set locales, Locale defaultLocale, LocaleResolver localeResolver, boolean preloadResourceBundles) { + super( locales, defaultLocale, localeResolver, preloadResourceBundles ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java index 87c5ed329f..9c8646539f 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java @@ -43,41 +43,41 @@ public class ResourceBundleMessageInterpolator extends AbstractMessageInterpolat private final ExpressionFactory expressionFactory; public ResourceBundleMessageInterpolator() { - this( Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver() ); + this( Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), false ); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator) { - this( userResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver() ); + this( userResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), false ); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator) { - this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver() ); + this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), false ); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator, boolean cachingEnabled) { this( userResourceBundleLocator, contributorResourceBundleLocator, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), - cachingEnabled ); + false, cachingEnabled ); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, boolean cachingEnabled) { - this( userResourceBundleLocator, null, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), cachingEnabled ); + this( userResourceBundleLocator, null, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), false, cachingEnabled ); } public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, boolean cachingEnabled, ExpressionFactory expressionFactory) { - this( userResourceBundleLocator, null, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), cachingEnabled ); + this( userResourceBundleLocator, null, Collections.emptySet(), Locale.getDefault(), new DefaultLocaleResolver(), false, cachingEnabled ); } /** * @since 6.1.1 */ @Incubating - public ResourceBundleMessageInterpolator(Set localesToInitialize, Locale defaultLocale, LocaleResolver localeResolver) { - super( localesToInitialize, defaultLocale, localeResolver ); + public ResourceBundleMessageInterpolator(Set locales, Locale defaultLocale, LocaleResolver localeResolver, boolean preloadResourceBundles) { + super( locales, defaultLocale, localeResolver, preloadResourceBundles ); this.expressionFactory = buildExpressionFactory(); } @@ -86,10 +86,11 @@ public ResourceBundleMessageInterpolator(Set localesToInitialize, Locale */ @Incubating public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, - Set localesToInitialize, + Set locales, Locale defaultLocale, - LocaleResolver localeResolver) { - super( userResourceBundleLocator, localesToInitialize, defaultLocale, localeResolver ); + LocaleResolver localeResolver, + boolean preloadResourceBundles) { + super( userResourceBundleLocator, locales, defaultLocale, localeResolver, preloadResourceBundles ); this.expressionFactory = buildExpressionFactory(); } @@ -99,10 +100,11 @@ public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundl @Incubating public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator, - Set localesToInitialize, + Set locales, Locale defaultLocale, - LocaleResolver localeResolver) { - super( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize, defaultLocale, localeResolver ); + LocaleResolver localeResolver, + boolean preloadResourceBundles) { + super( userResourceBundleLocator, contributorResourceBundleLocator, locales, defaultLocale, localeResolver, preloadResourceBundles ); this.expressionFactory = buildExpressionFactory(); } @@ -112,11 +114,13 @@ public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundl @Incubating public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, ResourceBundleLocator contributorResourceBundleLocator, - Set localesToInitialize, + Set locales, Locale defaultLocale, LocaleResolver localeResolver, + boolean preloadResourceBundles, boolean cachingEnabled) { - super( userResourceBundleLocator, contributorResourceBundleLocator, localesToInitialize, defaultLocale, localeResolver, cachingEnabled ); + super( userResourceBundleLocator, contributorResourceBundleLocator, locales, defaultLocale, localeResolver, preloadResourceBundles, + cachingEnabled ); this.expressionFactory = buildExpressionFactory(); } @@ -125,11 +129,12 @@ public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundl */ @Incubating public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, - Set localesToInitialize, + Set locales, Locale defaultLocale, LocaleResolver localeResolver, + boolean preloadResourceBundles, boolean cachingEnabled) { - super( userResourceBundleLocator, null, localesToInitialize, defaultLocale, localeResolver, cachingEnabled ); + super( userResourceBundleLocator, null, locales, defaultLocale, localeResolver, preloadResourceBundles, cachingEnabled ); this.expressionFactory = buildExpressionFactory(); } @@ -138,12 +143,13 @@ public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundl */ @Incubating public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundleLocator, - Set localesToInitialize, + Set locales, Locale defaultLocale, LocaleResolver localeResolver, + boolean preloadResourceBundles, boolean cachingEnabled, ExpressionFactory expressionFactory) { - super( userResourceBundleLocator, null, localesToInitialize, defaultLocale, localeResolver, cachingEnabled ); + super( userResourceBundleLocator, null, locales, defaultLocale, localeResolver, preloadResourceBundles, cachingEnabled ); this.expressionFactory = expressionFactory; } diff --git a/engine/src/main/java/org/hibernate/validator/resourceloading/AggregateResourceBundleLocator.java b/engine/src/main/java/org/hibernate/validator/resourceloading/AggregateResourceBundleLocator.java index daae9fa6fb..225d84eb1c 100644 --- a/engine/src/main/java/org/hibernate/validator/resourceloading/AggregateResourceBundleLocator.java +++ b/engine/src/main/java/org/hibernate/validator/resourceloading/AggregateResourceBundleLocator.java @@ -17,6 +17,7 @@ import java.util.ResourceBundle; import java.util.Set; +import org.hibernate.validator.Incubating; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; @@ -42,7 +43,7 @@ public class AggregateResourceBundleLocator extends DelegatingResourceBundleLoca * first bundle containing the key. */ public AggregateResourceBundleLocator(List bundleNames) { - this( bundleNames, Collections.emptySet(), null ); + this( bundleNames, false, Collections.emptySet(), null ); } /** @@ -58,7 +59,7 @@ public AggregateResourceBundleLocator(List bundleNames) { * source bundles. */ public AggregateResourceBundleLocator(List bundleNames, ResourceBundleLocator delegate) { - this( bundleNames, Collections.emptySet(), delegate, null ); + this( bundleNames, false, Collections.emptySet(), delegate, null ); } /** @@ -77,7 +78,7 @@ public AggregateResourceBundleLocator(List bundleNames, ResourceBundleLo */ public AggregateResourceBundleLocator(List bundleNames, ResourceBundleLocator delegate, ClassLoader classLoader) { - this( bundleNames, Collections.emptySet(), delegate, classLoader ); + this( bundleNames, false, Collections.emptySet(), delegate, classLoader ); } /** @@ -88,12 +89,14 @@ public AggregateResourceBundleLocator(List bundleNames, ResourceBundleLo * contain all entries from all source bundles. In case a key occurs * in multiple source bundles, the value will be taken from the * first bundle containing the key. - * @param localesToInitialize The set of locales to initialize at bootstrap. + * @param preloadResourceBundles if resource bundles should be initialized when initializing the locator + * @param localesToInitialize The set of locales to initialize at bootstrap * - * @since 6.1 + * @since 6.1.1 */ - public AggregateResourceBundleLocator(List bundleNames, Set localesToInitialize) { - this( bundleNames, localesToInitialize, null ); + @Incubating + public AggregateResourceBundleLocator(List bundleNames, boolean preloadResourceBundles, Set localesToInitialize) { + this( bundleNames, preloadResourceBundles, localesToInitialize, null ); } /** @@ -104,15 +107,20 @@ public AggregateResourceBundleLocator(List bundleNames, Set loca * contain all keys from all source bundles. In case a key occurs * in multiple source bundles, the value will be taken from the * first bundle containing the key. - * @param localesToInitialize The set of locales to initialize at bootstrap. + * @param preloadResourceBundles if resource bundles should be initialized when initializing the locator + * @param localesToInitialize The set of locales to initialize at bootstrap * @param delegate A delegate resource bundle locator. The bundle returned by * this locator will be added to the aggregate bundle after all * source bundles. * - * @since 6.1 + * @since 6.1.1 */ - public AggregateResourceBundleLocator(List bundleNames, Set localesToInitialize, ResourceBundleLocator delegate) { - this( bundleNames, localesToInitialize, delegate, null ); + @Incubating + public AggregateResourceBundleLocator(List bundleNames, + boolean preloadResourceBundles, + Set localesToInitialize, + ResourceBundleLocator delegate) { + this( bundleNames, preloadResourceBundles, localesToInitialize, delegate, null ); } /** @@ -123,22 +131,27 @@ public AggregateResourceBundleLocator(List bundleNames, Set loca * contain all keys from all source bundles. In case a key occurs * in multiple source bundles, the value will be taken from the * first bundle containing the key. - * @param localesToInitialize The set of locales to initialize at bootstrap. + * @param preloadResourceBundles if resource bundles should be initialized when initializing the locator + * @param localesToInitialize The set of locales to initialize at bootstrap * @param delegate A delegate resource bundle locator. The bundle returned by * this locator will be added to the aggregate bundle after all * source bundles. * @param classLoader The classloader to use for loading the bundle. * - * @since 6.1 + * @since 6.1.1 */ - public AggregateResourceBundleLocator(List bundleNames, Set localesToInitialize, ResourceBundleLocator delegate, + @Incubating + public AggregateResourceBundleLocator(List bundleNames, + boolean preloadResourceBundles, + Set localesToInitialize, + ResourceBundleLocator delegate, ClassLoader classLoader) { super( delegate ); Contracts.assertValueNotNull( bundleNames, "bundleNames" ); List tmpBundleLocators = new ArrayList<>( bundleNames.size() ); for ( String bundleName : bundleNames ) { - tmpBundleLocators.add( new PlatformResourceBundleLocator( bundleName, localesToInitialize, classLoader ) ); + tmpBundleLocators.add( new PlatformResourceBundleLocator( bundleName, preloadResourceBundles, localesToInitialize, classLoader ) ); } this.resourceBundleLocators = CollectionHelper.toImmutableList( tmpBundleLocators ); } diff --git a/engine/src/main/java/org/hibernate/validator/resourceloading/PlatformResourceBundleLocator.java b/engine/src/main/java/org/hibernate/validator/resourceloading/PlatformResourceBundleLocator.java index 93ecb09465..e804fe8adc 100644 --- a/engine/src/main/java/org/hibernate/validator/resourceloading/PlatformResourceBundleLocator.java +++ b/engine/src/main/java/org/hibernate/validator/resourceloading/PlatformResourceBundleLocator.java @@ -24,6 +24,7 @@ import java.util.ResourceBundle; import java.util.Set; +import org.hibernate.validator.Incubating; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.logging.Log; @@ -52,6 +53,7 @@ public class PlatformResourceBundleLocator implements ResourceBundleLocator { private final ClassLoader classLoader; private final boolean aggregate; + private final boolean preloadResourceBundles; @Immutable private final Map preloadedResourceBundles; @@ -61,7 +63,7 @@ public class PlatformResourceBundleLocator implements ResourceBundleLocator { * @param bundleName the name of the bundle to load */ public PlatformResourceBundleLocator(String bundleName) { - this( bundleName, Collections.emptySet() ); + this( bundleName, false, Collections.emptySet() ); } /** @@ -75,7 +77,7 @@ public PlatformResourceBundleLocator(String bundleName) { * @since 5.2 */ public PlatformResourceBundleLocator(String bundleName, ClassLoader classLoader) { - this( bundleName, Collections.emptySet(), classLoader ); + this( bundleName, false, Collections.emptySet(), classLoader ); } /** @@ -90,41 +92,47 @@ public PlatformResourceBundleLocator(String bundleName, ClassLoader classLoader) * @since 5.2 */ public PlatformResourceBundleLocator(String bundleName, ClassLoader classLoader, boolean aggregate) { - this( bundleName, Collections.emptySet(), classLoader, aggregate ); + this( bundleName, false, Collections.emptySet(), classLoader, aggregate ); } /** * Creates a new {@link PlatformResourceBundleLocator}. * * @param bundleName the name of the bundle to load - * @param localesToInitialize the set of locales to initialize at bootstrap. + * @param preloadResourceBundles if resource bundles should be initialized when initializing the locator + * @param localesToInitialize the set of locales to initialize at bootstrap * - * @since 6.1 + * @since 6.1.1 */ - public PlatformResourceBundleLocator(String bundleName, Set localesToInitialize) { - this( bundleName, localesToInitialize, null ); + @Incubating + public PlatformResourceBundleLocator(String bundleName, boolean preloadResourceBundles, Set localesToInitialize) { + this( bundleName, preloadResourceBundles, localesToInitialize, null ); } /** * Creates a new {@link PlatformResourceBundleLocator}. * * @param bundleName the name of the bundle to load - * @param localesToInitialize the set of locales to initialize at bootstrap. + * @param preloadResourceBundles if resource bundles should be initialized when initializing the locator + * @param localesToInitialize the set of locales to initialize at bootstrap * @param classLoader the classloader to be used for loading the bundle. If {@code null}, the current thread context * classloader and finally Hibernate Validator's own classloader will be used for loading the specified * bundle. + * @param preloadResourceBundles if resource bundles should be initialized when initializing the locator * - * @since 6.1 + * @since 6.1.1 */ - public PlatformResourceBundleLocator(String bundleName, Set localesToInitialize, ClassLoader classLoader) { - this( bundleName, localesToInitialize, classLoader, false ); + @Incubating + public PlatformResourceBundleLocator(String bundleName, boolean preloadResourceBundles, Set localesToInitialize, ClassLoader classLoader) { + this( bundleName, preloadResourceBundles, localesToInitialize, classLoader, false ); } /** * Creates a new {@link PlatformResourceBundleLocator}. * * @param bundleName the name of the bundle to load - * @param localesToInitialize the set of locales to initialize at bootstrap. + * @param preloadResourceBundles if resource bundles should be initialized when initializing the locator + * @param localesToInitialize the set of locales to initialize at bootstrap * @param classLoader the classloader to be used for loading the bundle. If {@code null}, the current thread context * classloader and finally Hibernate Validator's own classloader will be used for loading the specified * bundle. @@ -132,7 +140,12 @@ public PlatformResourceBundleLocator(String bundleName, Set localesToIni * * @since 6.1 */ - public PlatformResourceBundleLocator(String bundleName, Set localesToInitialize, ClassLoader classLoader, boolean aggregate) { + @Incubating + public PlatformResourceBundleLocator(String bundleName, + boolean preloadResourceBundles, + Set localesToInitialize, + ClassLoader classLoader, + boolean aggregate) { Contracts.assertNotNull( bundleName, "bundleName" ); this.bundleName = bundleName; @@ -140,7 +153,11 @@ public PlatformResourceBundleLocator(String bundleName, Set localesToIni this.aggregate = aggregate && RESOURCE_BUNDLE_CONTROL_INSTANTIABLE; - if ( !localesToInitialize.isEmpty() ) { + this.preloadResourceBundles = preloadResourceBundles; + + if ( preloadResourceBundles ) { + Contracts.assertNotEmpty( localesToInitialize, "localesToInitialize may not be empty if resource bundles have to be preloaded" ); + Map tmpPreloadedResourceBundles = CollectionHelper.newHashMap( localesToInitialize.size() ); for ( Locale localeToPreload : localesToInitialize ) { tmpPreloadedResourceBundles.put( localeToPreload, doGetResourceBundle( localeToPreload ) ); @@ -162,8 +179,7 @@ public PlatformResourceBundleLocator(String bundleName, Set localesToIni */ @Override public ResourceBundle getResourceBundle(Locale locale) { - // we are in the preloading case - if ( !preloadedResourceBundles.isEmpty() ) { + if ( preloadResourceBundles ) { // we need to use containsKey() as the cached resource bundle can be null if ( preloadedResourceBundles.containsKey( locale ) ) { return preloadedResourceBundles.get( locale ); diff --git a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java index 7ad9e400c0..a9309cc767 100644 --- a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java @@ -230,7 +230,7 @@ public void testBeanMetaDataClassNormalizerNoNormalizer() { ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) .configure() .initializeBeanMetaData( beanMetaDataToInitialize ) - .initializeLocales( Collections.singleton( Locale.getDefault() ) ) + .locales( Collections.singleton( Locale.getDefault() ) ) .buildValidatorFactory(); // As we don't have any metadata for BeanProxy, we consider it is not constrained at all. @@ -246,7 +246,7 @@ public void testBeanMetaDataClassNormalizer() { ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) .configure() .initializeBeanMetaData( beanMetaDataToInitialize ) - .initializeLocales( Collections.singleton( Locale.getDefault() ) ) + .locales( Collections.singleton( Locale.getDefault() ) ) .beanMetaDataClassNormalizer( new MyProxyInterfaceBeanMetaDataClassNormalizer() ) .buildValidatorFactory(); @@ -345,7 +345,7 @@ private static ValidatorFactory getValidatorFactoryWithInitializedLocale(Locale return Validation.byProvider( PredefinedScopeHibernateValidator.class ) .configure() .initializeBeanMetaData( beanMetaDataToInitialize ) - .initializeLocales( Collections.singleton( locale ) ) + .locales( Collections.singleton( locale ) ) .buildValidatorFactory(); } From 582db15881df1884157b221c66f590256f1ac4c6 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 2 Jan 2020 19:00:40 +0100 Subject: [PATCH 284/393] HV-1748 HV-1749 Add some documentation about the localization support --- documentation/src/main/asciidoc/ch12.asciidoc | 52 +++++++++++++ .../localization/LocalizationTest.java | 75 +++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/localization/LocalizationTest.java diff --git a/documentation/src/main/asciidoc/ch12.asciidoc b/documentation/src/main/asciidoc/ch12.asciidoc index 6d6e205f68..6abbddc995 100644 --- a/documentation/src/main/asciidoc/ch12.asciidoc +++ b/documentation/src/main/asciidoc/ch12.asciidoc @@ -51,6 +51,9 @@ Note that when a package is part of the public API this is not necessarily true `org.hibernate.validator.spi.constraintdefinition`:: An SPI for registering additional constraint validators programmatically, see <>. +`org.hibernate.validator.spi.messageinterpolation`:: + An SPI that can be used to tweak the resolution of the locale when interpolating the constraint violation messages. See <>. + `org.hibernate.validator.spi.nodenameprovider`:: An SPI that can be used to alter how the names of properties will be resolved when the property path is constructed. See <>. @@ -443,6 +446,55 @@ error messages from other resource bundles than _ValidationMessages_ while still interpolation algorithm as defined by the specification. Refer to <> to learn how to make use of that SPI. +[[section-locale-resolver]] +=== Customizing the locale resolution + +[WARNING] +==== +These contracts are marked as `@Incubating` so they might be subject to change in the future. +==== + +Hibernate Validator provides several extension points to build a custom locale resolution strategy. +The resolved locale is used when interpolating the constraint violation messages. + +The default behavior of Hibernate Validator is to always use the system default locale (as obtained via `Locale.getDefault()`). +This might not be the desired behavior if, for example, you usually set your system locale to `en-US` but want your application to provide messages in French. + +The following example shows how to set the Hibernate Validator default locale to `fr-FR`: + +[[example-configure-default-locale]] +.Configure the default locale +==== +[source, JAVA, indent=0] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/localization/LocalizationTest.java[tags=default-locale] +---- +==== + +While this is already a nice improvement, in a fully internationalized application, this is not sufficient: +you need Hibernate Validator to select the locale depending on the user context. + +Hibernate Validator provides the `org.hibernate.validator.spi.messageinterpolation.LocaleResolver` SPI +which allows to fine-tune the resolution of the locale. +Typically, in a JAX-RS environment, you can resolve the locale to use from the `Accept-Language` HTTP header. + +In the following example, we use a hardcoded value but, for instance, in the case of a RESTEasy application, +you could extract the header from the `ResteasyContext`. + +[[example-locale-resolver]] +.Fine tune the locale used to interpolate the messages via a `LocaleResolver` +==== +[source, JAVA, indent=0] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/localization/LocalizationTest.java[tags=locale-resolver] +---- +==== + +[NOTE] +==== +When using the `LocaleResolver`, you have to define the list of supported locales via the `locales()` method. +==== + === Custom contexts The Jakarta Bean Validation specification offers at several points in its API the possibility to unwrap a diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/localization/LocalizationTest.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/localization/LocalizationTest.java new file mode 100644 index 0000000000..76b3edc7a6 --- /dev/null +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/localization/LocalizationTest.java @@ -0,0 +1,75 @@ +package org.hibernate.validator.referenceguide.chapter12.localization; + +import static org.junit.Assert.assertEquals; + +import java.util.List; +import java.util.Locale; +import java.util.Locale.LanguageRange; +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.constraints.AssertTrue; + +import org.hibernate.validator.HibernateValidator; +import org.hibernate.validator.spi.messageinterpolation.LocaleResolver; +import org.hibernate.validator.spi.messageinterpolation.LocaleResolverContext; +import org.junit.Test; + +public class LocalizationTest { + + @Test + public void changeDefaultLocale() { + // tag::default-locale[] + Validator validator = Validation.byProvider( HibernateValidator.class ) + .configure() + .defaultLocale( Locale.FRANCE ) + .buildValidatorFactory() + .getValidator(); + + Set> violations = validator.validate( new Bean() ); + assertEquals( "doit avoir la valeur vrai", violations.iterator().next().getMessage() ); + // end::default-locale[] + } + + @Test + public void localeResolver() { + // tag::locale-resolver[] + LocaleResolver localeResolver = new LocaleResolver() { + + @Override + public Locale resolve(LocaleResolverContext context) { + // get the locales supported by the client from the Accept-Language header + String acceptLanguageHeader = "it-IT;q=0.9,en-US;q=0.7"; + + List acceptedLanguages = LanguageRange.parse( acceptLanguageHeader ); + List resolvedLocales = Locale.filter( acceptedLanguages, context.getSupportedLocales() ); + + if ( resolvedLocales.size() > 0 ) { + return resolvedLocales.get( 0 ); + } + + return context.getDefaultLocale(); + } + }; + + Validator validator = Validation.byProvider( HibernateValidator.class ) + .configure() + .defaultLocale( Locale.FRANCE ) + .locales( Locale.FRANCE, Locale.ITALY, Locale.US ) + .localeResolver( localeResolver ) + .buildValidatorFactory() + .getValidator(); + + Set> violations = validator.validate( new Bean() ); + assertEquals( "deve essere true", violations.iterator().next().getMessage() ); + // end::locale-resolver[] + } + + private static class Bean { + + @AssertTrue + private boolean invalid = false; + } +} From 2ed6f0593a7319fc1eb6b3e5f7ac706700b9f483 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 14 Jan 2020 13:03:00 +0100 Subject: [PATCH 285/393] HV-1748 Remove preloadResourceBundles from PlatformResourceBundleLocator --- .../engine/AbstractConfigurationImpl.java | 8 ++--- .../AbstractMessageInterpolator.java | 5 ++-- .../AggregateResourceBundleLocator.java | 3 +- .../PlatformResourceBundleLocator.java | 29 +++++++------------ 4 files changed, 17 insertions(+), 28 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java index e1996ff504..7c5d580c95 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java @@ -576,7 +576,7 @@ public final ConstraintValidatorFactory getDefaultConstraintValidatorFactory() { public final ResourceBundleLocator getDefaultResourceBundleLocator() { if ( defaultResourceBundleLocator == null ) { defaultResourceBundleLocator = new PlatformResourceBundleLocator( - ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, preloadResourceBundles(), getAllSupportedLocales() ); + ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, preloadResourceBundles() ? getAllSupportedLocales() : Collections.emptySet() ); } return defaultResourceBundleLocator; @@ -726,14 +726,12 @@ private MessageInterpolator getDefaultMessageInterpolatorConfiguredWithClassLoad if ( externalClassLoader != null ) { PlatformResourceBundleLocator userResourceBundleLocator = new PlatformResourceBundleLocator( ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, - preloadResourceBundles(), - getAllSupportedLocales(), + preloadResourceBundles() ? getAllSupportedLocales() : Collections.emptySet(), externalClassLoader ); PlatformResourceBundleLocator contributorResourceBundleLocator = new PlatformResourceBundleLocator( ResourceBundleMessageInterpolator.CONTRIBUTOR_VALIDATION_MESSAGES, - preloadResourceBundles(), - getAllSupportedLocales(), + preloadResourceBundles() ? getAllSupportedLocales() : Collections.emptySet(), externalClassLoader, true ); diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java index c11da82c84..bbb7f8bd65 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java @@ -280,7 +280,7 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat if ( userResourceBundleLocator == null ) { this.userResourceBundleLocator = new PlatformResourceBundleLocator( USER_VALIDATION_MESSAGES, - preloadResourceBundles, allLocalesToInitialize ); + allLocalesToInitialize ); } else { this.userResourceBundleLocator = userResourceBundleLocator; @@ -289,7 +289,6 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat if ( contributorResourceBundleLocator == null ) { this.contributorResourceBundleLocator = new PlatformResourceBundleLocator( CONTRIBUTOR_VALIDATION_MESSAGES, - preloadResourceBundles, allLocalesToInitialize, null, true @@ -299,7 +298,7 @@ public AbstractMessageInterpolator(ResourceBundleLocator userResourceBundleLocat this.contributorResourceBundleLocator = contributorResourceBundleLocator; } - this.defaultResourceBundleLocator = new PlatformResourceBundleLocator( DEFAULT_VALIDATION_MESSAGES, preloadResourceBundles, allLocalesToInitialize ); + this.defaultResourceBundleLocator = new PlatformResourceBundleLocator( DEFAULT_VALIDATION_MESSAGES, allLocalesToInitialize ); this.cachingEnabled = cacheMessages; if ( cachingEnabled ) { diff --git a/engine/src/main/java/org/hibernate/validator/resourceloading/AggregateResourceBundleLocator.java b/engine/src/main/java/org/hibernate/validator/resourceloading/AggregateResourceBundleLocator.java index 225d84eb1c..dc2ec57957 100644 --- a/engine/src/main/java/org/hibernate/validator/resourceloading/AggregateResourceBundleLocator.java +++ b/engine/src/main/java/org/hibernate/validator/resourceloading/AggregateResourceBundleLocator.java @@ -151,7 +151,8 @@ public AggregateResourceBundleLocator(List bundleNames, List tmpBundleLocators = new ArrayList<>( bundleNames.size() ); for ( String bundleName : bundleNames ) { - tmpBundleLocators.add( new PlatformResourceBundleLocator( bundleName, preloadResourceBundles, localesToInitialize, classLoader ) ); + tmpBundleLocators + .add( new PlatformResourceBundleLocator( bundleName, preloadResourceBundles ? localesToInitialize : Collections.emptySet(), classLoader ) ); } this.resourceBundleLocators = CollectionHelper.toImmutableList( tmpBundleLocators ); } diff --git a/engine/src/main/java/org/hibernate/validator/resourceloading/PlatformResourceBundleLocator.java b/engine/src/main/java/org/hibernate/validator/resourceloading/PlatformResourceBundleLocator.java index e804fe8adc..b78b263ab3 100644 --- a/engine/src/main/java/org/hibernate/validator/resourceloading/PlatformResourceBundleLocator.java +++ b/engine/src/main/java/org/hibernate/validator/resourceloading/PlatformResourceBundleLocator.java @@ -43,6 +43,7 @@ * * @author Hardy Ferentschik * @author Gunnar Morling + * @author Guillaume Smet */ public class PlatformResourceBundleLocator implements ResourceBundleLocator { @@ -53,7 +54,6 @@ public class PlatformResourceBundleLocator implements ResourceBundleLocator { private final ClassLoader classLoader; private final boolean aggregate; - private final boolean preloadResourceBundles; @Immutable private final Map preloadedResourceBundles; @@ -63,7 +63,7 @@ public class PlatformResourceBundleLocator implements ResourceBundleLocator { * @param bundleName the name of the bundle to load */ public PlatformResourceBundleLocator(String bundleName) { - this( bundleName, false, Collections.emptySet() ); + this( bundleName, Collections.emptySet() ); } /** @@ -77,7 +77,7 @@ public PlatformResourceBundleLocator(String bundleName) { * @since 5.2 */ public PlatformResourceBundleLocator(String bundleName, ClassLoader classLoader) { - this( bundleName, false, Collections.emptySet(), classLoader ); + this( bundleName, Collections.emptySet(), classLoader ); } /** @@ -92,46 +92,42 @@ public PlatformResourceBundleLocator(String bundleName, ClassLoader classLoader) * @since 5.2 */ public PlatformResourceBundleLocator(String bundleName, ClassLoader classLoader, boolean aggregate) { - this( bundleName, false, Collections.emptySet(), classLoader, aggregate ); + this( bundleName, Collections.emptySet(), classLoader, aggregate ); } /** * Creates a new {@link PlatformResourceBundleLocator}. * * @param bundleName the name of the bundle to load - * @param preloadResourceBundles if resource bundles should be initialized when initializing the locator * @param localesToInitialize the set of locales to initialize at bootstrap * * @since 6.1.1 */ @Incubating - public PlatformResourceBundleLocator(String bundleName, boolean preloadResourceBundles, Set localesToInitialize) { - this( bundleName, preloadResourceBundles, localesToInitialize, null ); + public PlatformResourceBundleLocator(String bundleName, Set localesToInitialize) { + this( bundleName, localesToInitialize, null ); } /** * Creates a new {@link PlatformResourceBundleLocator}. * * @param bundleName the name of the bundle to load - * @param preloadResourceBundles if resource bundles should be initialized when initializing the locator * @param localesToInitialize the set of locales to initialize at bootstrap * @param classLoader the classloader to be used for loading the bundle. If {@code null}, the current thread context * classloader and finally Hibernate Validator's own classloader will be used for loading the specified * bundle. - * @param preloadResourceBundles if resource bundles should be initialized when initializing the locator * * @since 6.1.1 */ @Incubating - public PlatformResourceBundleLocator(String bundleName, boolean preloadResourceBundles, Set localesToInitialize, ClassLoader classLoader) { - this( bundleName, preloadResourceBundles, localesToInitialize, classLoader, false ); + public PlatformResourceBundleLocator(String bundleName, Set localesToInitialize, ClassLoader classLoader) { + this( bundleName, localesToInitialize, classLoader, false ); } /** * Creates a new {@link PlatformResourceBundleLocator}. * * @param bundleName the name of the bundle to load - * @param preloadResourceBundles if resource bundles should be initialized when initializing the locator * @param localesToInitialize the set of locales to initialize at bootstrap * @param classLoader the classloader to be used for loading the bundle. If {@code null}, the current thread context * classloader and finally Hibernate Validator's own classloader will be used for loading the specified @@ -142,7 +138,6 @@ public PlatformResourceBundleLocator(String bundleName, boolean preloadResourceB */ @Incubating public PlatformResourceBundleLocator(String bundleName, - boolean preloadResourceBundles, Set localesToInitialize, ClassLoader classLoader, boolean aggregate) { @@ -153,11 +148,7 @@ public PlatformResourceBundleLocator(String bundleName, this.aggregate = aggregate && RESOURCE_BUNDLE_CONTROL_INSTANTIABLE; - this.preloadResourceBundles = preloadResourceBundles; - - if ( preloadResourceBundles ) { - Contracts.assertNotEmpty( localesToInitialize, "localesToInitialize may not be empty if resource bundles have to be preloaded" ); - + if ( !localesToInitialize.isEmpty() ) { Map tmpPreloadedResourceBundles = CollectionHelper.newHashMap( localesToInitialize.size() ); for ( Locale localeToPreload : localesToInitialize ) { tmpPreloadedResourceBundles.put( localeToPreload, doGetResourceBundle( localeToPreload ) ); @@ -179,7 +170,7 @@ public PlatformResourceBundleLocator(String bundleName, */ @Override public ResourceBundle getResourceBundle(Locale locale) { - if ( preloadResourceBundles ) { + if ( !preloadedResourceBundles.isEmpty() ) { // we need to use containsKey() as the cached resource bundle can be null if ( preloadedResourceBundles.containsKey( locale ) ) { return preloadedResourceBundles.get( locale ); From 19d683887903d982507e302ca41489364f019d0d Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Wed, 15 Jan 2020 08:11:27 +0000 Subject: [PATCH 286/393] [Jenkins release job] README.md updated by release build 6.1.1.Final --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 977b7886d9..ee1e92bb36 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hibernate Validator -*Version: 6.1.0.Final - 25-10-2019* +*Version: 6.1.1.Final - 15-01-2020* ## What is it? @@ -35,7 +35,7 @@ Logging will delegate any log requests to that provider. org.hibernate.validator hibernate-validator - 6.1.0.Final + 6.1.1.Final You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. @@ -54,7 +54,7 @@ extension by adding the following dependency: org.hibernate.validator hibernate-validator-cdi - 6.1.0.Final + 6.1.1.Final * _hibernate-validator-annotation-processor-<version>.jar_ is an optional jar which can be integrated with your build From dc58ae1050d1ce3cfe985c1b79ce04ebb953d903 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Wed, 15 Jan 2020 08:11:28 +0000 Subject: [PATCH 287/393] [Jenkins release job] changelog.txt updated by release build 6.1.1.Final --- changelog.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/changelog.txt b/changelog.txt index 442ca8bf83..c554b2309e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,21 @@ Hibernate Validator Changelog ============================= +6.1.1.Final (15-01-2020) +------------------------- + +** Improvement + * HV-1750 - engine - Add debug log when expression factory has failed to load + * HV-1747 - engine - Allow overriding the message interpolator in PredefinedScopeValidatorFactory context + * HV-1744 - documentation - Use auto-expanding entries in the documentation TOC + +** New Feature + * HV-1749 - engine - Introduce a LocaleResolver SPI + * HV-1748 - engine - Improve localization support via Locale.LanguageRange + +** Task + * HV-1745 - tests - Bump Jackson test dependency to 2.10.1 + 6.1.0.Final (25-10-2019) ------------------------- From 83b6387536198a07e67108a0bd0e37de4c4e9479 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Wed, 15 Jan 2020 08:11:36 +0000 Subject: [PATCH 288/393] [Jenkins release job] Preparing release 6.1.1.Final --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index bc53a92a6d..eaa7b1f035 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1-SNAPSHOT + 6.1.1.Final ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index a84f213f07..4647ce044b 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1-SNAPSHOT + 6.1.1.Final ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index db2f0c498a..8b27861727 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1-SNAPSHOT + 6.1.1.Final ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index 283808852a..0c8cc92f45 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1-SNAPSHOT + 6.1.1.Final ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 80da806fba..c8f6011908 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1-SNAPSHOT + 6.1.1.Final ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index b20f6c015b..d48eb08e55 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1-SNAPSHOT + 6.1.1.Final ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 74dec81c99..01095c450b 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1-SNAPSHOT + 6.1.1.Final ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index b7a5093fd8..26699d632c 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1-SNAPSHOT + 6.1.1.Final 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 87b8b34cca..4700b1b214 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.1-SNAPSHOT + 6.1.1.Final ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 888b34bc8d..45346972b1 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.1-SNAPSHOT + 6.1.1.Final ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 38f0eb0529..20ea1f1afd 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.1-SNAPSHOT + 6.1.1.Final ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index 14fb8b0246..9677ea4d96 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1-SNAPSHOT + 6.1.1.Final ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index f862e203fc..485068031c 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1-SNAPSHOT + 6.1.1.Final ../pom.xml diff --git a/pom.xml b/pom.xml index d00e7e06ce..463169da62 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1-SNAPSHOT + 6.1.1.Final pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 5e34d4d0bb..20ff15ef7a 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.1-SNAPSHOT + 6.1.1.Final org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index 8f0f893f60..055814e1df 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.1-SNAPSHOT + 6.1.1.Final org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index 3af71ba584..253805dae5 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.1-SNAPSHOT + 6.1.1.Final org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index dda823ffb3..9f53cd89f4 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.1-SNAPSHOT + 6.1.1.Final org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 59c0224b5d..cc5c69915b 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1-SNAPSHOT + 6.1.1.Final hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 53d079d516..c702de4d1e 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1-SNAPSHOT + 6.1.1.Final ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index e86476ec26..e34f176535 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1-SNAPSHOT + 6.1.1.Final hibernate-validator-test-utils From 5bfb25f077e278245adc1673c51b1746c7534740 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Wed, 15 Jan 2020 08:15:53 +0000 Subject: [PATCH 289/393] [Jenkins release job] Preparing next development iteration --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index eaa7b1f035..7600ebba05 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1.Final + 6.1.2-SNAPSHOT ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 4647ce044b..9954323420 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1.Final + 6.1.2-SNAPSHOT ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index 8b27861727..c82469904f 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1.Final + 6.1.2-SNAPSHOT ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index 0c8cc92f45..0abe36b8e7 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1.Final + 6.1.2-SNAPSHOT ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index c8f6011908..530ba98133 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1.Final + 6.1.2-SNAPSHOT ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index d48eb08e55..e296798501 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1.Final + 6.1.2-SNAPSHOT ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 01095c450b..0dcf4f75fe 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1.Final + 6.1.2-SNAPSHOT ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index 26699d632c..0e3c3b4585 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1.Final + 6.1.2-SNAPSHOT 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 4700b1b214..3a92e9f6fc 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.1.Final + 6.1.2-SNAPSHOT ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 45346972b1..fab1a4e1b8 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.1.Final + 6.1.2-SNAPSHOT ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 20ea1f1afd..ce8a66ed3a 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.1.Final + 6.1.2-SNAPSHOT ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index 9677ea4d96..9a0eefe9e0 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1.Final + 6.1.2-SNAPSHOT ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index 485068031c..01a5ca5d65 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1.Final + 6.1.2-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 463169da62..37eeb25953 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1.Final + 6.1.2-SNAPSHOT pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 20ff15ef7a..97f8ce5d50 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.1.Final + 6.1.2-SNAPSHOT org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index 055814e1df..ad51dbd0b0 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.1.Final + 6.1.2-SNAPSHOT org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index 253805dae5..aa00be8d1a 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.1.Final + 6.1.2-SNAPSHOT org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index 9f53cd89f4..5267f3c9f2 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.1.Final + 6.1.2-SNAPSHOT org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index cc5c69915b..28526c27e5 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1.Final + 6.1.2-SNAPSHOT hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index c702de4d1e..84d4ded8ad 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1.Final + 6.1.2-SNAPSHOT ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index e34f176535..0d9622da4e 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.1.Final + 6.1.2-SNAPSHOT hibernate-validator-test-utils From 600137aaeb9c834f23d1e09bcc98e3dadbab2b6f Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 22 Jan 2020 17:21:40 +0100 Subject: [PATCH 290/393] HV-1753 Force Karaf and Pax-Exam to use https for Maven Central --- osgi/integrationtest/pom.xml | 3 +++ .../integrationtest/KarafFeaturesAreInstallableTest.java | 7 +++++++ .../osgi/integrationtest/OsgiIntegrationTest.java | 7 +++++++ pom.xml | 4 ++++ 4 files changed, 21 insertions(+) diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index fab1a4e1b8..3e96f58368 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -180,6 +180,9 @@ maven-surefire-plugin false + + ${mavencentral.repo.url} + diff --git a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/KarafFeaturesAreInstallableTest.java b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/KarafFeaturesAreInstallableTest.java index ff7b12dd2e..235b2cd904 100644 --- a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/KarafFeaturesAreInstallableTest.java +++ b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/KarafFeaturesAreInstallableTest.java @@ -67,6 +67,8 @@ public Option[] config() { .type( "xml" ) .versionAsInProject(); + String mavenCentralRepository = System.getProperty( "maven.mavencentral.repo.url" ); + return options( when( DEBUG ).useOptions( debugConfiguration( "5005", true ) ), when( JavaVersionUtil.getMajorVersion() >= 9 ).useOptions( JAVA_9.options() ), @@ -92,6 +94,11 @@ public Option[] config() { "featuresBoot", "system" ), + editConfigurationFilePut( // Erase the defaults: Maven Central uses HTTP by default... + "etc/org.ops4j.pax.url.mvn.cfg", + "org.ops4j.pax.url.mvn.repositories", + mavenCentralRepository + "@id=central" + ), systemProperty( "validatorRepositoryUrl" ).value( hibernateValidatorFeature.getURL() ) ); } diff --git a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java index e156542893..f599e54c11 100644 --- a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java +++ b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java @@ -90,6 +90,8 @@ public Option[] config() { .type( "xml" ) .versionAsInProject(); + String mavenCentralRepository = System.getProperty( "maven.mavencentral.repo.url" ); + return options( when( DEBUG ).useOptions( debugConfiguration( "5005", true ) ), when( JavaVersionUtil.getMajorVersion() >= 9 ).useOptions( JAVA_9.options() ), @@ -115,6 +117,11 @@ public Option[] config() { "featuresBoot", "system" ), + editConfigurationFilePut( // Erase the defaults: Maven Central uses HTTP by default... + "etc/org.ops4j.pax.url.mvn.cfg", + "org.ops4j.pax.url.mvn.repositories", + mavenCentralRepository + "@id=central" + ), features( hibernateValidatorFeature, "hibernate-validator", "hibernate-validator-jsoup", "hibernate-validator-joda-time", "hibernate-validator-javax-money", "hibernate-validator-groovy" ) ); diff --git a/pom.xml b/pom.xml index 37eeb25953..0c5b300d7d 100644 --- a/pom.xml +++ b/pom.xml @@ -244,6 +244,10 @@ jboss-snapshots-repository https://repository.jboss.org/nexus/content/repositories/snapshots/ + + + https://repo.maven.apache.org/maven2/ + . From 8ba2d97c842e024b2733693cbffe58c1bd944085 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 30 Jan 2020 23:13:21 +0100 Subject: [PATCH 291/393] HV-1756 Fix variable names in the newly added translations --- .../ValidationMessages_cs.properties | 8 +++--- .../ValidationMessages_da.properties | 12 ++++----- .../ValidationMessages_mn_MN.properties | 2 +- .../ValidationMessages_pt_BR.properties | 26 +++++++++---------- .../ValidationMessages_ro.properties | 18 ++++++------- .../ValidationMessages_tr.properties | 2 +- .../ValidationMessages_uk.properties | 2 +- 7 files changed, 35 insertions(+), 35 deletions(-) diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_cs.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_cs.properties index c8f282a168..2948c13ca8 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_cs.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_cs.properties @@ -1,7 +1,7 @@ javax.validation.constraints.AssertFalse.message = mus\u00ed m\u00edt hodnotu ne javax.validation.constraints.AssertTrue.message = mus\u00ed m\u00edt hodnotu ano -javax.validation.constraints.DecimalMax.message = mus\u00ed b\u00fdt men\u0161\u00ed ne\u017e ${inclusive == true ? 'nebo rovna hodnot\u011b ' : ''}{hodnota} -javax.validation.constraints.DecimalMin.message = mus\u00ed b\u00fdt v\u011bt\u0161\u00ed ne\u017e ${inclusive == true ? 'nebo rovna hodnot\u011b ' : ''}{hodnota} +javax.validation.constraints.DecimalMax.message = mus\u00ed b\u00fdt men\u0161\u00ed ne\u017e ${inclusive == true ? 'nebo rovna hodnot\u011b ' : ''}{value} +javax.validation.constraints.DecimalMin.message = mus\u00ed b\u00fdt v\u011bt\u0161\u00ed ne\u017e ${inclusive == true ? 'nebo rovna hodnot\u011b ' : ''}{value} javax.validation.constraints.Digits.message = \u010d\u00edseln\u00e1 hodnota mimo rozsah (o\u010dek\u00e1v\u00e1no: <{integer} \u010d\u00edslic>.<{fraction} \u010d\u00edslic>) javax.validation.constraints.Email.message = mus\u00ed m\u00edt spr\u00e1vn\u011b utvo\u0159enou e-mailovou adresu javax.validation.constraints.Future.message = mus\u00ed se jednat o datum v budoucnu @@ -22,8 +22,8 @@ javax.validation.constraints.PositiveOrZero.message = mus\u00ed b\u00fdt v\u011 javax.validation.constraints.Size.message = velikost mus\u00ed le\u017eet v rozsahu {min} a\u017e {max} org.hibernate.validator.constraints.CreditCardNumber.message = neplatn\u00e9 \u010d\u00edslo kreditn\u00ed karty -org.hibernate.validator.constraints.Currency.message = neplatn\u00e1 m\u011bna (mus\u00ed m\u00edt jednu z hodnot {hodnota}) -org.hibernate.validator.constraints.EAN.message = neplatn\u00fd \u010d\u00e1rov\u00fd k\u00f3d {typ} +org.hibernate.validator.constraints.Currency.message = neplatn\u00e1 m\u011bna (mus\u00ed m\u00edt jednu z hodnot {value}) +org.hibernate.validator.constraints.EAN.message = neplatn\u00fd \u010d\u00e1rov\u00fd k\u00f3d {type} org.hibernate.validator.constraints.Email.message = mus\u00ed m\u00edt spr\u00e1vn\u011b utvo\u0159enou e-mailovou adresu org.hibernate.validator.constraints.ISBN.message = neplatn\u00e9 ISBN org.hibernate.validator.constraints.Length.message = d\u00e9lka mus\u00ed le\u017eet v rozsahu {min} a\u017e {max} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_da.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_da.properties index c2eb592ead..0e537928f0 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_da.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_da.properties @@ -22,16 +22,16 @@ javax.validation.constraints.PositiveOrZero.message = skal v\u00e javax.validation.constraints.Size.message = st\u00f8rrelse skal v\u00e6re mellem {min} og {max} org.hibernate.validator.constraints.CreditCardNumber.message = ugyldigt kreditkortnummer -org.hibernate.validator.constraints.Currency.message = ugyldig valuta (skal v\u00e6re en af {v\u00e6rdi}) +org.hibernate.validator.constraints.Currency.message = ugyldig valuta (skal v\u00e6re en af {value}) org.hibernate.validator.constraints.EAN.message = ugyldig {type} stregkode org.hibernate.validator.constraints.Email.message = ikke en velformuleret email adresse org.hibernate.validator.constraints.ISBN.message = ugyldigt ISBN org.hibernate.validator.constraints.Length.message = l\u00e6ngden skal v\u00e6re mellem {min} og {max} org.hibernate.validator.constraints.CodePointLength.message = l\u00e6ngden skal v\u00e6re mellem {min} og {max} -org.hibernate.validator.constraints.LuhnCheck.message = kontrolcifferet for $ {validatedValue} er ugyldigt, Luhn Modulo 10 checksum mislykkedes -org.hibernate.validator.constraints.Mod10Check.message = kontrolcifferet for $ {validatedValue} er ugyldigt, Modulo 10 checksum mislykkedes -org.hibernate.validator.constraints.Mod11Check.message = kontrolcifferet for $ {validatedValue} er ugyldigt, Modulo 11 checksum mislykkedes -org.hibernate.validator.constraints.ModCheck.message = kontrolcifferet for $ {validatedValue} er ugyldigt, $ {modType} checksummet mislykkedes +org.hibernate.validator.constraints.LuhnCheck.message = kontrolcifferet for ${validatedValue} er ugyldigt, Luhn Modulo 10 checksum mislykkedes +org.hibernate.validator.constraints.Mod10Check.message = kontrolcifferet for ${validatedValue} er ugyldigt, Modulo 10 checksum mislykkedes +org.hibernate.validator.constraints.Mod11Check.message = kontrolcifferet for ${validatedValue} er ugyldigt, Modulo 11 checksum mislykkedes +org.hibernate.validator.constraints.ModCheck.message = kontrolcifferet for ${validatedValue} er ugyldigt, ${modType} checksummet mislykkedes org.hibernate.validator.constraints.NotBlank.message = m\u00e5 ikke v\u00e6re tomt org.hibernate.validator.constraints.NotEmpty.message = m\u00e5 ikke v\u00e6re tomt org.hibernate.validator.constraints.ParametersScriptAssert.message = script udtryk "{script}" evaluerede ikke til true @@ -50,4 +50,4 @@ org.hibernate.validator.constraints.pl.NIP.message = ugyldigt mo org.hibernate.validator.constraints.pl.PESEL.message = ugyldigt polsk nationalt identifikationsnummer (PESEL) org.hibernate.validator.constraints.time.DurationMax.message = skal v\u00e6re kortere end${inclusive == true ? ' eller lig med' : ''}${days == 0 ? '' : days == 1 ? ' 1 dag' : ' ' += days += ' dage'}${hours == 0 ? '' : hours == 1 ? ' 1 time' : ' ' += hours += ' timer'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minut' : ' ' += minutes += ' minutter'}${seconds == 0 ? '' : seconds == 1 ? ' 1 sekund' : ' ' += seconds += ' sekunder'}${millis == 0 ? '' : millis == 1 ? ' 1 millisekund' : ' ' += millis += ' millisekunder'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanosekund' : ' ' += nanos += ' nanosekunder'} -org.hibernate.validator.constraints.time.DurationMin.message = skal v\u00e6re l\u00e6ngere end${inclusive == true ? ' eller lig med' : ''}${days == 0 ? '' : days == 1 ? ' 1 dag' : ' ' += days += ' dage'}${hours == 0 ? '' : hours == 1 ? ' 1 time' : ' ' += hours += ' timer'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minut' : ' ' += minutes += ' minutter'}${seconds == 0 ? '' : seconds == 1 ? ' 1 sekund : ' ' += seconds += ' sekunder'}${millis == 0 ? '' : millis == 1 ? ' 1 millisekund' : ' ' += millis += ' millisekunder'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanosekund' : ' ' += nanos += ' nanosekunder'} +org.hibernate.validator.constraints.time.DurationMin.message = skal v\u00e6re l\u00e6ngere end${inclusive == true ? ' eller lig med' : ''}${days == 0 ? '' : days == 1 ? ' 1 dag' : ' ' += days += ' dage'}${hours == 0 ? '' : hours == 1 ? ' 1 time' : ' ' += hours += ' timer'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minut' : ' ' += minutes += ' minutter'}${seconds == 0 ? '' : seconds == 1 ? ' 1 sekund' : ' ' += seconds += ' sekunder'}${millis == 0 ? '' : millis == 1 ? ' 1 millisekund' : ' ' += millis += ' millisekunder'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanosekund' : ' ' += nanos += ' nanosekunder'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_mn_MN.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_mn_MN.properties index 657ba34b99..0bc5e39713 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_mn_MN.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_mn_MN.properties @@ -2,7 +2,7 @@ javax.validation.constraints.AssertFalse.message = \u0425\u0443\u0434\u0430\u043 javax.validation.constraints.AssertTrue.message = \u04AE\u043D\u044D\u043D \u0431\u0430\u0439\u0445 \u0451\u0441\u0442\u043E\u0439 javax.validation.constraints.DecimalMax.message = {value}-\u0430\u0430\u0441 \u0431\u0430\u0433\u0430 \u0431\u0443\u044E\u0443 \u0442\u044D\u043D\u0446\u04AF\u04AF \u0431\u0430\u0439\u0445 \u0451\u0441\u0442\u043E\u0439 javax.validation.constraints.DecimalMin.message = {value}-\u0430\u0430\u0441 \u0438\u0445 \u0431\u0443\u044E\u0443 \u0442\u044D\u043D\u0446\u04AF\u04AF \u0431\u0430\u0439\u0445 \u0451\u0441\u0442\u043E\u0439 -javax.validation.constraints.Digits.message = \u0422\u043E\u043E\u043D \u0445\u044F\u0437\u0433\u0430\u0430\u0440\u0430\u0430\u0441 \u0445\u044D\u0442\u044D\u0440\u0441\u044D\u043D \u0431\u0430\u0439\u043D\u0430 (<{integerDigits} digits>.<{fractionalDigits} digits> \u0445\u043E\u043E\u0440\u043E\u043D\u0434 \u0431\u0430\u0439\u043D\u0430) +javax.validation.constraints.Digits.message = \u0422\u043E\u043E\u043D \u0445\u044F\u0437\u0433\u0430\u0430\u0440\u0430\u0430\u0441 \u0445\u044D\u0442\u044D\u0440\u0441\u044D\u043D \u0431\u0430\u0439\u043D\u0430 (<{integer} digits>.<{fraction} digits> \u0445\u043E\u043E\u0440\u043E\u043D\u0434 \u0431\u0430\u0439\u043D\u0430) javax.validation.constraints.Email.message = \u0411\u0443\u0440\u0443\u0443 \u0438-\u043C\u044D\u0439\u043B \u0445\u0430\u044F\u0433 \u0431\u0430\u0439\u043D\u0430 javax.validation.constraints.Future.message = \u0418\u0440\u044D\u044D\u0434\u04AF\u0439\u0434 \u0431\u0430\u0439\u0445 \u0451\u0441\u0442\u043E\u0439 javax.validation.constraints.Max.message = {value}-\u0430\u0430\u0441 \u0431\u0430\u0433\u0430 \u0431\u0443\u044E\u0443 \u0442\u044D\u043D\u0446\u04AF\u04AF \u0431\u0430\u0439\u0445 \u0451\u0441\u0442\u043E\u0439 diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties index 6cf00dc834..73ef080fdf 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties @@ -1,13 +1,13 @@ javax.validation.constraints.AssertFalse.message = deve ser falso javax.validation.constraints.AssertTrue.message = deve ser verdadeiro -javax.validation.constraints.DecimalMax.message = deve ser menor que ${inclusive == true ? 'ou igual a ' : ''}{valor} -javax.validation.constraints.DecimalMin.message = deve ser maior que ${inclusive == true ? 'ou igual a ' : ''}{valor} -javax.validation.constraints.Digits.message = valor n\u00famerico fora do limite (<{inteiro} d\u00edgito>.<{fra\u00e7\u00e3o} d\u00edgitos> esperar) +javax.validation.constraints.DecimalMax.message = deve ser menor que ${inclusive == true ? 'ou igual a ' : ''}{value} +javax.validation.constraints.DecimalMin.message = deve ser maior que ${inclusive == true ? 'ou igual a ' : ''}{value} +javax.validation.constraints.Digits.message = valor n\u00famerico fora do limite (<{integer} d\u00edgito>.<{fraction} d\u00edgitos> esperar) javax.validation.constraints.Email.message = deve ser um endere\u00e7o de e-mail bem formado javax.validation.constraints.Future.message = deve ser uma data futura javax.validation.constraints.FutureOrPresent.message = deve ser uma data no presente ou no futuro -javax.validation.constraints.Max.message = deve ser menor que ou igual \u00e0 {valor} -javax.validation.constraints.Min.message = deve ser maior que ou igual \u00e0 {valor} +javax.validation.constraints.Max.message = deve ser menor que ou igual \u00e0 {value} +javax.validation.constraints.Min.message = deve ser maior que ou igual \u00e0 {value} javax.validation.constraints.Negative.message = deve ser menor que 0 javax.validation.constraints.NegativeOrZero.message = deve ser menor ou igual a 0 javax.validation.constraints.NotBlank.message = n\u00e3o deve estar em branco @@ -19,15 +19,15 @@ javax.validation.constraints.PastOrPresent.message = deve ser uma data no pass javax.validation.constraints.Pattern.message = deve corresponder a "{regexp}" javax.validation.constraints.Positive.message = deve ser maior que 0 javax.validation.constraints.PositiveOrZero.message = deve ser maior ou igual a 0 -javax.validation.constraints.Size.message = tamanho deve ser entre {m\u00edn} e {max} +javax.validation.constraints.Size.message = tamanho deve ser entre {min} e {max} org.hibernate.validator.constraints.CreditCardNumber.message = n\u00famero do cart\u00e3o de cr\u00e9dito inv\u00e1lido -org.hibernate.validator.constraints.Currency.message = moeda inv\u00e1lida (deve ser uma de {valor}) -org.hibernate.validator.constraints.EAN.message = c\u00f3digo de barras {tipo} inv\u00e1lido +org.hibernate.validator.constraints.Currency.message = moeda inv\u00e1lida (deve ser uma de {value}) +org.hibernate.validator.constraints.EAN.message = c\u00f3digo de barras {type} inv\u00e1lido org.hibernate.validator.constraints.Email.message = deve ser um endere\u00e7o de e-mail bem formado org.hibernate.validator.constraints.ISBN.message = ISBN inv\u00e1lido -org.hibernate.validator.constraints.Length.message = o comprimento deve ser entre {m\u00edn} e {m\u00e1x} -org.hibernate.validator.constraints.CodePointLength.message = o comprimento deve ser entre {m\u00edn} e {m\u00e1x} +org.hibernate.validator.constraints.Length.message = o comprimento deve ser entre {min} e {max} +org.hibernate.validator.constraints.CodePointLength.message = o comprimento deve ser entre {min} e {max} org.hibernate.validator.constraints.LuhnCheck.message = o d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o Luhn Modulo 10 com falha org.hibernate.validator.constraints.Mod10Check.message = o d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o Modulo 10 com falha org.hibernate.validator.constraints.Mod11Check.message = o d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o Modulo 11 com falha @@ -35,7 +35,7 @@ org.hibernate.validator.constraints.ModCheck.message = o d\u00edg org.hibernate.validator.constraints.NotBlank.message = n\u00e3o deve estar em branco org.hibernate.validator.constraints.NotEmpty.message = n\u00e3o deve estar vazio org.hibernate.validator.constraints.ParametersScriptAssert.message = express\u00e3o de script "{script}" n\u00e3o avaliou para true -org.hibernate.validator.constraints.Range.message = deve estar entre {m\u00edn} e {m\u00e1x} +org.hibernate.validator.constraints.Range.message = deve estar entre {min} e {max} org.hibernate.validator.constraints.SafeHtml.message = pode ter conte\u00fado HTML n\u00e3o seguro org.hibernate.validator.constraints.ScriptAssert.message = express\u00e3o de script "{script}" n\u00e3o avaliou para true org.hibernate.validator.constraints.UniqueElements.message = deve conter apenas elementos exclusivos @@ -49,5 +49,5 @@ org.hibernate.validator.constraints.pl.REGON.message = n\u00famer org.hibernate.validator.constraints.pl.NIP.message = n\u00famero de identifica\u00e7\u00e3o de VAT (NIP) inv\u00e1lido org.hibernate.validator.constraints.pl.PESEL.message = n\u00famero de identifica\u00e7\u00e3o nacional polonesa (PESEL) inv\u00e1lido -org.hibernate.validator.constraints.time.DurationMax.message = deve ser menor que${inclusive == true ? ' ou igual a' : ''}${dias == 0 ? '' : dias == 1 ? ' 1 dia' : ' ' += dias += ' dias'}${horas == 0 ? '' : horas == 1 ? ' 1 hora' : ' ' += horas += ' horas'}${minutos == 0 ? '' : minutos == 1 ? ' 1 minuto' : ' ' += minutos += ' minutos'}${segundos == 0 ? '' : segundos == 1 ? ' 1 segundo' : ' ' += segundos += ' segundos'}${miliss == 0 ? '' : miliss == 1 ? ' 1 mili' : ' ' += miliss += ' miliss'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} -org.hibernate.validator.constraints.time.DurationMin.message = deve ser maior que${inclusive == true ? ' ou igual a' : ''}${dias == 0 ? '' : dias == 1 ? ' 1 dia' : ' ' += dias += ' dias'}${horas == 0 ? '' : horas == 1 ? ' 1 hora' : ' ' += horas += ' horas'}${minutos == 0 ? '' : minutos == 1 ? ' 1 minuto' : ' ' += minutos += ' minutos'}${segundos == 0 ? '' : segundos == 1 ? ' 1 segundo' : ' ' += segundos += ' segundos'}${miliss == 0 ? '' : miliss == 1 ? ' 1 mili' : ' ' += miliss += ' miliss'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} +org.hibernate.validator.constraints.time.DurationMax.message = deve ser menor que${inclusive == true ? ' ou igual a' : ''}${days == 0 ? '' : days == 1 ? ' 1 dia' : ' ' += days += ' dias'}${hours == 0 ? '' : hours == 1 ? ' 1 hora' : ' ' += hours += ' horas'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minuto' : ' ' += minutes += ' minutos'}${seconds == 0 ? '' : seconds == 1 ? ' 1 segundo' : ' ' += seconds += ' segundos'}${millis == 0 ? '' : millis == 1 ? ' 1 mili' : ' ' += millis += ' miliss'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} +org.hibernate.validator.constraints.time.DurationMin.message = deve ser maior que${inclusive == true ? ' ou igual a' : ''}${days == 0 ? '' : days == 1 ? ' 1 dia' : ' ' += days += ' dias'}${hours == 0 ? '' : hours == 1 ? ' 1 hora' : ' ' += hours += ' horas'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minuto' : ' ' += minutes += ' minutos'}${seconds == 0 ? '' : seconds == 1 ? ' 1 segundo' : ' ' += seconds += ' segundos'}${millis == 0 ? '' : millis == 1 ? ' 1 mili' : ' ' += millis += ' miliss'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nano' : ' ' += nanos += ' nanos'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ro.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ro.properties index 453a27e153..d83fecb319 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ro.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ro.properties @@ -1,13 +1,13 @@ javax.validation.constraints.AssertFalse.message = trebuie s\u0103 fie false javax.validation.constraints.AssertTrue.message = trebuie s\u0103 fie true -javax.validation.constraints.DecimalMax.message = trebuie s\u0103 fie mai mic dec\u00e2t ${inclusiv == true ? 'sau egal cu ' : ''}{valoare} -javax.validation.constraints.DecimalMin.message = trebuie s\u0103 fie mai mare dec\u00e2t ${inclusiv == true ? 'sau egal cu ' : ''}{valoare} -javax.validation.constraints.Digits.message = valoare numeric\u0103 \u00een afara limitelor (<{num\u0103r \u00eentreg} digi\u0163i>.<{num\u0103r frac\u0163ionar} digi\u0163i> a\u015fteptat) +javax.validation.constraints.DecimalMax.message = trebuie s\u0103 fie mai mic dec\u00e2t ${inclusive == true ? 'sau egal cu ' : ''}{value} +javax.validation.constraints.DecimalMin.message = trebuie s\u0103 fie mai mare dec\u00e2t ${inclusive == true ? 'sau egal cu ' : ''}{value} +javax.validation.constraints.Digits.message = valoare numeric\u0103 \u00een afara limitelor (<{integer} digi\u0163i>.<{fraction} digi\u0163i> a\u015fteptat) javax.validation.constraints.Email.message = trebuie s\u0103 fie o adres\u0103 de e-mail cu format corect javax.validation.constraints.Future.message = trebuie s\u0103 fie o dat\u0103 viitoare javax.validation.constraints.FutureOrPresent.message = trebuie s\u0103 fie o dat\u0103 \u00een prezent sau \u00een viitor -javax.validation.constraints.Max.message = trebuie s\u0103 fie mai mic sau egal dec\u00e2t {valoare} -javax.validation.constraints.Min.message = trebuie s\u0103 fie mai mare sau egal dec\u00e2t {valoare} +javax.validation.constraints.Max.message = trebuie s\u0103 fie mai mic sau egal dec\u00e2t {value} +javax.validation.constraints.Min.message = trebuie s\u0103 fie mai mare sau egal dec\u00e2t {value} javax.validation.constraints.Negative.message = trebuie s\u0103 fie mai mic dec\u00e2t 0 javax.validation.constraints.NegativeOrZero.message = trebuie s\u0103 fie mai mic sau egal dec\u00e2t 0 javax.validation.constraints.NotBlank.message = nu trebuie s\u0103 fie blanc @@ -22,8 +22,8 @@ javax.validation.constraints.PositiveOrZero.message = trebuie s\u0103 fie mai m javax.validation.constraints.Size.message = dimensiunea trebuie s\u0103 fie \u00eentre {min} \u015fi {max} org.hibernate.validator.constraints.CreditCardNumber.message = num\u0103r invalid de card de credit -org.hibernate.validator.constraints.Currency.message = moned\u0103 invalid\u0103 trebuie s\u0103 fie una din {valoare}) -org.hibernate.validator.constraints.EAN.message = cod de bare {tip} invalid +org.hibernate.validator.constraints.Currency.message = moned\u0103 invalid\u0103 trebuie s\u0103 fie una din {value}) +org.hibernate.validator.constraints.EAN.message = cod de bare {type} invalid org.hibernate.validator.constraints.Email.message = trebuie s\u0103 fie o adres\u0103 de e-mail cu format corect org.hibernate.validator.constraints.ISBN.message = ISBN invalid org.hibernate.validator.constraints.Length.message = lungimea trebuie s\u0103 fie \u00eentre {min} \u015fi {max} @@ -49,5 +49,5 @@ org.hibernate.validator.constraints.pl.REGON.message = num\u0103r org.hibernate.validator.constraints.pl.NIP.message = num\u0103r invalid de identificare VAT (NIP) org.hibernate.validator.constraints.pl.PESEL.message = num\u0103r invalid de identificare na\u0163ional polonez (PESEL) -org.hibernate.validator.constraints.time.DurationMax.message = trebuie s\u0103 fie mai scurt dec\u00e2t${inclusiv == true ? ' sau egal cu' : ''}${zile == 0 ? '' : zile == 1 ? ' 1 zi' : ' ' += zile += ' zile'}${ore == 0 ? '' : ore == 1 ? ' 1 or\u0103' : ' ' += ore += ' ore'}${minute == 0 ? '' : minute == 1 ? ' 1 minut' : ' ' += minute += ' minute'}${secunde == 0 ? '' : secunde == 1 ? ' 1 secund\u0103' : ' ' += secunde += ' secunde'}${milisecunde == 0 ? '' : milisecunde == 1 ? ' 1 milisecund\u0103' : ' ' += milisecunde += ' milisecunde'}${nanosecunde == 0 ? '' : nanosecunde == 1 ? ' 1 nanosecund\u0103' : ' ' += nanosecunde += ' nanosecunde'} -org.hibernate.validator.constraints.time.DurationMin.message = trebuie s\u0103 fie mai lung dec\u00e2t${inclusiv == true ? ' sau egal cu' : ''}${zile == 0 ? '' : zile == 1 ? ' 1 zi' : ' ' += zile += ' zile'}${ore == 0 ? '' : ore == 1 ? ' 1 or\u0103' : ' ' += ore += ' ore'}${minute == 0 ? '' : minute == 1 ? ' 1 minut' : ' ' += minute += ' minute'}${secunde == 0 ? '' : secunde == 1 ? ' 1 secund\u0103' : ' ' += secunde += ' secunde'}${milisecunde == 0 ? '' : milisecunde == 1 ? ' 1 milisecund\u0103' : ' ' += milisecunde += ' milisecunde'}${nanosecunde == 0 ? '' : nanosecunde == 1 ? ' 1 nanosecund\u0103' : ' ' += nanosecunde += ' nanosecunde'} +org.hibernate.validator.constraints.time.DurationMax.message = trebuie s\u0103 fie mai scurt dec\u00e2t${inclusive == true ? ' sau egal cu' : ''}${days == 0 ? '' : days == 1 ? ' 1 zi' : ' ' += days += ' zile'}${hours == 0 ? '' : hours == 1 ? ' 1 or\u0103' : ' ' += hours += ' ore'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minut' : ' ' += minutes += ' minute'}${seconds == 0 ? '' : seconds == 1 ? ' 1 secund\u0103' : ' ' += seconds += ' secunde'}${millis == 0 ? '' : millis == 1 ? ' 1 milisecund\u0103' : ' ' += millis += ' milisecunde'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanosecund\u0103' : ' ' += nanos += ' nanosecunde'} +org.hibernate.validator.constraints.time.DurationMin.message = trebuie s\u0103 fie mai lung dec\u00e2t${inclusive == true ? ' sau egal cu' : ''}${days == 0 ? '' : days == 1 ? ' 1 zi' : ' ' += days += ' zile'}${hours == 0 ? '' : hours == 1 ? ' 1 or\u0103' : ' ' += hours += ' ore'}${minutes == 0 ? '' : minutes == 1 ? ' 1 minut' : ' ' += minutes += ' minute'}${seconds == 0 ? '' : seconds == 1 ? ' 1 secund\u0103' : ' ' += seconds += ' secunde'}${millis == 0 ? '' : millis == 1 ? ' 1 milisecund\u0103' : ' ' += millis += ' milisecunde'}${nanos == 0 ? '' : nanos == 1 ? ' 1 nanosecund\u0103' : ' ' += nanos += ' nanosecunde'} diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_tr.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_tr.properties index 37e7223d66..9b7691e11d 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_tr.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_tr.properties @@ -2,7 +2,7 @@ javax.validation.constraints.AssertFalse.message = teyit ba\u015Far\u0131s\u0131 javax.validation.constraints.AssertTrue.message = teyit ba\u015Far\u0131s\u0131z javax.validation.constraints.DecimalMax.message = '{value}' de\u011Ferinden k\u00FC\u00E7\u00FCk yada e\u015Fit olmal\u0131 javax.validation.constraints.DecimalMin.message = '{value}' de\u011Ferinden b\u00FCy\u00FCk yada e\u015Fit olmal\u0131 -javax.validation.constraints.Digits.message = s\u0131n\u0131rlar\u0131n d\u0131\u015F\u0131nda say\u0131sal de\u011Fer (beklenen <{integerDigits} basamak>.<{fractionalDigits} basamak>) +javax.validation.constraints.Digits.message = s\u0131n\u0131rlar\u0131n d\u0131\u015F\u0131nda say\u0131sal de\u011Fer (beklenen <{integer} basamak>.<{fraction} basamak>) javax.validation.constraints.Email.message = d\u00FCzg\u00FCn bi\u00E7imli bir e-posta adresi de\u011Fil! javax.validation.constraints.Future.message = ileri bir tarih olmal\u0131 javax.validation.constraints.Max.message = '{value}' de\u011Ferinden k\u00FC\u00E7\u00FCk yada e\u015Fit olmal\u0131 diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_uk.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_uk.properties index fb4e559c68..cf201e4e33 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_uk.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_uk.properties @@ -50,4 +50,4 @@ org.hibernate.validator.constraints.pl.NIP.message = \u043d\u0435\u043f\u04 org.hibernate.validator.constraints.pl.PESEL.message = \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0438\u0439 \u043f\u043e\u043b\u044c\u0441\u043a\u0438\u0439 \u043d\u0430\u0446\u0456\u043e\u043d\u0430\u043b\u044c\u043d\u0438\u0439 \u0456\u0434\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u0439\u043d\u0438\u0439 \u043d\u043e\u043c\u0435\u0440 (PESEL) org.hibernate.validator.constraints.time.DurationMax.message = \u043c\u0430\u0454 \u0431\u0443\u0442\u0438 \u043a\u043e\u0440\u043e\u0442\u0448\u0438\u0439${inclusive == true ? ' \u0430\u0431\u043e \u0440\u0456\u0432\u043d\u0438\u0439' : ''} \u0437\u0430${days == 0 ? '' : days == 1 ? ' 1 \u0434\u0435\u043d\u044c' : ' ' += days += ' \u0434\u043d\u0456\u0432'}${hours == 0 ? '' : hours == 1 ? ' 1 \u0433\u043e\u0434\u0438\u043d\u0430' : ' ' += hours += ' \u0433\u043e\u0434\u0438\u043d'}${minutes == 0 ? '' : minutes == 1 ? ' 1 \u0445\u0432\u0438\u043b\u0438\u043d\u0430' : ' ' += minutes += ' \u0445\u0432\u0438\u043b\u0438\u043d'}${seconds == 0 ? '' : seconds == 1 ? ' 1 \u0441\u0435\u043a\u0443\u043d\u0434\u0430' : ' ' += seconds += ' \u0441\u0435\u043a\u0443\u043d\u0434'}${millis == 0 ? '' : millis == 1 ? ' 1 \u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434\u0430' : ' ' += millis += ' \u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434'}${nanos == 0 ? '' : nanos == 1 ? ' 1 \u043d\u0430\u043d\u043e\u0441\u0435\u043a\u0443\u043d\u0434\u0430' : ' ' += nanos += ' \u043d\u0430\u043d\u043e\u0441\u0435\u043a\u0443\u043d\u0434'} -org.hibernate.validator.constraints.time.DurationMin.message = \u043c\u0430\u0454 \u0431\u0443\u0442\u0438 \u0434\u043e\u0432\u0448\u0438\u0439{inclusive == true ? ' \u0430\u0431\u043e \u0440\u0456\u0432\u043d\u0438\u0439' : ''} \u0437\u0430${days == 0 ? '' : days == 1 ? ' 1 \u0434\u0435\u043d\u044c' : ' ' += days += ' \u0434\u043d\u0456\u0432'}${hours == 0 ? '' : hours == 1 ? ' 1 \u0433\u043e\u0434\u0438\u043d\u0430' : ' ' += hours += ' \u0433\u043e\u0434\u0438\u043d'}${minutes == 0 ? '' : minutes == 1 ? ' 1 \u0445\u0432\u0438\u043b\u0438\u043d\u0430' : ' ' += minutes += ' \u0445\u0432\u0438\u043b\u0438\u043d'}${seconds == 0 ? '' : seconds == 1 ? ' 1 \u0441\u0435\u043a\u0443\u043d\u0434\u0430' : ' ' += seconds += ' \u0441\u0435\u043a\u0443\u043d\u0434'}${millis == 0 ? '' : millis == 1 ? ' 1 \u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434\u0430' : ' ' += millis += ' \u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434'}${nanos == 0 ? '' : nanos == 1 ? ' 1 \u043d\u0430\u043d\u043e\u0441\u0435\u043a\u0443\u043d\u0434\u0430' : ' ' += nanos += ' \u043d\u0430\u043d\u043e\u0441\u0435\u043a\u0443\u043d\u0434'} +org.hibernate.validator.constraints.time.DurationMin.message = \u043c\u0430\u0454 \u0431\u0443\u0442\u0438 \u0434\u043e\u0432\u0448\u0438\u0439${inclusive == true ? ' \u0430\u0431\u043e \u0440\u0456\u0432\u043d\u0438\u0439' : ''} \u0437\u0430${days == 0 ? '' : days == 1 ? ' 1 \u0434\u0435\u043d\u044c' : ' ' += days += ' \u0434\u043d\u0456\u0432'}${hours == 0 ? '' : hours == 1 ? ' 1 \u0433\u043e\u0434\u0438\u043d\u0430' : ' ' += hours += ' \u0433\u043e\u0434\u0438\u043d'}${minutes == 0 ? '' : minutes == 1 ? ' 1 \u0445\u0432\u0438\u043b\u0438\u043d\u0430' : ' ' += minutes += ' \u0445\u0432\u0438\u043b\u0438\u043d'}${seconds == 0 ? '' : seconds == 1 ? ' 1 \u0441\u0435\u043a\u0443\u043d\u0434\u0430' : ' ' += seconds += ' \u0441\u0435\u043a\u0443\u043d\u0434'}${millis == 0 ? '' : millis == 1 ? ' 1 \u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434\u0430' : ' ' += millis += ' \u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434'}${nanos == 0 ? '' : nanos == 1 ? ' 1 \u043d\u0430\u043d\u043e\u0441\u0435\u043a\u0443\u043d\u0434\u0430' : ' ' += nanos += ' \u043d\u0430\u043d\u043e\u0441\u0435\u043a\u0443\u043d\u0434'} From b833b110a8b4006ddaa3a70f1c46c53d55cd0d12 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 31 Jan 2020 11:43:06 +0100 Subject: [PATCH 292/393] HV-1756 Be less verbose in test logging --- .../java/org/hibernate/validator/ValidationMessages.java | 4 ++-- engine/src/test/resources/log4j.properties | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/engine/src/test/java/org/hibernate/validator/ValidationMessages.java b/engine/src/test/java/org/hibernate/validator/ValidationMessages.java index 8da94713cd..91281345d5 100644 --- a/engine/src/test/java/org/hibernate/validator/ValidationMessages.java +++ b/engine/src/test/java/org/hibernate/validator/ValidationMessages.java @@ -34,9 +34,9 @@ public class ValidationMessages extends ResourceBundle { public ValidationMessages() throws Exception { - log.info( "For test purposes are we proxying the built-in messages!" ); + log.debug( "For test purposes we are proxying the built-in messages!" ); addTestPropertiesToBundle(); - log.infof( "Adding the following properties to default properties %s", messages ); + log.debugf( "Adding the following properties to default properties %s", messages ); loadDefaultValidationProperties(); } diff --git a/engine/src/test/resources/log4j.properties b/engine/src/test/resources/log4j.properties index 6e7112b594..78c71c612a 100644 --- a/engine/src/test/resources/log4j.properties +++ b/engine/src/test/resources/log4j.properties @@ -18,9 +18,9 @@ log4j.appender.socket.locationInfo=true ### set log levels - for more verbose logging change 'info' to 'debug' ### -log4j.rootLogger=debug, stdout +log4j.rootLogger=info, stdout -log4j.logger.org.hibernate.validator.internal.engine.ValidatorImpl=trace +#log4j.logger.org.hibernate.validator.internal.engine.ValidatorImpl=trace #log4j.logger.org.hibernate.validator.internal.engine.resolver.JPATraversableResolver=trace #log4j.logger.org.hibernate.validatorengine.ConstraintTree=trace -log4j.logger.org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator=info +#log4j.logger.org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator=info From 3cc3d5c23db86024e6d06a69a1e0425a2aaf553d Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 31 Jan 2020 11:43:19 +0100 Subject: [PATCH 293/393] HV-1756 Add a test validating all the messages are properly interpolated --- .../MessagePropertiesTest.java | 359 ++++++++++++++++++ 1 file changed, 359 insertions(+) create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/MessagePropertiesTest.java diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/MessagePropertiesTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/MessagePropertiesTest.java new file mode 100644 index 0000000000..5886f25f2e --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/MessagePropertiesTest.java @@ -0,0 +1,359 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.constraintvalidators; + +import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; + +import java.math.BigDecimal; +import java.time.Duration; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +import javax.money.MonetaryAmount; +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.constraints.AssertFalse; +import javax.validation.constraints.AssertTrue; +import javax.validation.constraints.DecimalMax; +import javax.validation.constraints.DecimalMin; +import javax.validation.constraints.Digits; +import javax.validation.constraints.Email; +import javax.validation.constraints.Future; +import javax.validation.constraints.FutureOrPresent; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.Negative; +import javax.validation.constraints.NegativeOrZero; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Null; +import javax.validation.constraints.Past; +import javax.validation.constraints.PastOrPresent; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Positive; +import javax.validation.constraints.PositiveOrZero; +import javax.validation.constraints.Size; + +import org.hibernate.validator.HibernateValidator; +import org.hibernate.validator.constraints.CodePointLength; +import org.hibernate.validator.constraints.CreditCardNumber; +import org.hibernate.validator.constraints.Currency; +import org.hibernate.validator.constraints.EAN; +import org.hibernate.validator.constraints.ISBN; +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.LuhnCheck; +import org.hibernate.validator.constraints.Mod10Check; +import org.hibernate.validator.constraints.Mod11Check; +import org.hibernate.validator.constraints.ModCheck; +import org.hibernate.validator.constraints.ParameterScriptAssert; +import org.hibernate.validator.constraints.Range; +import org.hibernate.validator.constraints.SafeHtml; +import org.hibernate.validator.constraints.ScriptAssert; +import org.hibernate.validator.constraints.URL; +import org.hibernate.validator.constraints.UniqueElements; +import org.hibernate.validator.constraints.br.CNPJ; +import org.hibernate.validator.constraints.br.CPF; +import org.hibernate.validator.constraints.br.TituloEleitoral; +import org.hibernate.validator.constraints.pl.NIP; +import org.hibernate.validator.constraints.pl.PESEL; +import org.hibernate.validator.constraints.pl.REGON; +import org.hibernate.validator.constraints.time.DurationMax; +import org.hibernate.validator.constraints.time.DurationMin; +import org.hibernate.validator.testutil.ConstraintViolationAssert; +import org.javamoney.moneta.Money; +import org.testng.annotations.Test; + +/** + * Test that all the messages of all the constraints are properly interpolated for all the supported locales. + * + * @author Guillaume Smet + */ +@SuppressWarnings("deprecation") +public class MessagePropertiesTest { + + private static final List ALL_SUPPORTED_LOCALES = Arrays.asList( + Locale.forLanguageTag( "ar" ), + Locale.forLanguageTag( "cs" ), + Locale.forLanguageTag( "da" ), + Locale.forLanguageTag( "de" ), + Locale.forLanguageTag( "en" ), + Locale.forLanguageTag( "es" ), + Locale.forLanguageTag( "fa" ), + Locale.forLanguageTag( "fr" ), + Locale.forLanguageTag( "hu" ), + Locale.forLanguageTag( "it" ), + Locale.forLanguageTag( "ja" ), + Locale.forLanguageTag( "ko" ), + Locale.forLanguageTag( "mn-MN" ), + Locale.forLanguageTag( "nl" ), + Locale.forLanguageTag( "pl" ), + Locale.forLanguageTag( "pt-BR" ), + Locale.forLanguageTag( "ro" ), + Locale.forLanguageTag( "ru" ), + Locale.forLanguageTag( "sk" ), + Locale.forLanguageTag( "tr" ), + Locale.forLanguageTag( "uk" ), + Locale.forLanguageTag( "zh-CN" ), + Locale.forLanguageTag( "zh-TW" ), + Locale.forLanguageTag( "zh" ) + ); + + @Test + public void testMessageProperties() throws NoSuchMethodException, SecurityException { + List invalidMessages = new ArrayList<>(); + + for ( Locale locale : ALL_SUPPORTED_LOCALES ) { + Validator validator = Validation.byProvider( HibernateValidator.class ) + .configure() + .defaultLocale( locale ) + .buildValidatorFactory() + .getValidator(); + + Set> violations = validator.validate( new Bean() ); + + ConstraintViolationAssert.assertThat( violations ) + .containsOnlyViolations( + violationOf( AssertFalse.class ), + violationOf( AssertTrue.class ), + violationOf( DecimalMax.class ), + violationOf( DecimalMin.class ), + violationOf( Digits.class ), + violationOf( Email.class ), + violationOf( Future.class ), + violationOf( FutureOrPresent.class ), + violationOf( Max.class ), + violationOf( Min.class ), + violationOf( Negative.class ), + violationOf( NegativeOrZero.class ), + violationOf( NotBlank.class ), + violationOf( NotEmpty.class ), + violationOf( NotNull.class ), + violationOf( Null.class ), + violationOf( Past.class ), + violationOf( PastOrPresent.class ), + violationOf( Pattern.class ), + violationOf( Positive.class ), + violationOf( PositiveOrZero.class ), + violationOf( Size.class ), + violationOf( CreditCardNumber.class ), + violationOf( Currency.class ), + violationOf( EAN.class ), + violationOf( org.hibernate.validator.constraints.Email.class ), + violationOf( ISBN.class ), + violationOf( Length.class ), + violationOf( CodePointLength.class ), + violationOf( LuhnCheck.class ), + violationOf( Mod10Check.class ), + violationOf( Mod11Check.class ), + violationOf( ModCheck.class ), + violationOf( org.hibernate.validator.constraints.NotBlank.class ), + violationOf( org.hibernate.validator.constraints.NotEmpty.class ), + violationOf( Range.class ), + violationOf( SafeHtml.class ), + violationOf( UniqueElements.class ), + violationOf( URL.class ), + violationOf( CNPJ.class ), + violationOf( CPF.class ), + violationOf( TituloEleitoral.class ), + violationOf( REGON.class ), + violationOf( NIP.class ), + violationOf( PESEL.class ), + violationOf( DurationMax.class ), + violationOf( DurationMin.class ), + violationOf( ScriptAssert.class ) + ); + + collectInvalidMessages( locale, invalidMessages, violations ); + + Set> parameterScriptAssertBeanViolations = validator.forExecutables().validateParameters( + new ParameterScriptAssertBean(), ParameterScriptAssertBean.class.getDeclaredMethod( "doTest", boolean.class ), new Object[]{ false } ); + + ConstraintViolationAssert.assertThat( parameterScriptAssertBeanViolations ) + .containsOnlyViolations( + violationOf( ParameterScriptAssert.class ) ); + + collectInvalidMessages( locale, invalidMessages, parameterScriptAssertBeanViolations ); + } + + if ( !invalidMessages.isEmpty() ) { + throw new IllegalStateException( "Some messages are invalid:\n\t- " + String.join( "\n\t- ", invalidMessages ) + "\n" ); + } + } + + private void collectInvalidMessages(Locale locale, List invalidMessages, Set> violations) { + for ( ConstraintViolation violation : violations ) { + if ( violation.getMessage().contains( "{" ) ) { + invalidMessages.add( + "Message for constraint " + violation.getConstraintDescriptor().getAnnotation().annotationType() + " and locale " + locale + + " contains a curly brace: " + violation.getMessage() ); + } + } + } + + @ScriptAssert(lang = "groovy", script = "_this.scriptAssert") + private static class Bean { + + @AssertFalse + private boolean assertFalse = true; + + @AssertTrue + private boolean assertTrue = false; + + @DecimalMax("3") + private double decimalMax = 4; + + @DecimalMin("3") + private double decimalMin = 2; + + @Digits(integer = 1, fraction = 3) + private BigDecimal digits = BigDecimal.valueOf( 13333.3333f ); + + @Email + private String email = "invalid"; + + @Future + private LocalDate future = LocalDate.of( 2010, 10, 4 ); + + @FutureOrPresent + private LocalDate futureOrPresent = LocalDate.of( 2010, 10, 4 ); + + @Max(4) + private int max = 6; + + @Min(4) + private int min = 2; + + @Negative + private int negative = 4; + + @NegativeOrZero + private int negativeOrZero = 4; + + @NotBlank + private String notBlank = ""; + + @NotEmpty + private List notEmpty = Collections.emptyList(); + + @NotNull + private String notNull = null; + + @Null + private String nullConstraint = "not null"; + + @Past + private LocalDate past = LocalDate.of( 2890, 10, 4 ); + + @PastOrPresent + private LocalDate pastOrPresent = LocalDate.of( 2890, 10, 4 ); + + @Pattern(regexp = "[0-9]+") + private String pattern = "invalid"; + + @Positive + private int positive = -4; + + @PositiveOrZero + private int positiveOrZero = -4; + + @Size(min = 2, max = 4) + private String size = "666666"; + + @CreditCardNumber + private String creditCardNumber = "invalid"; + + @Currency("EUR") + private MonetaryAmount currency = Money.of( 1000f, "USD" ); + + @EAN + private String ean = "invalid"; + + @org.hibernate.validator.constraints.Email + private String hvEmail = "invalid"; + + @ISBN + private String isbn = "invalid"; + + @Length(min = 2, max = 4) + private String length = "666666"; + + @CodePointLength(min = 2, max = 4) + private String codePointLength = "666666"; + + @LuhnCheck + private String luhnCheck = "4"; + + @Mod10Check + private String mod10Check = "4"; + + @Mod11Check + private String mod11Check = "4"; + + @ModCheck(multiplier = 2, modType = ModCheck.ModType.MOD10) + private String modCheck = "4"; + + @org.hibernate.validator.constraints.NotBlank + private String hvNotBlank = ""; + + @org.hibernate.validator.constraints.NotEmpty + private List hvNotEmpty = Collections.emptyList(); + + @Range(min = 2, max = 4) + private int range = 6; + + @SafeHtml + private String safeHtml = ""; + + @UniqueElements + private List uniqueElements = Arrays.asList( "a", "a" ); + + @URL + private String url = "invalid"; + + @CNPJ + private String cnpj = "invalid"; + + @CPF + private String cpf = "invalid"; + + @TituloEleitoral + private String tituloEleitoral = "invalid"; + + @REGON + private String regon = "invalid"; + + @NIP + private String nip = "invalid"; + + @PESEL + private String pesel = "invalid"; + + @DurationMax(days = 4, hours = 4, minutes = 4, millis = 4, nanos = 4) + private Duration durationMax = Duration.ofDays( 8 ); + + @DurationMin(days = 4, hours = 4, minutes = 4, millis = 4, nanos = 4) + private Duration durationMin = Duration.ofDays( 2 ); + + @SuppressWarnings("unused") + private boolean scriptAssert = false; + } + + private static class ParameterScriptAssertBean { + + @ParameterScriptAssert(lang = "groovy", script = "test") + public boolean doTest(boolean test) { + return test; + } + } +} From a3a6738b54a5fa789bd7a38911c20aa2d89da10a Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 31 Jan 2020 11:23:12 +0000 Subject: [PATCH 294/393] [Jenkins release job] README.md updated by release build 6.1.2.Final --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ee1e92bb36..ab0cabbb14 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hibernate Validator -*Version: 6.1.1.Final - 15-01-2020* +*Version: 6.1.2.Final - 31-01-2020* ## What is it? @@ -35,7 +35,7 @@ Logging will delegate any log requests to that provider. org.hibernate.validator hibernate-validator - 6.1.1.Final + 6.1.2.Final You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. @@ -54,7 +54,7 @@ extension by adding the following dependency: org.hibernate.validator hibernate-validator-cdi - 6.1.1.Final + 6.1.2.Final * _hibernate-validator-annotation-processor-<version>.jar_ is an optional jar which can be integrated with your build From 587528f6ba5818f70feb1a671c20bfd3fac28018 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 31 Jan 2020 11:23:13 +0000 Subject: [PATCH 295/393] [Jenkins release job] changelog.txt updated by release build 6.1.2.Final --- changelog.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/changelog.txt b/changelog.txt index c554b2309e..c9510ff45d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,15 @@ Hibernate Validator Changelog ============================= +6.1.2.Final (31-01-2020) +------------------------- + +** Bug + * HV-1756 - translations - Incorrect variables in the newly added translations + +** Task + * HV-1753 - tests - Force Pax-Exam and Karaf to use Maven Central repository with SSL enabled + 6.1.1.Final (15-01-2020) ------------------------- From 334e271992ae6c3cb649fe3ea32bd6dd38c02685 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 31 Jan 2020 11:23:19 +0000 Subject: [PATCH 296/393] [Jenkins release job] Preparing release 6.1.2.Final --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 7600ebba05..ecc48bbcaf 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2-SNAPSHOT + 6.1.2.Final ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 9954323420..367261bfdb 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2-SNAPSHOT + 6.1.2.Final ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index c82469904f..0d0ba20cea 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2-SNAPSHOT + 6.1.2.Final ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index 0abe36b8e7..3479001345 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2-SNAPSHOT + 6.1.2.Final ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 530ba98133..df6f78914b 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2-SNAPSHOT + 6.1.2.Final ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index e296798501..e942487c84 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2-SNAPSHOT + 6.1.2.Final ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 0dcf4f75fe..8c2cc64e7c 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2-SNAPSHOT + 6.1.2.Final ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index 0e3c3b4585..11a2268ae1 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2-SNAPSHOT + 6.1.2.Final 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 3a92e9f6fc..da7695bbb6 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.2-SNAPSHOT + 6.1.2.Final ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 3e96f58368..91e4e34872 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.2-SNAPSHOT + 6.1.2.Final ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index ce8a66ed3a..e3dc2934cf 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.2-SNAPSHOT + 6.1.2.Final ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index 9a0eefe9e0..e52b9996b9 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2-SNAPSHOT + 6.1.2.Final ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index 01a5ca5d65..b94c4bc562 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2-SNAPSHOT + 6.1.2.Final ../pom.xml diff --git a/pom.xml b/pom.xml index 0c5b300d7d..1f83df8189 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2-SNAPSHOT + 6.1.2.Final pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 97f8ce5d50..e2c442ddbb 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.2-SNAPSHOT + 6.1.2.Final org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index ad51dbd0b0..02d8ebe636 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.2-SNAPSHOT + 6.1.2.Final org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index aa00be8d1a..c7f675c0d3 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.2-SNAPSHOT + 6.1.2.Final org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index 5267f3c9f2..b135418e0b 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.2-SNAPSHOT + 6.1.2.Final org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 28526c27e5..e7e10facc5 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2-SNAPSHOT + 6.1.2.Final hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 84d4ded8ad..78a1e3b0b5 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2-SNAPSHOT + 6.1.2.Final ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 0d9622da4e..8136b235ea 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2-SNAPSHOT + 6.1.2.Final hibernate-validator-test-utils From 0d22da6761382249eb33e68d20236a6f2e054bfd Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 31 Jan 2020 11:26:54 +0000 Subject: [PATCH 297/393] [Jenkins release job] Preparing next development iteration --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index ecc48bbcaf..09b51bfb95 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2.Final + 6.1.3-SNAPSHOT ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 367261bfdb..e5bd46024b 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2.Final + 6.1.3-SNAPSHOT ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index 0d0ba20cea..43e9a6e463 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2.Final + 6.1.3-SNAPSHOT ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index 3479001345..abccaa3efc 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2.Final + 6.1.3-SNAPSHOT ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index df6f78914b..82469be62b 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2.Final + 6.1.3-SNAPSHOT ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index e942487c84..51bf49a7da 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2.Final + 6.1.3-SNAPSHOT ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 8c2cc64e7c..cddc08a7e4 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2.Final + 6.1.3-SNAPSHOT ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index 11a2268ae1..f8268c9013 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2.Final + 6.1.3-SNAPSHOT 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index da7695bbb6..1143f70ee5 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.2.Final + 6.1.3-SNAPSHOT ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 91e4e34872..1ca38b61c0 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.2.Final + 6.1.3-SNAPSHOT ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index e3dc2934cf..2f94c135be 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.2.Final + 6.1.3-SNAPSHOT ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index e52b9996b9..312d1f5749 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2.Final + 6.1.3-SNAPSHOT ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index b94c4bc562..a00d6b54fe 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2.Final + 6.1.3-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 1f83df8189..f7f7c81e30 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2.Final + 6.1.3-SNAPSHOT pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index e2c442ddbb..4bdb3a8d19 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.2.Final + 6.1.3-SNAPSHOT org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index 02d8ebe636..f75663d079 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.2.Final + 6.1.3-SNAPSHOT org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index c7f675c0d3..4af4e218e1 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.2.Final + 6.1.3-SNAPSHOT org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index b135418e0b..956fc14494 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.2.Final + 6.1.3-SNAPSHOT org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index e7e10facc5..89f763fc8b 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2.Final + 6.1.3-SNAPSHOT hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 78a1e3b0b5..70eeff7700 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2.Final + 6.1.3-SNAPSHOT ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 8136b235ea..a7a3dfe691 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.2.Final + 6.1.3-SNAPSHOT hibernate-validator-test-utils From 85ef10d64ba262d0d375fde4aed8054fc9166461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 25 Feb 2020 13:23:30 +0100 Subject: [PATCH 298/393] HV-1758 Remove extra $ characters in built-in contraint messages "{modType}" is evaluated to "MOD10" for example, so with the extra $ we were getting "$MOD10" in interpolated messages, instead of just "MOD10". --- .../org/hibernate/validator/ValidationMessages.properties | 2 +- .../org/hibernate/validator/ValidationMessages_cs.properties | 2 +- .../org/hibernate/validator/ValidationMessages_da.properties | 2 +- .../org/hibernate/validator/ValidationMessages_de.properties | 2 +- .../org/hibernate/validator/ValidationMessages_es.properties | 2 +- .../org/hibernate/validator/ValidationMessages_fa.properties | 2 +- .../org/hibernate/validator/ValidationMessages_fr.properties | 4 ++-- .../org/hibernate/validator/ValidationMessages_hu.properties | 2 +- .../org/hibernate/validator/ValidationMessages_it.properties | 2 +- .../org/hibernate/validator/ValidationMessages_ja.properties | 2 +- .../org/hibernate/validator/ValidationMessages_ko.properties | 2 +- .../org/hibernate/validator/ValidationMessages_nl.properties | 2 +- .../org/hibernate/validator/ValidationMessages_pl.properties | 2 +- .../hibernate/validator/ValidationMessages_pt_BR.properties | 2 +- .../org/hibernate/validator/ValidationMessages_ro.properties | 2 +- .../org/hibernate/validator/ValidationMessages_ru.properties | 2 +- .../org/hibernate/validator/ValidationMessages_sk.properties | 2 +- .../org/hibernate/validator/ValidationMessages_uk.properties | 2 +- .../org/hibernate/validator/ValidationMessages_zh.properties | 2 +- .../hibernate/validator/ValidationMessages_zh_CN.properties | 2 +- .../hibernate/validator/ValidationMessages_zh_TW.properties | 2 +- 21 files changed, 22 insertions(+), 22 deletions(-) diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages.properties index 2cb1354faa..c3064d0066 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages.properties @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = length mus org.hibernate.validator.constraints.LuhnCheck.message = the check digit for ${validatedValue} is invalid, Luhn Modulo 10 checksum failed org.hibernate.validator.constraints.Mod10Check.message = the check digit for ${validatedValue} is invalid, Modulo 10 checksum failed org.hibernate.validator.constraints.Mod11Check.message = the check digit for ${validatedValue} is invalid, Modulo 11 checksum failed -org.hibernate.validator.constraints.ModCheck.message = the check digit for ${validatedValue} is invalid, ${modType} checksum failed +org.hibernate.validator.constraints.ModCheck.message = the check digit for ${validatedValue} is invalid, {modType} checksum failed org.hibernate.validator.constraints.NotBlank.message = may not be empty org.hibernate.validator.constraints.NotEmpty.message = may not be empty org.hibernate.validator.constraints.ParametersScriptAssert.message = script expression "{script}" didn't evaluate to true diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_cs.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_cs.properties index 2948c13ca8..54022d9fa3 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_cs.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_cs.properties @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = d\u00e9lka org.hibernate.validator.constraints.LuhnCheck.message = kontroln\u00ed \u010d\u00edslice pro ${validatedValue} je neplatn\u00e1, kontroln\u00ed sou\u010det Luhn Modulo 10 se nezda\u0159il org.hibernate.validator.constraints.Mod10Check.message = kontroln\u00ed \u010d\u00edslice pro ${validatedValue} je neplatn\u00e1, kontroln\u00ed sou\u010det Modulo 10 se nezda\u0159il org.hibernate.validator.constraints.Mod11Check.message = kontroln\u00ed \u010d\u00edslice pro ${validatedValue} je neplatn\u00e1, kontroln\u00ed sou\u010det Modulo 11 se nezda\u0159il -org.hibernate.validator.constraints.ModCheck.message = kontroln\u00ed \u010d\u00edslice pro ${validatedValue} je neplatn\u00e1, kontroln\u00ed sou\u010det ${modType} se nezda\u0159il +org.hibernate.validator.constraints.ModCheck.message = kontroln\u00ed \u010d\u00edslice pro ${validatedValue} je neplatn\u00e1, kontroln\u00ed sou\u010det {modType} se nezda\u0159il org.hibernate.validator.constraints.NotBlank.message = nesm\u00ed b\u00fdt pr\u00e1zdn\u00e1 org.hibernate.validator.constraints.NotEmpty.message = nesm\u00ed b\u00fdt pr\u00e1zdn\u00e1 org.hibernate.validator.constraints.ParametersScriptAssert.message = v\u00fdraz skriptu "{script}" se nevyhodnotil na true diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_da.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_da.properties index 0e537928f0..302098cd17 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_da.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_da.properties @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = l\u00e6ngde org.hibernate.validator.constraints.LuhnCheck.message = kontrolcifferet for ${validatedValue} er ugyldigt, Luhn Modulo 10 checksum mislykkedes org.hibernate.validator.constraints.Mod10Check.message = kontrolcifferet for ${validatedValue} er ugyldigt, Modulo 10 checksum mislykkedes org.hibernate.validator.constraints.Mod11Check.message = kontrolcifferet for ${validatedValue} er ugyldigt, Modulo 11 checksum mislykkedes -org.hibernate.validator.constraints.ModCheck.message = kontrolcifferet for ${validatedValue} er ugyldigt, ${modType} checksummet mislykkedes +org.hibernate.validator.constraints.ModCheck.message = kontrolcifferet for ${validatedValue} er ugyldigt, {modType} checksummet mislykkedes org.hibernate.validator.constraints.NotBlank.message = m\u00e5 ikke v\u00e6re tomt org.hibernate.validator.constraints.NotEmpty.message = m\u00e5 ikke v\u00e6re tomt org.hibernate.validator.constraints.ParametersScriptAssert.message = script udtryk "{script}" evaluerede ikke til true diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties index 413e0943b5..079d45b168 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = L\u00e4nge org.hibernate.validator.constraints.LuhnCheck.message = die Pr\u00fcfziffer f\u00fcr ${validatedValue} ist ung\u00fcltig, Luhn Modulo 10-Kontrollsumme ist fehlgeschlagen org.hibernate.validator.constraints.Mod10Check.message = die Pr\u00fcfziffer f\u00fcr ${validatedValue} ist ung\u00fcltig, Modulo 10-Kontrollsumme ist fehlgeschlagen org.hibernate.validator.constraints.Mod11Check.message = die Pr\u00fcfziffer f\u00fcr ${validatedValue} ist ung\u00fcltig, Modulo 11-Kontrollsumme ist fehlgeschlagen -org.hibernate.validator.constraints.ModCheck.message = die Pr\u00fcfziffer f\u00fcr ${validatedValue} ist ung\u00fcltig, ${modType}-Kontrollsumme ist fehlgeschlagen +org.hibernate.validator.constraints.ModCheck.message = die Pr\u00fcfziffer f\u00fcr ${validatedValue} ist ung\u00fcltig, {modType}-Kontrollsumme ist fehlgeschlagen org.hibernate.validator.constraints.NotBlank.message = darf nicht leer sein org.hibernate.validator.constraints.NotEmpty.message = darf nicht leer sein org.hibernate.validator.constraints.ParametersScriptAssert.message = die Evaluierung des Scriptausdrucks "{script}" ergab nicht true diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_es.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_es.properties index 89bc7106c2..d763c05f84 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_es.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_es.properties @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = la longitu org.hibernate.validator.constraints.LuhnCheck.message = el d\u00edgito de comprobaci\u00f3n para ${validatedValue} no es v\u00e1lido, ha fallado la suma de comprobaci\u00f3n de Luhn Modulo 10 org.hibernate.validator.constraints.Mod10Check.message = el d\u00edgito de comprobaci\u00f3n para ${validatedValue} no es v\u00e1lido, ha fallado la suma de comprobaci\u00f3n de Modulo 10 org.hibernate.validator.constraints.Mod11Check.message = el d\u00edgito de comprobaci\u00f3n para ${validatedValue} no es v\u00e1lido, ha fallado la suma de comprobaci\u00f3n de Modulo 11 -org.hibernate.validator.constraints.ModCheck.message = el d\u00edgito de comprobaci\u00f3n para ${validatedValue} no es v\u00e1lido, ha fallado la suma de comprobaci\u00f3n ${modType} +org.hibernate.validator.constraints.ModCheck.message = el d\u00edgito de comprobaci\u00f3n para ${validatedValue} no es v\u00e1lido, ha fallado la suma de comprobaci\u00f3n {modType} org.hibernate.validator.constraints.NotBlank.message = no debe estar vac\u00edo org.hibernate.validator.constraints.NotEmpty.message = no debe estar vac\u00edo org.hibernate.validator.constraints.ParametersScriptAssert.message = la expresi\u00f3n de script "{script}" no se ha evaluado en verdadera diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fa.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fa.properties index f86a395bb1..373db2a5ae 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fa.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fa.properties @@ -30,7 +30,7 @@ org.hibernate.validator.constraints.CodePointLength.message = \u0637\u06 org.hibernate.validator.constraints.LuhnCheck.message = \u0645\u0642\u062F\u0627\u0631 ${validatedValue} \u0628\u0627 Luhn Modulo 10 \u0647\u0645\u062E\u0648\u0627\u0646\u06CC \u0646\u062F\u0627\u0631\u062F org.hibernate.validator.constraints.Mod10Check.message = \u0645\u0642\u062F\u0627\u0631 ${validatedValue} \u0628\u0627 Modulo 10 \u0647\u0645\u062E\u0648\u0627\u0646\u06CC \u0646\u062F\u0627\u0631\u062F org.hibernate.validator.constraints.Mod11Check.message = \u0645\u0642\u062F\u0627\u0631 ${validatedValue} \u0628\u0627 Modulo 11 \u0647\u0645\u062E\u0648\u0627\u0646\u06CC \u0646\u062F\u0627\u0631\u062F -org.hibernate.validator.constraints.ModCheck.message = \u0645\u0642\u062F\u0627\u0631 ${validatedValue} \u0628\u0627 ${modType} \u0647\u0645\u062E\u0648\u0627\u0646\u06CC \u0646\u062F\u0627\u0631\u062F +org.hibernate.validator.constraints.ModCheck.message = \u0645\u0642\u062F\u0627\u0631 ${validatedValue} \u0628\u0627 {modType} \u0647\u0645\u062E\u0648\u0627\u0646\u06CC \u0646\u062F\u0627\u0631\u062F org.hibernate.validator.constraints.NotBlank.message = \u0645\u0642\u062F\u0627\u0631 \u0646\u0628\u0627\u06CC\u062F \u062E\u0627\u0644\u06CC \u0628\u0627\u0634\u062F org.hibernate.validator.constraints.NotEmpty.message = \u0645\u0642\u062F\u0627\u0631 \u0646\u0628\u0627\u06CC\u062F \u062E\u0627\u0644\u06CC \u0628\u0627\u0634\u062F org.hibernate.validator.constraints.ParametersScriptAssert.message = \u0627\u0633\u06A9\u0631\u06CC\u067E\u062A "{script}" \u0645\u0642\u062F\u0627\u0631 \u062F\u0631\u0633\u062A \u0628\u0631\u0646\u0645\u06CC\u06AF\u0631\u062F\u0627\u0646\u062F diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties index f12655d8ac..062367d185 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties @@ -12,7 +12,7 @@ javax.validation.constraints.Negative.message = doit \u00eatre inf\u00e9r javax.validation.constraints.NegativeOrZero.message = doit \u00eatre inf\u00e9rieur ou \u00e9gal \u00e0 0 javax.validation.constraints.NotBlank.message = ne doit pas \u00eatre vide javax.validation.constraints.NotEmpty.message = ne doit pas \u00eatre vide -javax.validation.constraints.NotNull.message = ne doit pas être nul +javax.validation.constraints.NotNull.message = ne doit pas �tre nul javax.validation.constraints.Null.message = doit \u00EAtre nul javax.validation.constraints.Past.message = doit \u00eatre une date dans le pass\u00e9 javax.validation.constraints.PastOrPresent.message = doit \u00eatre une date dans le pass\u00e9 ou le pr\u00e9sent @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = la longueu org.hibernate.validator.constraints.LuhnCheck.message = la cl\u00e9 de contr\u00f4le pour ${validatedValue} n'est pas valide ; la somme de contr\u00f4le de l'algorithme de Luhn (modulo 10) a \u00e9chou\u00e9 org.hibernate.validator.constraints.Mod10Check.message = la cl\u00e9 de contr\u00f4le pour ${validatedValue} n'est pas valide ; la somme de contr\u00f4le de l'algorithme modulo 10 a \u00e9chou\u00e9 org.hibernate.validator.constraints.Mod11Check.message = la cl\u00e9 de contr\u00f4le pour ${validatedValue} n'est pas valide ; la somme de contr\u00f4le de l'algorithme modulo 11 a \u00e9chou\u00e9 -org.hibernate.validator.constraints.ModCheck.message = la cl\u00e9 de contr\u00f4le pour ${validatedValue} n'est pas valide ; la somme de contr\u00f4le de l'algorithme ${modType} a \u00e9chou\u00e9 +org.hibernate.validator.constraints.ModCheck.message = la cl\u00e9 de contr\u00f4le pour ${validatedValue} n'est pas valide ; la somme de contr\u00f4le de l'algorithme {modType} a \u00e9chou\u00e9 org.hibernate.validator.constraints.NotBlank.message = ne doit pas \u00eatre vide org.hibernate.validator.constraints.NotEmpty.message = ne doit pas \u00eatre vide org.hibernate.validator.constraints.ParametersScriptAssert.message = le script "{script}" n'a pas \u00E9t\u00E9 \u00E9valu\u00E9 \u00E0 vrai diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_hu.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_hu.properties index 79ab3d3170..1b0a40a38f 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_hu.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_hu.properties @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = a hossznak org.hibernate.validator.constraints.LuhnCheck.message = a(z) ${validatedValue} ellen\u0151rz\u0151 sz\u00e1mjegye \u00e9rv\u00e9nytelen, a Luhn Modulo 10 ellen\u0151rz\u0151\u00f6sszeg meghi\u00fasult org.hibernate.validator.constraints.Mod10Check.message = a(z) ${validatedValue} ellen\u0151rz\u0151 sz\u00e1mjegye \u00e9rv\u00e9nytelen, a Modulo 10 ellen\u0151rz\u0151\u00f6sszeg meghi\u00fasult org.hibernate.validator.constraints.Mod11Check.message = a(z) ${validatedValue} ellen\u0151rz\u0151 sz\u00e1mjegye \u00e9rv\u00e9nytelen, a Modulo 11 ellen\u0151rz\u0151\u00f6sszeg meghi\u00fasult -org.hibernate.validator.constraints.ModCheck.message = a(z) ${validatedValue} ellen\u0151rz\u0151 sz\u00e1mjegye \u00e9rv\u00e9nytelen, a(z) ${modType} ellen\u0151rz\u0151\u00f6sszeg meghi\u00fasult +org.hibernate.validator.constraints.ModCheck.message = a(z) ${validatedValue} ellen\u0151rz\u0151 sz\u00e1mjegye \u00e9rv\u00e9nytelen, a(z) {modType} ellen\u0151rz\u0151\u00f6sszeg meghi\u00fasult org.hibernate.validator.constraints.NotBlank.message = nem lehet \u00fcres org.hibernate.validator.constraints.NotEmpty.message = nem lehet \u00fcres org.hibernate.validator.constraints.ParametersScriptAssert.message = a(z) "{script}" parancsf\u00e1jl kifejez\u00e9s nem true \u00e9rt\u00e9kre \u00e9rt\u00e9kel\u0151d\u00f6tt ki diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_it.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_it.properties index 368780928e..156a87a2e5 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_it.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_it.properties @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = la lunghez org.hibernate.validator.constraints.LuhnCheck.message = la cifra di controllo per ${validatedValue} non \u00e8 valida, checksum Luhn Modulo 10 non riuscito org.hibernate.validator.constraints.Mod10Check.message = la cifra di controllo per ${validatedValue} non \u00e8 valida, checksum Modulo 10 non riuscito org.hibernate.validator.constraints.Mod11Check.message = la cifra di controllo per ${validatedValue} non \u00e8 valida, checksum Modulo 11 non riuscito -org.hibernate.validator.constraints.ModCheck.message = la cifra di controllo per ${validatedValue} non \u00e8 valida, checksum ${modType} non riuscito +org.hibernate.validator.constraints.ModCheck.message = la cifra di controllo per ${validatedValue} non \u00e8 valida, checksum {modType} non riuscito org.hibernate.validator.constraints.NotBlank.message = non deve essere spazio org.hibernate.validator.constraints.NotEmpty.message = non deve essere vuoto org.hibernate.validator.constraints.ParametersScriptAssert.message = espressione script "{script}" non valutata true diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ja.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ja.properties index 71994d2ae4..3fa76e054c 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ja.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ja.properties @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = {min} \u30 org.hibernate.validator.constraints.LuhnCheck.message = ${validatedValue} \u306e\u30c1\u30a7\u30c3\u30af\u30c7\u30b8\u30c3\u30c8\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093 (Luhn \u30e2\u30c7\u30e5\u30e9\u30b910\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0) org.hibernate.validator.constraints.Mod10Check.message = ${validatedValue} \u306e\u30c1\u30a7\u30c3\u30af\u30c7\u30b8\u30c3\u30c8\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093 (\u30e2\u30c7\u30e5\u30e9\u30b910) org.hibernate.validator.constraints.Mod11Check.message = ${validatedValue} \u306e\u30c1\u30a7\u30c3\u30af\u30c7\u30b8\u30c3\u30c8\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093 (\u30e2\u30c7\u30e5\u30e9\u30b911) -org.hibernate.validator.constraints.ModCheck.message = ${validatedValue} \u306e\u30c1\u30a7\u30c3\u30af\u30c7\u30b8\u30c3\u30c8\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093 (${modType} \u306e\u30c1\u30a7\u30c3\u30af\u30b5\u30e0\u304c\u5931\u6557\u3057\u307e\u3057\u305f) +org.hibernate.validator.constraints.ModCheck.message = ${validatedValue} \u306e\u30c1\u30a7\u30c3\u30af\u30c7\u30b8\u30c3\u30c8\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093 ({modType} \u306e\u30c1\u30a7\u30c3\u30af\u30b5\u30e0\u304c\u5931\u6557\u3057\u307e\u3057\u305f) org.hibernate.validator.constraints.NotBlank.message = \u7a7a\u767d\u306f\u8a31\u53ef\u3055\u308c\u3066\u307e\u305b\u3093 org.hibernate.validator.constraints.NotEmpty.message = \u7a7a\u8981\u7d20\u306f\u8a31\u53ef\u3055\u308c\u3066\u3044\u307e\u305b\u3093 org.hibernate.validator.constraints.ParametersScriptAssert.message = \u6b21\u306e\u30b9\u30af\u30ea\u30d7\u30c8\u5f0f "{script}" \u306b\u3088\u308b\u8a55\u4fa1\u7d50\u679c\u304c true \u306b\u306a\u308a\u307e\u305b\u3093\u3067\u3057\u305f diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ko.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ko.properties index 510d70b968..25971cf6cf 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ko.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ko.properties @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = \uae38\uc7 org.hibernate.validator.constraints.LuhnCheck.message = ${validatedValue}\uc758 \uccb4\ud06c \ub514\uc9c0\ud2b8\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. Luhn Modulo 10 \uccb4\ud06c\uc12c\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4 org.hibernate.validator.constraints.Mod10Check.message = ${validatedValue}\uc758 \uccb4\ud06c \ub514\uc9c0\ud2b8\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. Modulo 10 \uccb4\ud06c\uc12c\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4 org.hibernate.validator.constraints.Mod11Check.message = ${validatedValue}\uc758 \uccb4\ud06c \ub514\uc9c0\ud2b8\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. Modulo 11 \uccb4\ud06c\uc12c\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4 -org.hibernate.validator.constraints.ModCheck.message = ${validatedValue}\uc758 \uccb4\ud06c \ub514\uc9c0\ud2b8\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. ${modType} \uccb4\ud06c\uc12c\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4 +org.hibernate.validator.constraints.ModCheck.message = ${validatedValue}\uc758 \uccb4\ud06c \ub514\uc9c0\ud2b8\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. {modType} \uccb4\ud06c\uc12c\uc774 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4 org.hibernate.validator.constraints.NotBlank.message = \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4 org.hibernate.validator.constraints.NotEmpty.message = \ube44\uc5b4 \uc788\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4 org.hibernate.validator.constraints.ParametersScriptAssert.message = \uc2a4\ud06c\ub9bd\ud2b8 \ud45c\ud604\uc2dd "{script}"\uac00 true\ub85c \ud3c9\uac00\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4 diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties index 526f3cfb62..0fb8f5ca5f 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_nl.properties @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = moet tusse org.hibernate.validator.constraints.LuhnCheck.message = het controlecijfer voor ${validatedValue} is ongeldig, Luhn Modulo 10 checksum mislukt org.hibernate.validator.constraints.Mod10Check.message = het controlecijfer voor ${validatedValue} is ongeldig, Modulo 10 checksum mislukt org.hibernate.validator.constraints.Mod11Check.message = het controlecijfer voor ${validatedValue} is ongeldig, Modulo 11 checksum mislukt -org.hibernate.validator.constraints.ModCheck.message = het controlecijfer voor ${validatedValue} is ongeldig, ${modType} checksum mislukt +org.hibernate.validator.constraints.ModCheck.message = het controlecijfer voor ${validatedValue} is ongeldig, {modType} checksum mislukt org.hibernate.validator.constraints.NotBlank.message = mag niet onbeschreven zijn org.hibernate.validator.constraints.NotEmpty.message = mag niet leeg zijn org.hibernate.validator.constraints.ParametersScriptAssert.message = scriptexpressie "{script}" is ongeldig diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pl.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pl.properties index b0a9853af3..dd15fed310 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pl.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pl.properties @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = d\u0142ugo org.hibernate.validator.constraints.LuhnCheck.message = cyfra kontrolna dla warto\u015bci ${validatedValue} jest niepoprawna, sprawdzenie sumy kontrolnej za pomoc\u0105 algorytmu Luhn Modulo 10 nie powiod\u0142o si\u0119 org.hibernate.validator.constraints.Mod10Check.message = cyfra kontrolna dla warto\u015bci ${validatedValue} jest niepoprawna, sprawdzenie sumy kontrolnej za pomoc\u0105 algorytmu Modulo 10 nie powiod\u0142o si\u0119 org.hibernate.validator.constraints.Mod11Check.message = cyfra kontrolna dla warto\u015bci ${validatedValue} jest niepoprawna, sprawdzenie sumy kontrolnej za pomoc\u0105 algorytmu Modulo 11 nie powiod\u0142o si\u0119 -org.hibernate.validator.constraints.ModCheck.message = cyfra kontrolna dla warto\u015bci ${validatedValue} jest niepoprawna, sprawdzenie sumy kontrolnej za pomoc\u0105 algorytmu ${modType} nie powiod\u0142o si\u0119 +org.hibernate.validator.constraints.ModCheck.message = cyfra kontrolna dla warto\u015bci ${validatedValue} jest niepoprawna, sprawdzenie sumy kontrolnej za pomoc\u0105 algorytmu {modType} nie powiod\u0142o si\u0119 org.hibernate.validator.constraints.NotBlank.message = nie mo\u017ce by\u0107 odst\u0119pem org.hibernate.validator.constraints.NotEmpty.message = nie mo\u017ce by\u0107 puste org.hibernate.validator.constraints.ParametersScriptAssert.message = warto\u015bciowanie wyra\u017cenia skryptu {script} nie zwr\u00f3ci\u0142o warto\u015bci true diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties index 73ef080fdf..4e8694b250 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_pt_BR.properties @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = o comprime org.hibernate.validator.constraints.LuhnCheck.message = o d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o Luhn Modulo 10 com falha org.hibernate.validator.constraints.Mod10Check.message = o d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o Modulo 10 com falha org.hibernate.validator.constraints.Mod11Check.message = o d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o Modulo 11 com falha -org.hibernate.validator.constraints.ModCheck.message = o d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o ${modType} com falha +org.hibernate.validator.constraints.ModCheck.message = o d\u00edgito de verifica\u00e7\u00e3o para ${validatedValue} \u00e9 inv\u00e1lido, soma de verifica\u00e7\u00e3o {modType} com falha org.hibernate.validator.constraints.NotBlank.message = n\u00e3o deve estar em branco org.hibernate.validator.constraints.NotEmpty.message = n\u00e3o deve estar vazio org.hibernate.validator.constraints.ParametersScriptAssert.message = express\u00e3o de script "{script}" n\u00e3o avaliou para true diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ro.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ro.properties index d83fecb319..63532987c1 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ro.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ro.properties @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = lungimea t org.hibernate.validator.constraints.LuhnCheck.message = cifra de verificare pentru ${validatedValue} este invalid\u0103, suma de control Luhn Modulo 10 a e\u015fuat org.hibernate.validator.constraints.Mod10Check.message = cifra de verificare pentru ${validatedValue} este invalid\u0103, suma de control Modulo 10 a e\u015fuat org.hibernate.validator.constraints.Mod11Check.message = cifra de verificare pentru ${validatedValue} este invalid\u0103, suma de control Modulo 11 a e\u015fuat -org.hibernate.validator.constraints.ModCheck.message = cifra de verificare pentru ${validatedValue} este invalid\u0103, suma de control ${modType} a e\u015fuat +org.hibernate.validator.constraints.ModCheck.message = cifra de verificare pentru ${validatedValue} este invalid\u0103, suma de control {modType} a e\u015fuat org.hibernate.validator.constraints.NotBlank.message = nu trebuie s\u0103 fie blanc org.hibernate.validator.constraints.NotEmpty.message = nu trebuie s\u0103 fie gol org.hibernate.validator.constraints.ParametersScriptAssert.message = expresia de script "{script}" nu s-a evaluat la true diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ru.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ru.properties index 94e70ec254..eae1cfbb43 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ru.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_ru.properties @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = \u0434\u04 org.hibernate.validator.constraints.LuhnCheck.message = \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u0440\u044f\u0434 \u0434\u043b\u044f ${validatedValue} \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u043e\u0439 \u0441\u0443\u043c\u043c\u044b Luhn Modulo 10 org.hibernate.validator.constraints.Mod10Check.message = \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u0440\u044f\u0434 \u0434\u043b\u044f ${validatedValue} \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u043e\u0439 \u0441\u0443\u043c\u043c\u044b Modulo 10 org.hibernate.validator.constraints.Mod11Check.message = \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u0440\u044f\u0434 \u0434\u043b\u044f ${validatedValue} \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u043e\u0439 \u0441\u0443\u043c\u043c\u044b Modulo 11 -org.hibernate.validator.constraints.ModCheck.message = \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u0440\u044f\u0434 \u0434\u043b\u044f ${validatedValue} \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u043e\u0439 \u0441\u0443\u043c\u043c\u044b ${modType} +org.hibernate.validator.constraints.ModCheck.message = \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u0440\u044f\u0434 \u0434\u043b\u044f ${validatedValue} \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u043e\u0439 \u0441\u0443\u043c\u043c\u044b {modType} org.hibernate.validator.constraints.NotBlank.message = \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c org.hibernate.validator.constraints.NotEmpty.message = \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c org.hibernate.validator.constraints.ParametersScriptAssert.message = \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f "{script}" \u043d\u0435 \u0440\u0430\u0432\u0435\u043d true diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_sk.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_sk.properties index 1268340cd9..2380b475f8 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_sk.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_sk.properties @@ -23,7 +23,7 @@ org.hibernate.validator.constraints.CodePointLength.message = d\u013a\u0 org.hibernate.validator.constraints.LuhnCheck.message = kontroln\u00e1 \u010d\u00edslica pre ${validatedValue} nie je spr\u00e1vna, kontroln\u00fd s\u00fa\u010det Luhn Modulo 10 zlyhal org.hibernate.validator.constraints.Mod10Check.message = kontroln\u00e1 \u010d\u00edslica pre ${validatedValue} nie je spr\u00e1vna, kontroln\u00fd s\u00fa\u010det Modulo 10 zlyhal org.hibernate.validator.constraints.Mod11Check.message = kontroln\u00e1 \u010d\u00edslica pre ${validatedValue} nie je spr\u00e1vna, kontroln\u00fd s\u00fa\u010det Modulo 11 zlyhal -org.hibernate.validator.constraints.ModCheck.message = kontroln\u00e1 \u010d\u00edslica pre ${validatedValue} nie je spr\u00e1vna, kontroln\u00fd s\u00fa\u010det ${modType} zlyhal +org.hibernate.validator.constraints.ModCheck.message = kontroln\u00e1 \u010d\u00edslica pre ${validatedValue} nie je spr\u00e1vna, kontroln\u00fd s\u00fa\u010det {modType} zlyhal org.hibernate.validator.constraints.NotBlank.message = nem\u00f4\u017ee by\u0165 pr\u00e1zdne org.hibernate.validator.constraints.NotEmpty.message = nem\u00f4\u017ee by\u0165 pr\u00e1zdne org.hibernate.validator.constraints.ParametersScriptAssert.message = skriptovac\u00ed v\u00fdraz "{script}" nebol vyhodnoten\u00fd na \u00e1no diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_uk.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_uk.properties index cf201e4e33..18d1416159 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_uk.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_uk.properties @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = \u0434\u04 org.hibernate.validator.constraints.LuhnCheck.message = \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u0430 \u0446\u0438\u0444\u0440\u0430 \u0434\u043b\u044f ${validatedValue}, \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u0437\u0430 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u043c \u041b\u0443\u043d\u0430 \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u043b\u0430\u0441\u044c \u0437 \u043f\u043e\u043c\u0438\u043b\u043a\u043e\u044e org.hibernate.validator.constraints.Mod10Check.message = \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u0430 \u0446\u0438\u0444\u0440\u0430 \u0434\u043b\u044f ${validatedValue}, \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u0437\u0430 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u043c Mod10 \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u043b\u0430\u0441\u044c \u0437 \u043f\u043e\u043c\u0438\u043b\u043a\u043e\u044e org.hibernate.validator.constraints.Mod11Check.message = \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u0430 \u0446\u0438\u0444\u0440\u0430 \u0434\u043b\u044f ${validatedValue}, \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u0437\u0430 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u043c Mod11 \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u043b\u0430\u0441\u044c \u0437 \u043f\u043e\u043c\u0438\u043b\u043a\u043e\u044e -org.hibernate.validator.constraints.ModCheck.message = \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u0430 \u0446\u0438\u0444\u0440\u0430 \u0434\u043b\u044f ${validatedValue}, \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u0437\u0430 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u043c ${modType} \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u043b\u0430\u0441\u044c \u0437 \u043f\u043e\u043c\u0438\u043b\u043a\u043e\u044e +org.hibernate.validator.constraints.ModCheck.message = \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u0430 \u0446\u0438\u0444\u0440\u0430 \u0434\u043b\u044f ${validatedValue}, \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u0437\u0430 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u043c {modType} \u0437\u0430\u043a\u0456\u043d\u0447\u0438\u043b\u0430\u0441\u044c \u0437 \u043f\u043e\u043c\u0438\u043b\u043a\u043e\u044e org.hibernate.validator.constraints.NotBlank.message = \u043d\u0435 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u043f\u0443\u0441\u0442\u0438\u043c org.hibernate.validator.constraints.NotEmpty.message = \u043d\u0435 \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u043f\u043e\u0440\u043e\u0436\u043d\u0456\u043c org.hibernate.validator.constraints.ParametersScriptAssert.message = \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432\u0438\u0439 \u0432\u0438\u0440\u0430\u0437 "{script}" \u043d\u0435 \u0454 \u0456\u0441\u0442\u0438\u043d\u043d\u0438\u043c diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh.properties index 3c4c3de950..fa10daf1d8 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh.properties @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = \u957f\u5e org.hibernate.validator.constraints.LuhnCheck.message = ${validatedValue} \u7684\u6821\u9a8c\u4f4d\u65e0\u6548\uff0cLuhn Modulo 10 \u6821\u9a8c\u548c\u5931\u8d25 org.hibernate.validator.constraints.Mod10Check.message = ${validatedValue} \u7684\u6821\u9a8c\u4f4d\u65e0\u6548\uff0cModulo 10 \u6821\u9a8c\u548c\u5931\u8d25 org.hibernate.validator.constraints.Mod11Check.message = ${validatedValue} \u7684\u6821\u9a8c\u4f4d\u65e0\u6548\uff0cModulo 11 \u6821\u9a8c\u548c\u5931\u8d25 -org.hibernate.validator.constraints.ModCheck.message = ${validatedValue} \u7684\u6821\u9a8c\u4f4d\u65e0\u6548\uff0c${modType} \u6821\u9a8c\u548c\u5931\u8d25 +org.hibernate.validator.constraints.ModCheck.message = ${validatedValue} \u7684\u6821\u9a8c\u4f4d\u65e0\u6548\uff0c{modType} \u6821\u9a8c\u548c\u5931\u8d25 org.hibernate.validator.constraints.NotBlank.message = \u53ef\u80fd\u4e0d\u4e3a\u7a7a org.hibernate.validator.constraints.NotEmpty.message = \u53ef\u80fd\u4e0d\u4e3a\u7a7a org.hibernate.validator.constraints.ParametersScriptAssert.message = \u811a\u672c\u8868\u8fbe\u5f0f "{script}" \u672a\u6c42\u503c\u4e3a true diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh_CN.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh_CN.properties index dba87b580d..b2a75318fe 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh_CN.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh_CN.properties @@ -30,7 +30,7 @@ org.hibernate.validator.constraints.CodePointLength.message = \u957f\u5e org.hibernate.validator.constraints.LuhnCheck.message = ${validatedValue}\u7684\u6821\u9a8c\u7801\u4e0d\u5408\u6cd5, Luhn\u6a2110\u6821\u9a8c\u548c\u4e0d\u5339\u914d org.hibernate.validator.constraints.Mod10Check.message = ${validatedValue}\u7684\u6821\u9a8c\u7801\u4e0d\u5408\u6cd5, \u6a2110\u6821\u9a8c\u548c\u4e0d\u5339\u914d org.hibernate.validator.constraints.Mod11Check.message = ${validatedValue}\u7684\u6821\u9a8c\u7801\u4e0d\u5408\u6cd5, \u6a2111\u6821\u9a8c\u548c\u4e0d\u5339\u914d -org.hibernate.validator.constraints.ModCheck.message = ${validatedValue}\u7684\u6821\u9a8c\u7801\u4e0d\u5408\u6cd5, ${modType}\u6821\u9a8c\u548c\u4e0d\u5339\u914d +org.hibernate.validator.constraints.ModCheck.message = ${validatedValue}\u7684\u6821\u9a8c\u7801\u4e0d\u5408\u6cd5, {modType}\u6821\u9a8c\u548c\u4e0d\u5339\u914d org.hibernate.validator.constraints.NotBlank.message = \u4e0d\u80fd\u4e3a\u7a7a org.hibernate.validator.constraints.NotEmpty.message = \u4e0d\u80fd\u4e3a\u7a7a org.hibernate.validator.constraints.ParametersScriptAssert.message = \u6267\u884c\u811a\u672c\u8868\u8fbe\u5f0f"{script}"\u6ca1\u6709\u8fd4\u56de\u671f\u671b\u7ed3\u679c diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh_TW.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh_TW.properties index de7aca4d3e..3bd3f887f2 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh_TW.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh_TW.properties @@ -31,7 +31,7 @@ org.hibernate.validator.constraints.CodePointLength.message = \u9577\u5e org.hibernate.validator.constraints.LuhnCheck.message = ${validatedValue} \u7684\u6aa2\u67e5\u78bc\u7121\u6548\uff0cLuhn \u6a21\u6578 10 \u7e3d\u548c\u6aa2\u67e5\u5931\u6557 org.hibernate.validator.constraints.Mod10Check.message = ${validatedValue} \u7684\u6aa2\u67e5\u78bc\u7121\u6548\uff0c\u6a21\u6578 10 \u7e3d\u548c\u6aa2\u67e5\u5931\u6557 org.hibernate.validator.constraints.Mod11Check.message = ${validatedValue} \u7684\u6aa2\u67e5\u78bc\u7121\u6548\uff0c\u6a21\u6578 11 \u7e3d\u548c\u6aa2\u67e5\u5931\u6557 -org.hibernate.validator.constraints.ModCheck.message = ${validatedValue} \u7684\u6aa2\u67e5\u78bc\u7121\u6548\uff0c${modType} \u7e3d\u548c\u6aa2\u67e5\u5931\u6557 +org.hibernate.validator.constraints.ModCheck.message = ${validatedValue} \u7684\u6aa2\u67e5\u78bc\u7121\u6548\uff0c{modType} \u7e3d\u548c\u6aa2\u67e5\u5931\u6557 org.hibernate.validator.constraints.NotBlank.message = \u4e0d\u80fd\u662f\u7a7a\u7684 org.hibernate.validator.constraints.NotEmpty.message = \u4e0d\u80fd\u662f\u7a7a\u7684 org.hibernate.validator.constraints.ParametersScriptAssert.message = Script \u8868\u793a\u5f0f "{script}" \u4e0d\u662f\u6c42\u503c\u70ba true From e0ac8c465cf356d2803f74cc9fc751f85d6aa37a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 25 Feb 2020 15:00:02 +0100 Subject: [PATCH 299/393] HV-1758 Check for un-interpolated dollar signs in MessagePropertiesTest --- .../internal/constraintvalidators/MessagePropertiesTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/MessagePropertiesTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/MessagePropertiesTest.java index 5886f25f2e..ad05550768 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/MessagePropertiesTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/MessagePropertiesTest.java @@ -198,6 +198,11 @@ private void collectInvalidMessages(Locale locale, List invalidMessages, "Message for constraint " + violation.getConstraintDescriptor().getAnnotation().annotationType() + " and locale " + locale + " contains a curly brace: " + violation.getMessage() ); } + if ( violation.getMessage().contains( "$" ) ) { + invalidMessages.add( + "Message for constraint " + violation.getConstraintDescriptor().getAnnotation().annotationType() + " and locale " + locale + + " contains a dollar sign: " + violation.getMessage() ); + } } } From 5596949b1ba6bde88eb28e03b75799c288532749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 25 Feb 2020 15:51:08 +0100 Subject: [PATCH 300/393] HV-1758 Replace unicode representation of accented character with \uXX format Co-Authored-By: Guillaume Smet --- .../org/hibernate/validator/ValidationMessages_fr.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties index 062367d185..cc1b76278b 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_fr.properties @@ -12,7 +12,7 @@ javax.validation.constraints.Negative.message = doit \u00eatre inf\u00e9r javax.validation.constraints.NegativeOrZero.message = doit \u00eatre inf\u00e9rieur ou \u00e9gal \u00e0 0 javax.validation.constraints.NotBlank.message = ne doit pas \u00eatre vide javax.validation.constraints.NotEmpty.message = ne doit pas \u00eatre vide -javax.validation.constraints.NotNull.message = ne doit pas �tre nul +javax.validation.constraints.NotNull.message = ne doit pas \u00eatre nul javax.validation.constraints.Null.message = doit \u00EAtre nul javax.validation.constraints.Past.message = doit \u00eatre une date dans le pass\u00e9 javax.validation.constraints.PastOrPresent.message = doit \u00eatre une date dans le pass\u00e9 ou le pr\u00e9sent From 5f275a74bdfc12c1e4d1e680f4768005ed713b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 22 Oct 2019 09:39:25 +0200 Subject: [PATCH 301/393] HV-1755 Test constraints on method parameters of EJB Jax-RS beans --- integration/pom.xml | 11 +++ .../integration/wildfly/ejb/EjbIT.java | 70 +++++++++++++++++++ .../wildfly/ejb/EjbJaxRsResource.java | 30 ++++++++ .../wildfly/ejb/JaxRsApplication.java | 20 ++++++ pom.xml | 12 ++++ 5 files changed, 143 insertions(+) create mode 100644 integration/src/test/java/org/hibernate/validator/integration/wildfly/ejb/EjbIT.java create mode 100644 integration/src/test/java/org/hibernate/validator/integration/wildfly/ejb/EjbJaxRsResource.java create mode 100644 integration/src/test/java/org/hibernate/validator/integration/wildfly/ejb/JaxRsApplication.java diff --git a/integration/pom.xml b/integration/pom.xml index cddc08a7e4..5053e46480 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -42,6 +42,11 @@ assertj-core test + + io.rest-assured + rest-assured + test + log4j log4j @@ -89,6 +94,12 @@ jakarta.annotation-api test + + + jakarta.ws.rs + jakarta.ws.rs-api + provided + org.jboss.arquillian.testng arquillian-testng-container diff --git a/integration/src/test/java/org/hibernate/validator/integration/wildfly/ejb/EjbIT.java b/integration/src/test/java/org/hibernate/validator/integration/wildfly/ejb/EjbIT.java new file mode 100644 index 0000000000..35c7404f15 --- /dev/null +++ b/integration/src/test/java/org/hibernate/validator/integration/wildfly/ejb/EjbIT.java @@ -0,0 +1,70 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.integration.wildfly.ejb; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; + +import org.hibernate.validator.integration.AbstractArquillianIT; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.shrinkwrap.descriptor.api.Descriptors; + +import io.restassured.filter.log.ErrorLoggingFilter; +import io.restassured.http.ContentType; +import org.testng.annotations.Test; + +public class EjbIT extends AbstractArquillianIT { + private static final String WAR_FILE_NAME = EjbIT.class.getSimpleName() + ".war"; + private static final String APPLICATION_PATH = EjbIT.class.getSimpleName(); + + @Deployment + public static WebArchive createTestArchive() throws Exception { + return buildTestArchive( WAR_FILE_NAME ) + .addClass( EjbJaxRsResource.class ) + .addClass( JaxRsApplication.class ) + .addAsWebInfResource( EmptyAsset.INSTANCE, "beans.xml" ) + .addAsWebInfResource( + new StringAsset( + Descriptors.create( org.jboss.shrinkwrap.descriptor.api.webapp31.WebAppDescriptor.class ) + .exportAsString() + ), + "web.xml" + ); + } + + @Test + @RunAsClient + public void testRestEasyWorks() { + given() + .filter( new ErrorLoggingFilter() ) + .body( "[\"a\", \"b\", \"c\"]" ) + .contentType( ContentType.JSON ) + .post( APPLICATION_PATH + "/put/list/" ) + .then() + .statusCode( 200 ) + .body( equalTo( "Hello bars a, b, c" ) ); + } + + @Test + @RunAsClient + public void testValidationWorks() { + given() + .filter( new ErrorLoggingFilter() ) + .body( "[]" ) + .contentType( ContentType.JSON ) + .post( APPLICATION_PATH + "/put/list/" ) + .then() + .statusCode( 400 ) + .body( containsString( "must not be empty" ) ); + } +} diff --git a/integration/src/test/java/org/hibernate/validator/integration/wildfly/ejb/EjbJaxRsResource.java b/integration/src/test/java/org/hibernate/validator/integration/wildfly/ejb/EjbJaxRsResource.java new file mode 100644 index 0000000000..777ae195f6 --- /dev/null +++ b/integration/src/test/java/org/hibernate/validator/integration/wildfly/ejb/EjbJaxRsResource.java @@ -0,0 +1,30 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.integration.wildfly.ejb; + +import java.util.List; +import java.util.stream.Collectors; +import javax.ejb.Stateless; +import javax.validation.constraints.NotEmpty; +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.core.MediaType; + +@Stateless +@Path("/") +public class EjbJaxRsResource { + + @POST + @Path("put/list") + @Consumes(MediaType.APPLICATION_JSON) + public String putList(@NotEmpty List a) { + return "Hello bars " + a.stream().collect( Collectors.joining( ", " ) ); + } + +} + diff --git a/integration/src/test/java/org/hibernate/validator/integration/wildfly/ejb/JaxRsApplication.java b/integration/src/test/java/org/hibernate/validator/integration/wildfly/ejb/JaxRsApplication.java new file mode 100644 index 0000000000..9f1d7e830c --- /dev/null +++ b/integration/src/test/java/org/hibernate/validator/integration/wildfly/ejb/JaxRsApplication.java @@ -0,0 +1,20 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.integration.wildfly.ejb; + +import java.util.Collections; +import java.util.Set; +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; + +@ApplicationPath("") +public class JaxRsApplication extends Application { + @Override + public Set> getClasses() { + return Collections.emptySet(); + } +} diff --git a/pom.xml b/pom.xml index f7f7c81e30..9e0254d058 100644 --- a/pom.xml +++ b/pom.xml @@ -150,6 +150,7 @@ 3.2.5 1.2.4 1.3.5 + 2.1.6 1.0.1 @@ -168,6 +169,7 @@ 3.8.0 4.12 3.4 + 4.1.2 2.4.12 27.1-jre 4.3.10.RELEASE @@ -430,6 +432,11 @@ assertj-core ${version.org.assertj.assertj-core} + + io.rest-assured + rest-assured + ${version.io.rest-assured} + org.jboss.arquillian arquillian-bom @@ -442,6 +449,11 @@ jakarta.annotation-api ${version.jakarta.annotation-api} + + jakarta.ws.rs + jakarta.ws.rs-api + ${version.jakarta.ws.rs-api} + jakarta.interceptor jakarta.interceptor-api From a9c3d043d55d7910b31002f26e59619cb4190697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 22 Oct 2019 11:55:06 +0200 Subject: [PATCH 302/393] HV-1755 Make the BeanMetaDataClassNormalizer a bit safer --- .../internal/metadata/DefaultBeanMetaDataClassNormalizer.java | 2 +- .../validator/metadata/BeanMetaDataClassNormalizer.java | 2 +- .../predefinedscope/PredefinedScopeValidatorFactoryTest.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/DefaultBeanMetaDataClassNormalizer.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/DefaultBeanMetaDataClassNormalizer.java index a40a987786..14e6e40f37 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/DefaultBeanMetaDataClassNormalizer.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/DefaultBeanMetaDataClassNormalizer.java @@ -18,7 +18,7 @@ public class DefaultBeanMetaDataClassNormalizer implements BeanMetaDataClassNormalizer { @Override - public Class normalize(Class beanClass) { + public Class normalize(Class beanClass) { return beanClass; } } diff --git a/engine/src/main/java/org/hibernate/validator/metadata/BeanMetaDataClassNormalizer.java b/engine/src/main/java/org/hibernate/validator/metadata/BeanMetaDataClassNormalizer.java index e5d50b005f..a637f4c53b 100644 --- a/engine/src/main/java/org/hibernate/validator/metadata/BeanMetaDataClassNormalizer.java +++ b/engine/src/main/java/org/hibernate/validator/metadata/BeanMetaDataClassNormalizer.java @@ -35,5 +35,5 @@ public interface BeanMetaDataClassNormalizer { * @param beanClass the original bean class * @return the normalized class */ - Class normalize(Class beanClass); + Class normalize(Class beanClass); } diff --git a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java index a9309cc767..2e94a98448 100644 --- a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java @@ -455,7 +455,7 @@ private interface MyProxyInterface { private static class MyProxyInterfaceBeanMetaDataClassNormalizer implements BeanMetaDataClassNormalizer { @Override - public Class normalize(Class beanClass) { + public Class normalize(Class beanClass) { if ( MyProxyInterface.class.isAssignableFrom( beanClass ) ) { return beanClass.getSuperclass(); } From 3c9aa8d7e01288e0b14858d7828e6d8d3f52454f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 22 Oct 2019 12:22:30 +0200 Subject: [PATCH 303/393] HV-1755 Extend support for BeanMetadataClassNormalizer to all validator factories --- .../BaseHibernateValidatorConfiguration.java | 4 + ...dScopeHibernateValidatorConfiguration.java | 5 - .../engine/AbstractConfigurationImpl.java | 14 ++ .../PredefinedScopeConfigurationImpl.java | 13 -- .../ValidatorFactoryConfigurationHelper.java | 2 +- .../internal/engine/ValidatorFactoryImpl.java | 6 + .../metadata/BeanMetaDataManagerImpl.java | 22 +++- ...actoryBeanMetadataClassNormalizerTest.java | 120 ++++++++++++++++++ .../internal/engine/path/PathImplTest.java | 2 + .../metadata/BeanMetaDataManagerTest.java | 2 + .../aggregated/ExecutableMetaDataTest.java | 2 + .../aggregated/ParameterMetaDataTest.java | 3 + .../aggregated/PropertyMetaDataTest.java | 2 + 13 files changed, 172 insertions(+), 25 deletions(-) create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/ValidatorFactoryBeanMetadataClassNormalizerTest.java diff --git a/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java index d2f2c7030a..44955071e5 100644 --- a/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java @@ -25,6 +25,7 @@ import org.hibernate.validator.constraints.ParameterScriptAssert; import org.hibernate.validator.constraints.ScriptAssert; import org.hibernate.validator.spi.messageinterpolation.LocaleResolver; +import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider; import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; @@ -423,4 +424,7 @@ default S locales(Locale... locales) { */ @Incubating S localeResolver(LocaleResolver localeResolver); + + @Incubating + S beanMetaDataClassNormalizer(BeanMetaDataClassNormalizer beanMetaDataClassNormalizer); } diff --git a/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java index 50be18cc58..1f4a85118d 100644 --- a/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java @@ -9,8 +9,6 @@ import java.util.Locale; import java.util.Set; -import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; - /** * Extension of {@link HibernateValidatorConfiguration} with additional methods dedicated to defining the predefined * scope of bean validation e.g. validated classes, constraint validators... @@ -31,7 +29,4 @@ public interface PredefinedScopeHibernateValidatorConfiguration extends BaseHibe @Incubating @Deprecated PredefinedScopeHibernateValidatorConfiguration initializeLocales(Set locales); - - @Incubating - PredefinedScopeHibernateValidatorConfiguration beanMetaDataClassNormalizer(BeanMetaDataClassNormalizer beanMetaDataClassNormalizer); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java index 7c5d580c95..f9a20712d5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java @@ -57,6 +57,7 @@ import org.hibernate.validator.internal.xml.config.ValidationBootstrapParameters; import org.hibernate.validator.internal.xml.config.ValidationXmlParser; import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; +import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; import org.hibernate.validator.resourceloading.PlatformResourceBundleLocator; import org.hibernate.validator.spi.messageinterpolation.LocaleResolver; import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider; @@ -118,6 +119,7 @@ public abstract class AbstractConfigurationImpl locales = Collections.emptySet(); private Locale defaultLocale = Locale.getDefault(); private LocaleResolver localeResolver; + private BeanMetaDataClassNormalizer beanMetaDataClassNormalizer; protected AbstractConfigurationImpl(BootstrapState state) { this(); @@ -597,6 +599,18 @@ public Set> getDefaultValueExtractors() { return ValueExtractorManager.getDefaultValueExtractors(); } + @Override + public T beanMetaDataClassNormalizer( + BeanMetaDataClassNormalizer beanMetaDataClassNormalizer) { + this.beanMetaDataClassNormalizer = beanMetaDataClassNormalizer; + return thisAsT(); + } + + public BeanMetaDataClassNormalizer getBeanMetaDataClassNormalizer() { + return beanMetaDataClassNormalizer; + } + + public final Set getProgrammaticMappings() { return programmaticMappings; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java index 7c8be7fa88..3b8aadca30 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java @@ -18,7 +18,6 @@ import org.hibernate.validator.PredefinedScopeHibernateValidatorConfiguration; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.Contracts; -import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; /** * @author Guillaume Smet @@ -28,8 +27,6 @@ public class PredefinedScopeConfigurationImpl extends AbstractConfigurationImpl< private Set> beanClassesToInitialize; - private BeanMetaDataClassNormalizer beanMetaDataClassNormalizer; - public PredefinedScopeConfigurationImpl(BootstrapState state) { super( state ); } @@ -55,16 +52,6 @@ public PredefinedScopeHibernateValidatorConfiguration initializeLocales(Set hibernateSpecificConfig) { if ( hibernateSpecificConfig.getBeanMetaDataClassNormalizer() != null ) { return hibernateSpecificConfig.getBeanMetaDataClassNormalizer(); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java index 9fb2a7705b..581b597443 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java @@ -9,6 +9,7 @@ import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowMultipleCascadedValidationOnReturnValues; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowOverridingMethodAlterParameterConstraint; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowParallelMethodsDefineParameterConstraints; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineBeanMetaDataClassNormalizer; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineConstraintMappings; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineConstraintValidatorPayload; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineExternalClassLoader; @@ -59,6 +60,7 @@ import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.util.stereotypes.Immutable; import org.hibernate.validator.internal.util.stereotypes.ThreadSafe; +import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; @@ -122,6 +124,8 @@ public class ValidatorFactoryImpl implements HibernateValidatorFactory { private final JavaBeanHelper javaBeanHelper; + private final BeanMetaDataClassNormalizer beanMetadataClassNormalizer; + private final ValidationOrderGenerator validationOrderGenerator; public ValidatorFactoryImpl(ConfigurationState configurationState) { @@ -171,6 +175,7 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { this.executableHelper = new ExecutableHelper( typeResolutionHelper ); this.javaBeanHelper = new JavaBeanHelper( ValidatorFactoryConfigurationHelper.determineGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ), ValidatorFactoryConfigurationHelper.determinePropertyNodeNameProvider( hibernateSpecificConfig, properties, externalClassLoader ) ); + this.beanMetadataClassNormalizer = determineBeanMetaDataClassNormalizer( hibernateSpecificConfig ); // HV-302; don't load XmlMappingParser if not necessary if ( configurationState.getMappingStreams().isEmpty() ) { @@ -306,6 +311,7 @@ Validator createValidator(ConstraintValidatorFactory constraintValidatorFactory, executableHelper, validatorFactoryScopedContext.getParameterNameProvider(), javaBeanHelper, + beanMetadataClassNormalizer, validationOrderGenerator, buildMetaDataProviders(), methodValidationConfiguration diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java index 722d92aa2f..b9b3e6f8ae 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/BeanMetaDataManagerImpl.java @@ -34,6 +34,7 @@ import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper; import org.hibernate.validator.internal.util.stereotypes.Immutable; +import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; /** * This manager is in charge of providing all constraint related meta data @@ -92,6 +93,8 @@ public class BeanMetaDataManagerImpl implements BeanMetaDataManager { */ private final ExecutableHelper executableHelper; + private final BeanMetaDataClassNormalizer beanMetaDataClassNormalizer; + private final ValidationOrderGenerator validationOrderGenerator; /** @@ -105,12 +108,14 @@ public BeanMetaDataManagerImpl(ConstraintCreationContext constraintCreationConte ExecutableHelper executableHelper, ExecutableParameterNameProvider parameterNameProvider, JavaBeanHelper javaBeanHelper, + BeanMetaDataClassNormalizer beanMetaDataClassNormalizer, ValidationOrderGenerator validationOrderGenerator, List optionalMetaDataProviders, MethodValidationConfiguration methodValidationConfiguration) { this.constraintCreationContext = constraintCreationContext; this.executableHelper = executableHelper; this.parameterNameProvider = parameterNameProvider; + this.beanMetaDataClassNormalizer = beanMetaDataClassNormalizer; this.validationOrderGenerator = validationOrderGenerator; this.methodValidationConfiguration = methodValidationConfiguration; @@ -142,26 +147,31 @@ public BeanMetaDataManagerImpl(ConstraintCreationContext constraintCreationConte } @Override + // TODO Some of these casts from BeanMetadata to BeanMetadata may not be safe. + // Maybe we should return a wrapper around the BeanMetadata if the normalized class is different from beanClass? @SuppressWarnings("unchecked") public BeanMetaData getBeanMetaData(Class beanClass) { Contracts.assertNotNull( beanClass, MESSAGES.beanTypeCannotBeNull() ); + Class normalizedBeanClass = beanMetaDataClassNormalizer.normalize( beanClass ); + // First, let's do a simple lookup as it's the default case - BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataCache.get( beanClass ); + BeanMetaData beanMetaData = (BeanMetaData) beanMetaDataCache.get( normalizedBeanClass ); if ( beanMetaData != null ) { - return beanMetaData; + return (BeanMetaData) beanMetaData; } - beanMetaData = createBeanMetaData( beanClass ); - BeanMetaData previousBeanMetaData = (BeanMetaData) beanMetaDataCache.putIfAbsent( beanClass, beanMetaData ); + beanMetaData = createBeanMetaData( normalizedBeanClass ); + BeanMetaData previousBeanMetaData = + (BeanMetaData) beanMetaDataCache.putIfAbsent( normalizedBeanClass, beanMetaData ); // we return the previous value if not null if ( previousBeanMetaData != null ) { - return previousBeanMetaData; + return (BeanMetaData) previousBeanMetaData; } - return beanMetaData; + return (BeanMetaData) beanMetaData; } @Override diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/ValidatorFactoryBeanMetadataClassNormalizerTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/ValidatorFactoryBeanMetadataClassNormalizerTest.java new file mode 100644 index 0000000000..33e930c256 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/ValidatorFactoryBeanMetadataClassNormalizerTest.java @@ -0,0 +1,120 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.engine; + +import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.pathWith; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.ValidationException; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import javax.validation.constraints.Email; +import javax.validation.valueextraction.Unwrapping; + +import org.hibernate.validator.HibernateValidator; +import org.hibernate.validator.internal.engine.ValidatorFactoryImpl; +import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; + +import org.testng.annotations.Test; + +/** + * Test for {@link ValidatorFactoryImpl}. + * + * @author Gunnar Morling + */ +public class ValidatorFactoryBeanMetadataClassNormalizerTest { + + @Test(expectedExceptions = ValidationException.class, + expectedExceptionsMessageRegExp = ".*No suitable value extractor found for type interface java.util.List.*") + public void testBeanMetaDataClassNormalizerNoNormalizer() throws NoSuchMethodException { + ValidatorFactory validatorFactory = Validation.byDefaultProvider() + .configure() + .buildValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + + // As the proxy defines invalid constraints (see BeanProxy), we expect this to fail + validator.forExecutables().validateParameters( + new BeanProxy(), BeanProxy.class.getMethod( "setEmails", List.class ), + new Object[] { Arrays.asList( "notAnEmail" ) } + ); + } + + @Test + public void testBeanMetaDataClassNormalizer() throws NoSuchMethodException { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .beanMetaDataClassNormalizer( new MyProxyInterfaceBeanMetaDataClassNormalizer() ) + .buildValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + + Set> violations = validator.forExecutables().validateParameters( + new BeanProxy(), BeanProxy.class.getMethod( "setEmails", List.class ), + new Object[] { Arrays.asList( "notAnEmail" ) } + ); + + assertThat( violations ).containsOnlyViolations( + violationOf( Email.class ).withPropertyPath( + pathWith().method( "setEmails" ) + .parameter( "emails", 0 ) + .containerElement( "", true, null, 0, List.class, 0 ) + ) + ); + } + + private static class Bean { + + private List emails; + + public Bean() { + } + + public Bean(List emails) { + this.emails = emails; + } + + public List getEmails() { + return emails; + } + + public void setEmails(@Email(payload = Unwrapping.Unwrap.class) List emails) { + this.emails = emails; + } + } + + private interface MyProxyInterface { + } + + private static class MyProxyInterfaceBeanMetaDataClassNormalizer implements BeanMetaDataClassNormalizer { + + @Override + public Class normalize(Class beanClass) { + if ( MyProxyInterface.class.isAssignableFrom( beanClass ) ) { + return beanClass.getSuperclass(); + } + + return beanClass; + } + } + + private static class BeanProxy extends Bean implements MyProxyInterface { + // The proxy dropped the generics, but kept constraint annotations, + // which will cause trouble unless its metadata is ignored. + @Override + @SuppressWarnings("unchecked") + public void setEmails(@Email(payload = Unwrapping.Unwrap.class) List emails) { + super.setEmails( emails ); + } + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java index 6c4a45fcbd..074645b79f 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/path/PathImplTest.java @@ -35,6 +35,7 @@ import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl; +import org.hibernate.validator.internal.metadata.DefaultBeanMetaDataClassNormalizer; import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; @@ -198,6 +199,7 @@ public void testCreationOfExecutablePath() throws Exception { new ExecutableHelper( new TypeResolutionHelper() ), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy(), new DefaultPropertyNodeNameProvider() ), + new DefaultBeanMetaDataClassNormalizer(), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java index 55ec5dd048..d83b3ce7fe 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/BeanMetaDataManagerTest.java @@ -26,6 +26,7 @@ import org.hibernate.validator.internal.engine.MethodValidationConfiguration; import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl; +import org.hibernate.validator.internal.metadata.DefaultBeanMetaDataClassNormalizer; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; @@ -57,6 +58,7 @@ public void setUpBeanMetaDataManager() { new ExecutableHelper( new TypeResolutionHelper() ), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy(), new DefaultPropertyNodeNameProvider() ), + new DefaultBeanMetaDataClassNormalizer(), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java index dee545145b..f8a24308ed 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ExecutableMetaDataTest.java @@ -29,6 +29,7 @@ import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl; +import org.hibernate.validator.internal.metadata.DefaultBeanMetaDataClassNormalizer; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; @@ -63,6 +64,7 @@ public void setupBeanMetaData() { new ExecutableHelper( new TypeResolutionHelper() ), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy(), new DefaultPropertyNodeNameProvider() ), + new DefaultBeanMetaDataClassNormalizer(), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java index cb8b39c6f1..e9a97a095e 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/ParameterMetaDataTest.java @@ -30,6 +30,7 @@ import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl; +import org.hibernate.validator.internal.metadata.DefaultBeanMetaDataClassNormalizer; import org.hibernate.validator.internal.metadata.aggregated.BeanMetaData; import org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData; import org.hibernate.validator.internal.metadata.aggregated.ParameterMetaData; @@ -63,6 +64,7 @@ public void setupBeanMetaData() { new ExecutableHelper( new TypeResolutionHelper() ), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy(), new DefaultPropertyNodeNameProvider() ), + new DefaultBeanMetaDataClassNormalizer(), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() @@ -132,6 +134,7 @@ public void parameterNameInInheritanceHierarchy() throws Exception { new ExecutableHelper( new TypeResolutionHelper() ), new ExecutableParameterNameProvider( new SkewedParameterNameProvider() ), new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy(), new DefaultPropertyNodeNameProvider() ), + new DefaultBeanMetaDataClassNormalizer(), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java index cd83158b14..f73cb77d7d 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/aggregated/PropertyMetaDataTest.java @@ -23,6 +23,7 @@ import org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator; import org.hibernate.validator.internal.metadata.BeanMetaDataManager; import org.hibernate.validator.internal.metadata.BeanMetaDataManagerImpl; +import org.hibernate.validator.internal.metadata.DefaultBeanMetaDataClassNormalizer; import org.hibernate.validator.internal.metadata.aggregated.PropertyMetaData; import org.hibernate.validator.internal.metadata.provider.MetaDataProvider; import org.hibernate.validator.internal.properties.DefaultGetterPropertySelectionStrategy; @@ -47,6 +48,7 @@ public void setupBeanMetaDataManager() { new ExecutableHelper( new TypeResolutionHelper() ), new ExecutableParameterNameProvider( new DefaultParameterNameProvider() ), new JavaBeanHelper( new DefaultGetterPropertySelectionStrategy(), new DefaultPropertyNodeNameProvider() ), + new DefaultBeanMetaDataClassNormalizer(), new ValidationOrderGenerator(), Collections.emptyList(), new MethodValidationConfiguration.Builder().build() From cff92d84b0e272f6f09341479b6767fb34315e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 22 Oct 2019 15:05:48 +0200 Subject: [PATCH 304/393] HV-1755 Log the BeanMetaDataClassNormalizer at the debug level when set Similarly to other configuration options such as the propertyNodeNameProvider. --- .../internal/engine/AbstractConfigurationImpl.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java index f9a20712d5..f2a4b11465 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java @@ -600,8 +600,13 @@ public Set> getDefaultValueExtractors() { } @Override - public T beanMetaDataClassNormalizer( - BeanMetaDataClassNormalizer beanMetaDataClassNormalizer) { + public T beanMetaDataClassNormalizer(BeanMetaDataClassNormalizer beanMetaDataClassNormalizer) { + if ( LOG.isDebugEnabled() ) { + if ( beanMetaDataClassNormalizer != null ) { + LOG.debug( "Setting custom BeanMetaDataClassNormalizer of type " + beanMetaDataClassNormalizer.getClass() + .getName() ); + } + } this.beanMetaDataClassNormalizer = beanMetaDataClassNormalizer; return thisAsT(); } From 548396b1216d3bcb8b4db21f5fc6a131165bd271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Thu, 16 Jan 2020 17:14:44 +0100 Subject: [PATCH 305/393] HV-1755 Allow bean metadata class normalizers to be provided to the CDI extension --- .../cdi/internal/ValidatorFactoryBean.java | 21 +++++++++++++++++++ .../validator/cdi/spi/BeanNames.java | 16 ++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 cdi/src/main/java/org/hibernate/validator/cdi/spi/BeanNames.java diff --git a/cdi/src/main/java/org/hibernate/validator/cdi/internal/ValidatorFactoryBean.java b/cdi/src/main/java/org/hibernate/validator/cdi/internal/ValidatorFactoryBean.java index 342342f282..632a9e7750 100644 --- a/cdi/src/main/java/org/hibernate/validator/cdi/internal/ValidatorFactoryBean.java +++ b/cdi/src/main/java/org/hibernate/validator/cdi/internal/ValidatorFactoryBean.java @@ -22,6 +22,8 @@ import javax.enterprise.context.ApplicationScoped; import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.Instance; +import javax.enterprise.inject.literal.NamedLiteral; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; import javax.enterprise.inject.spi.InjectionPoint; @@ -37,12 +39,15 @@ import javax.validation.ValidatorFactory; import javax.validation.valueextraction.ValueExtractor; +import org.hibernate.validator.HibernateValidatorConfiguration; +import org.hibernate.validator.cdi.spi.BeanNames; import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorDescriptor; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.classhierarchy.ClassHierarchyHelper; import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader; import org.hibernate.validator.internal.util.privilegedactions.GetInstancesFromServiceLoader; import org.hibernate.validator.internal.util.privilegedactions.LoadClass; +import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; /** * A {@link Bean} representing a {@link ValidatorFactory}. There is one instance of this type representing the default @@ -126,6 +131,22 @@ public ValidatorFactory create(CreationalContext ctx) { config.parameterNameProvider( createParameterNameProvider( config ) ); config.clockProvider( createClockProvider( config ) ); + if ( config instanceof HibernateValidatorConfiguration ) { + HibernateValidatorConfiguration hvConfig = (HibernateValidatorConfiguration) config; + Instance beanMetaDataClassNormalizerInstance = + beanManager.createInstance() + .select( + BeanMetaDataClassNormalizer.class, + NamedLiteral.of( BeanNames.BEAN_META_DATA_CLASS_NORMALIZER ) + ); + if ( beanMetaDataClassNormalizerInstance.isResolvable() ) { + BeanMetaDataClassNormalizer normalizer = beanMetaDataClassNormalizerInstance.get(); + destructibleResources.add( new DestructibleBeanInstance<>( beanManager, normalizer ) ); + + hvConfig.beanMetaDataClassNormalizer( normalizer ); + } + } + addValueExtractorBeans( config ); return config.buildValidatorFactory(); diff --git a/cdi/src/main/java/org/hibernate/validator/cdi/spi/BeanNames.java b/cdi/src/main/java/org/hibernate/validator/cdi/spi/BeanNames.java new file mode 100644 index 0000000000..cb9f1da7f5 --- /dev/null +++ b/cdi/src/main/java/org/hibernate/validator/cdi/spi/BeanNames.java @@ -0,0 +1,16 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.cdi.spi; + +public final class BeanNames { + + private BeanNames() { + } + + public static final String BEAN_META_DATA_CLASS_NORMALIZER = "hibernate-validator-bean-meta-data-class-normalizer"; + +} From 2a01faec4f62ba12e8b583389cd32b8e95ef3fd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Thu, 16 Jan 2020 18:12:50 +0100 Subject: [PATCH 306/393] HV-1755 Test bean metadata class normalizers provided to the CDI extension --- .../cdi/internal/ValidatorFactoryBean.java | 2 +- .../CustomProxy.java | 10 ++ ...ustomProxyBeanMetaDataClassNormalizer.java | 89 +++++++++++++++ ...anMetadataClassNormalizerCdiExtension.java | 18 ++++ ...ovidedBeanMetadataClassNormalizerTest.java | 102 ++++++++++++++++++ 5 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 cdi/src/test/java/org/hibernate/validator/test/cdi/internal/beanmetadataclassnormalizer/CustomProxy.java create mode 100644 cdi/src/test/java/org/hibernate/validator/test/cdi/internal/beanmetadataclassnormalizer/CustomProxyBeanMetaDataClassNormalizer.java create mode 100644 cdi/src/test/java/org/hibernate/validator/test/cdi/internal/beanmetadataclassnormalizer/CustomProxyBeanMetadataClassNormalizerCdiExtension.java create mode 100644 cdi/src/test/java/org/hibernate/validator/test/cdi/internal/beanmetadataclassnormalizer/ExtensionProvidedBeanMetadataClassNormalizerTest.java diff --git a/cdi/src/main/java/org/hibernate/validator/cdi/internal/ValidatorFactoryBean.java b/cdi/src/main/java/org/hibernate/validator/cdi/internal/ValidatorFactoryBean.java index 632a9e7750..eec74f1042 100644 --- a/cdi/src/main/java/org/hibernate/validator/cdi/internal/ValidatorFactoryBean.java +++ b/cdi/src/main/java/org/hibernate/validator/cdi/internal/ValidatorFactoryBean.java @@ -142,7 +142,7 @@ public ValidatorFactory create(CreationalContext ctx) { if ( beanMetaDataClassNormalizerInstance.isResolvable() ) { BeanMetaDataClassNormalizer normalizer = beanMetaDataClassNormalizerInstance.get(); destructibleResources.add( new DestructibleBeanInstance<>( beanManager, normalizer ) ); - + hvConfig.beanMetaDataClassNormalizer( normalizer ); } } diff --git a/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/beanmetadataclassnormalizer/CustomProxy.java b/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/beanmetadataclassnormalizer/CustomProxy.java new file mode 100644 index 0000000000..5bb6b09212 --- /dev/null +++ b/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/beanmetadataclassnormalizer/CustomProxy.java @@ -0,0 +1,10 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.cdi.internal.beanmetadataclassnormalizer; + +public interface CustomProxy { +} diff --git a/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/beanmetadataclassnormalizer/CustomProxyBeanMetaDataClassNormalizer.java b/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/beanmetadataclassnormalizer/CustomProxyBeanMetaDataClassNormalizer.java new file mode 100644 index 0000000000..2e59a3819e --- /dev/null +++ b/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/beanmetadataclassnormalizer/CustomProxyBeanMetaDataClassNormalizer.java @@ -0,0 +1,89 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.cdi.internal.beanmetadataclassnormalizer; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.Set; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.literal.NamedLiteral; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.InjectionPoint; + +import org.hibernate.validator.cdi.spi.BeanNames; +import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; + + +public class CustomProxyBeanMetaDataClassNormalizer + implements BeanMetaDataClassNormalizer, Bean { + + @Override + public Class normalize(Class clazz) { + if ( CustomProxy.class.isAssignableFrom( clazz ) ) { + return clazz.getSuperclass(); + } + return clazz; + } + + @Override + public Class getBeanClass() { + return BeanMetaDataClassNormalizer.class; + } + + @Override + public Set getInjectionPoints() { + return Collections.emptySet(); + } + + @Override + public boolean isNullable() { + return false; + } + + @Override + public BeanMetaDataClassNormalizer create(CreationalContext creationalContext) { + return new CustomProxyBeanMetaDataClassNormalizer(); + } + + @Override + public void destroy(BeanMetaDataClassNormalizer beanMetaDataClassNormalizer, + CreationalContext creationalContext) { + // Nothing to do + } + + @Override + public Set getTypes() { + return Collections.singleton( BeanMetaDataClassNormalizer.class ); + } + + @Override + public Set getQualifiers() { + return Collections.singleton( NamedLiteral.of( BeanNames.BEAN_META_DATA_CLASS_NORMALIZER ) ); + } + + @Override + public Class getScope() { + return ApplicationScoped.class; + } + + @Override + public String getName() { + return BeanNames.BEAN_META_DATA_CLASS_NORMALIZER; + } + + @Override + public Set> getStereotypes() { + return Collections.emptySet(); + } + + @Override + public boolean isAlternative() { + return false; + } +} diff --git a/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/beanmetadataclassnormalizer/CustomProxyBeanMetadataClassNormalizerCdiExtension.java b/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/beanmetadataclassnormalizer/CustomProxyBeanMetadataClassNormalizerCdiExtension.java new file mode 100644 index 0000000000..7ea42a77f8 --- /dev/null +++ b/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/beanmetadataclassnormalizer/CustomProxyBeanMetadataClassNormalizerCdiExtension.java @@ -0,0 +1,18 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.cdi.internal.beanmetadataclassnormalizer; + +import javax.enterprise.event.Observes; +import javax.enterprise.inject.spi.AfterBeanDiscovery; +import javax.enterprise.inject.spi.Extension; + +public class CustomProxyBeanMetadataClassNormalizerCdiExtension implements Extension { + + public void addEjbProxyNormalizer(@Observes AfterBeanDiscovery afterBeanDiscovery) { + afterBeanDiscovery.addBean( new CustomProxyBeanMetaDataClassNormalizer() ); + } +} diff --git a/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/beanmetadataclassnormalizer/ExtensionProvidedBeanMetadataClassNormalizerTest.java b/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/beanmetadataclassnormalizer/ExtensionProvidedBeanMetadataClassNormalizerTest.java new file mode 100644 index 0000000000..e7b7778506 --- /dev/null +++ b/cdi/src/test/java/org/hibernate/validator/test/cdi/internal/beanmetadataclassnormalizer/ExtensionProvidedBeanMetadataClassNormalizerTest.java @@ -0,0 +1,102 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.cdi.internal.beanmetadataclassnormalizer; + +import static org.assertj.core.api.Assertions.assertThat; + +import javax.inject.Inject; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import javax.validation.constraints.DecimalMax; +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.cdi.HibernateValidator; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.testng.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; + +import org.testng.annotations.Test; + +public class ExtensionProvidedBeanMetadataClassNormalizerTest extends Arquillian { + + @Deployment + public static JavaArchive createDeployment() { + return ShrinkWrap.create( JavaArchive.class ) + .addAsManifestResource( EmptyAsset.INSTANCE, "beans.xml" ) + // Register the CDI extension that provides the normalizer bean + .addAsManifestResource( + new StringAsset( CustomProxyBeanMetadataClassNormalizerCdiExtension.class.getName() ), + "services/javax.enterprise.inject.spi.Extension" + ); + } + + @HibernateValidator + @Inject + ValidatorFactory validatorFactory; + + @HibernateValidator + @Inject + Validator validator; + + @Inject + ValidatorFactory defaultValidatorFactory; + + @Inject + Validator defaultValidator; + + @Test + public void testProxyMetadataIgnoredWithQualifiedValidator() throws Exception { + assertThat( validator ).isNotNull(); + doTest( validator ); + } + + @Test + public void testProxyMetadataIgnoredWithDefaultValidator() throws Exception { + assertThat( defaultValidator ).isNotNull(); + doTest( defaultValidator ); + } + + @Test + public void testProxyMetadataIgnoredWithQualifiedValidatorFactory() throws Exception { + assertThat( validatorFactory ).isNotNull(); + doTest( validatorFactory.getValidator() ); + } + + @Test + public void testProxyMetadataIgnoredWithDefaultValidatorFactory() throws Exception { + assertThat( defaultValidatorFactory ).isNotNull(); + doTest( defaultValidatorFactory.getValidator() ); + } + + private void doTest(Validator validator) { + assertThat( validator ).isNotNull(); + /* + * Even though we pass an instance of the proxy class that has invalid annotations, + * we expect those to be ignored + * because of the class normalizer we defined. + */ + assertThat( validator.validate( new TestEntityProxy() ) ).hasSize( 1 ); + } + + public static class TestEntity { + @NotNull + private String foo; + } + + public static class TestEntityProxy extends TestEntity implements CustomProxy { + /* + * This is invalid, but should be ignored because it's defined in a proxy class which gets ignored + * because of the class normalizer we defined. + */ + @DecimalMax(value = "foo") + private String foo; + } +} From 6a42a82bbf55132359c2ecfb3bbbfb5d6fe93ffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Thu, 23 Jan 2020 09:19:41 +0100 Subject: [PATCH 307/393] HV-1755 Ignore EjbIT pending its resolution in WildFly See HV-1754. --- .../validator/integration/wildfly/ejb/EjbIT.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/integration/src/test/java/org/hibernate/validator/integration/wildfly/ejb/EjbIT.java b/integration/src/test/java/org/hibernate/validator/integration/wildfly/ejb/EjbIT.java index 35c7404f15..da4fef6bb3 100644 --- a/integration/src/test/java/org/hibernate/validator/integration/wildfly/ejb/EjbIT.java +++ b/integration/src/test/java/org/hibernate/validator/integration/wildfly/ejb/EjbIT.java @@ -23,6 +23,11 @@ import io.restassured.http.ContentType; import org.testng.annotations.Test; +/** + * This is a reproducer for WFL-11566, but fixing the problem requires changes in WildFly. + * Thus it is ignored for now. + * See HV-1754. + */ public class EjbIT extends AbstractArquillianIT { private static final String WAR_FILE_NAME = EjbIT.class.getSimpleName() + ".war"; private static final String APPLICATION_PATH = EjbIT.class.getSimpleName(); @@ -42,7 +47,7 @@ public static WebArchive createTestArchive() throws Exception { ); } - @Test + @Test(enabled = false) @RunAsClient public void testRestEasyWorks() { given() @@ -55,7 +60,7 @@ public void testRestEasyWorks() { .body( equalTo( "Hello bars a, b, c" ) ); } - @Test + @Test(enabled = false) @RunAsClient public void testValidationWorks() { given() From 32e58c9ee36667ca510f88a021f9af1e4591400f Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 9 Apr 2020 14:39:43 +0200 Subject: [PATCH 308/393] HV-1763 Adjust performance profiles and add a benchmark for executable --- performance/pom.xml | 13 +- .../simple/ExecutableValidation.java | 158 ++++++++++++++++++ 2 files changed, 166 insertions(+), 5 deletions(-) create mode 100644 performance/src/main/java/org/hibernate/validator/performance/simple/ExecutableValidation.java diff --git a/performance/pom.xml b/performance/pom.xml index a00d6b54fe..ff638ad2d1 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -21,6 +21,9 @@ Hibernate Validator performance tests. + + true + From 65c54b2523a40678ea13d3edbf70408ae18e1848 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 10 Apr 2020 09:59:03 +0200 Subject: [PATCH 313/393] HV-1765 Upgrade WildFly versions to 18.0.1 and 19.0.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 1157f3adf1..2dcdfd1436 100644 --- a/pom.xml +++ b/pom.xml @@ -122,9 +122,9 @@ 2.1.0.Final - 18.0.0.Final + 19.0.0.Final - 17.0.1.Final + 18.0.1.Final ${version.wildfly} From 19699572cc7904990bc9ea44e51fae023f3a2c35 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 10 Apr 2020 12:06:51 +0200 Subject: [PATCH 314/393] HV-1765 Adjust javafx module installation for incontainer tests --- tck-runner/src/script/updateStandaloneXml.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tck-runner/src/script/updateStandaloneXml.groovy b/tck-runner/src/script/updateStandaloneXml.groovy index 258f1527f0..766bdff874 100644 --- a/tck-runner/src/script/updateStandaloneXml.groovy +++ b/tck-runner/src/script/updateStandaloneXml.groovy @@ -18,7 +18,7 @@ standaloneXml = new File( getPropertyValue('wildfly.target-dir'), 'standalone/co println "[INFO] Add javafx.api as global module" processFileInplace( standaloneXml ) { text -> - text.replaceAll( //, '\n \n \n ' ) + text.replaceAll( //, '\n \n \n ' ) } println "[INFO] ------------------------------------------------------------------------"; From 9f0b1498e8040703c8afd1acfcbf91ac759edef1 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 10 Apr 2020 11:22:27 +0000 Subject: [PATCH 315/393] [Jenkins release job] README.md updated by release build 6.1.3.Final --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ab0cabbb14..f779246c41 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hibernate Validator -*Version: 6.1.2.Final - 31-01-2020* +*Version: 6.1.3.Final - 10-04-2020* ## What is it? @@ -35,7 +35,7 @@ Logging will delegate any log requests to that provider. org.hibernate.validator hibernate-validator - 6.1.2.Final + 6.1.3.Final You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. @@ -54,7 +54,7 @@ extension by adding the following dependency: org.hibernate.validator hibernate-validator-cdi - 6.1.2.Final + 6.1.3.Final * _hibernate-validator-annotation-processor-<version>.jar_ is an optional jar which can be integrated with your build From ec2d496ffb2d82950ac081f76d7369545a5adcea Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 10 Apr 2020 11:22:27 +0000 Subject: [PATCH 316/393] [Jenkins release job] changelog.txt updated by release build 6.1.3.Final --- changelog.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/changelog.txt b/changelog.txt index c9510ff45d..ca5e7e0070 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,22 @@ Hibernate Validator Changelog ============================= +6.1.3.Final (10-04-2020) +------------------------- + +** Bug + * HV-1758 - translations - Extra dollar sign in validation messages for ModCheck + +** Improvement + * HV-1763 - engine - Improve performances of ExecutableHelper#getSignature + +** New Feature + * HV-1755 - engine - Introduce the notion of BeanMetaDataClassNormalizer in the standard ValidatorFactory + +** Task + * HV-1765 - integration - Upgrade WildFly versions to 18.0.1.Final and 19.0.0.Final + * HV-1764 - tests - Upgrade Jackson test dependencies to 2.10.3 + 6.1.2.Final (31-01-2020) ------------------------- From 0276343b8b0beeeb5bf33eb11e11eede91997670 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 10 Apr 2020 11:22:34 +0000 Subject: [PATCH 317/393] [Jenkins release job] Preparing release 6.1.3.Final --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 09b51bfb95..b25eb7b574 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index e5bd46024b..1d0b0dabe6 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index 43e9a6e463..cac39ef0d9 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index abccaa3efc..bd1fbf7222 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 82469be62b..1d2a3b08af 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index 51bf49a7da..4f3aded4da 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 5053e46480..53f5f9f8bc 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index f8268c9013..3abb7802af 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 1143f70ee5..547acbcac0 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 1ca38b61c0..86c46b4044 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 2f94c135be..6af6458a3a 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index 312d1f5749..72e6463d48 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index ff638ad2d1..b7c490d717 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/pom.xml b/pom.xml index 2dcdfd1436..2ebb2bc3bb 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 4bdb3a8d19..6d14318f13 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.3-SNAPSHOT + 6.1.3.Final org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index f75663d079..33940a623a 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.3-SNAPSHOT + 6.1.3.Final org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index 4af4e218e1..21af294406 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.3-SNAPSHOT + 6.1.3.Final org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index 956fc14494..0f21187879 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.3-SNAPSHOT + 6.1.3.Final org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 89f763fc8b..459823284f 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 70eeff7700..9782b4a65c 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index a7a3dfe691..03cf20bdd5 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final hibernate-validator-test-utils From e7481a8bc8e18a92cb2d5521ae86125349655c3a Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 10 Apr 2020 11:25:28 +0000 Subject: [PATCH 318/393] [Jenkins release job] Preparing next development iteration --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index b25eb7b574..59c19db310 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 1d0b0dabe6..b4dd834c9f 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index cac39ef0d9..4deda9adc1 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index bd1fbf7222..10f2fac979 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 1d2a3b08af..b7d925afb4 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index 4f3aded4da..f68f0ecde1 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 53f5f9f8bc..37bc261fdd 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index 3abb7802af..f6b0817a02 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 547acbcac0..7d627d5dbd 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 86c46b4044..a7dc8e5d0f 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 6af6458a3a..9e5867237d 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index 72e6463d48..9c6b9294c3 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index b7c490d717..a79626ba2b 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 2ebb2bc3bb..2e47778273 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 6d14318f13..33822787af 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.3.Final + 6.1.4-SNAPSHOT org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index 33940a623a..6054919232 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.3.Final + 6.1.4-SNAPSHOT org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index 21af294406..297bf58af5 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.3.Final + 6.1.4-SNAPSHOT org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index 0f21187879..9dddc1ac27 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.3.Final + 6.1.4-SNAPSHOT org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 459823284f..a14f5a2dbe 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 9782b4a65c..447ae37af8 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 03cf20bdd5..330474de80 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT hibernate-validator-test-utils From 94364343b598bc37e2bd5d18a486970c86668146 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 15 Apr 2020 20:03:21 +0200 Subject: [PATCH 319/393] HV-1767 Reduce the overhead of ConstraintHelper initialization in the predefined scope case --- ...dScopeHibernateValidatorConfiguration.java | 3 + .../PredefinedScopeConfigurationImpl.java | 13 + .../PredefinedScopeValidatorFactoryImpl.java | 2 +- .../internal/engine/ValidatorFactoryImpl.java | 2 +- .../metadata/core/BuiltinConstraint.java | 139 +++ .../metadata/core/ConstraintHelper.java | 853 ++++++++++-------- .../PredefinedScopeAllConstraintsTest.java | 457 ++++++++++ ...ssionLanguageMessageInterpolationTest.java | 4 +- ...ResourceBundleMessageInterpolatorTest.java | 8 +- .../metadata/core/ConstraintHelperTest.java | 2 +- .../metadata/core/MetaConstraintTest.java | 2 +- .../PredefinedScopeValidatorFactoryTest.java | 6 + ...nstraintValidatorInitializationHelper.java | 4 +- 13 files changed, 1092 insertions(+), 403 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/metadata/core/BuiltinConstraint.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/PredefinedScopeAllConstraintsTest.java diff --git a/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java index 1f4a85118d..a295e88430 100644 --- a/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java @@ -20,6 +20,9 @@ @Incubating public interface PredefinedScopeHibernateValidatorConfiguration extends BaseHibernateValidatorConfiguration { + @Incubating + PredefinedScopeHibernateValidatorConfiguration builtinConstraints(Set constraints); + @Incubating PredefinedScopeHibernateValidatorConfiguration initializeBeanMetaData(Set> beanClassesToInitialize); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java index 3b8aadca30..15b239e627 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java @@ -8,6 +8,7 @@ import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES; +import java.util.Collections; import java.util.Locale; import java.util.Set; @@ -25,6 +26,8 @@ public class PredefinedScopeConfigurationImpl extends AbstractConfigurationImpl implements PredefinedScopeHibernateValidatorConfiguration, ConfigurationState { + private Set builtinConstraints = Collections.emptySet(); + private Set> beanClassesToInitialize; public PredefinedScopeConfigurationImpl(BootstrapState state) { @@ -35,12 +38,22 @@ public PredefinedScopeConfigurationImpl(ValidationProvider validationProvider super( validationProvider ); } + @Override + public PredefinedScopeHibernateValidatorConfiguration builtinConstraints(Set constraints) { + this.builtinConstraints = CollectionHelper.toImmutableSet( constraints ); + return thisAsT(); + } + @Override public PredefinedScopeHibernateValidatorConfiguration initializeBeanMetaData(Set> beanMetaDataToInitialize) { beanClassesToInitialize = CollectionHelper.toImmutableSet( beanMetaDataToInitialize ); return thisAsT(); } + public Set getBuiltinConstraints() { + return builtinConstraints; + } + public Set> getBeanClassesToInitialize() { return beanClassesToInitialize; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java index 8785843e17..2eddf9153f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java @@ -132,7 +132,7 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState this.getterPropertySelectionStrategy = ValidatorFactoryConfigurationHelper.determineGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ); this.valueExtractorManager = new ValueExtractorManager( configurationState.getValueExtractors() ); - ConstraintHelper constraintHelper = new ConstraintHelper(); + ConstraintHelper constraintHelper = ConstraintHelper.forBuiltinConstraints( hibernateSpecificConfig.getBuiltinConstraints() ); TypeResolutionHelper typeResolutionHelper = new TypeResolutionHelper(); ConstraintCreationContext constraintCreationContext = new ConstraintCreationContext( constraintHelper, diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java index 581b597443..918177fd46 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java @@ -167,7 +167,7 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { this.validationOrderGenerator = new ValidationOrderGenerator(); ValueExtractorManager valueExtractorManager = new ValueExtractorManager( configurationState.getValueExtractors() ); - ConstraintHelper constraintHelper = new ConstraintHelper(); + ConstraintHelper constraintHelper = ConstraintHelper.forAllBuiltinConstraints(); TypeResolutionHelper typeResolutionHelper = new TypeResolutionHelper(); this.constraintCreationContext = new ConstraintCreationContext( constraintHelper, constraintValidatorManager, typeResolutionHelper, valueExtractorManager ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/BuiltinConstraint.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/BuiltinConstraint.java new file mode 100644 index 0000000000..9a7197359b --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/BuiltinConstraint.java @@ -0,0 +1,139 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.metadata.core; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * The list of built-in constraints. + *

    + * We are not using the class directly to avoid loading the class if possible. + *

    + * In the case of composing constraints, you need to define the dependencies manually. + *

    + * When adding a new built-in constraint, please add a test in {@code MessagePropertiesTest} and + * {@code PredefinedScopeAllConstraintsTest}. + * + * @author Guillaume Smet + */ +enum BuiltinConstraint { + + // Specification constraints + JAVAX_VALIDATION_CONSTRAINTS_ASSERT_FALSE("javax.validation.constraints.AssertFalse"), + JAVAX_VALIDATION_CONSTRAINTS_ASSERT_TRUE("javax.validation.constraints.AssertTrue"), + JAVAX_VALIDATION_CONSTRAINTS_DECIMAL_MAX("javax.validation.constraints.DecimalMax"), + JAVAX_VALIDATION_CONSTRAINTS_DECIMAL_MIN("javax.validation.constraints.DecimalMin"), + JAVAX_VALIDATION_CONSTRAINTS_DIGITS("javax.validation.constraints.Digits"), + JAVAX_VALIDATION_CONSTRAINTS_EMAIL("javax.validation.constraints.Email"), + JAVAX_VALIDATION_CONSTRAINTS_FUTURE("javax.validation.constraints.Future"), + JAVAX_VALIDATION_CONSTRAINTS_FUTURE_OR_PRESENT("javax.validation.constraints.FutureOrPresent"), + JAVAX_VALIDATION_CONSTRAINTS_MIN("javax.validation.constraints.Min"), + JAVAX_VALIDATION_CONSTRAINTS_MAX("javax.validation.constraints.Max"), + JAVAX_VALIDATION_CONSTRAINTS_NEGATIVE("javax.validation.constraints.Negative"), + JAVAX_VALIDATION_CONSTRAINTS_NEGATIVE_OR_ZERO("javax.validation.constraints.NegativeOrZero"), + JAVAX_VALIDATION_CONSTRAINTS_NOT_BLANK("javax.validation.constraints.NotBlank"), + JAVAX_VALIDATION_CONSTRAINTS_NOT_EMPTY("javax.validation.constraints.NotEmpty"), + JAVAX_VALIDATION_CONSTRAINTS_NOT_NULL("javax.validation.constraints.NotNull"), + JAVAX_VALIDATION_CONSTRAINTS_NULL("javax.validation.constraints.Null"), + JAVAX_VALIDATION_CONSTRAINTS_PAST("javax.validation.constraints.Past"), + JAVAX_VALIDATION_CONSTRAINTS_PAST_OR_PRESENT("javax.validation.constraints.PastOrPresent"), + JAVAX_VALIDATION_CONSTRAINTS_PATTERN("javax.validation.constraints.Pattern"), + JAVAX_VALIDATION_CONSTRAINTS_POSITIVE("javax.validation.constraints.Positive"), + JAVAX_VALIDATION_CONSTRAINTS_POSITIVE_OR_ZERO("javax.validation.constraints.PositiveOrZero"), + JAVAX_VALIDATION_CONSTRAINTS_SIZE("javax.validation.constraints.Size"), + + // Hibernate Validator specific constraints + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CODE_POINT_LENGTH("org.hibernate.validator.constraints.CodePointLength"), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CURRENCY("org.hibernate.validator.constraints.Currency"), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_EMAIL("org.hibernate.validator.constraints.Email", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_PATTERN ) ), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_ISBN("org.hibernate.validator.constraints.ISBN"), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_LENGTH("org.hibernate.validator.constraints.Length"), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_LUHN_CHECK("org.hibernate.validator.constraints.LuhnCheck"), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CREDIT_CARD_NUMBER("org.hibernate.validator.constraints.CreditCardNumber", + Arrays.asList( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_LUHN_CHECK ) ), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD10_CHECK("org.hibernate.validator.constraints.Mod10Check"), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD11_CHECK("org.hibernate.validator.constraints.Mod11Check"), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD_CHECK("org.hibernate.validator.constraints.ModCheck"), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_EAN("org.hibernate.validator.constraints.EAN", Arrays.asList( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD10_CHECK ) ), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NOT_BLANK("org.hibernate.validator.constraints.NotBlank", + Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_NOT_NULL ) ), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NOT_EMPTY("org.hibernate.validator.constraints.NotEmpty", + Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_NOT_NULL, JAVAX_VALIDATION_CONSTRAINTS_SIZE )), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PARAMETER_SCRIPT_ASSERT("org.hibernate.validator.constraints.ParameterScriptAssert"), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_RANGE("org.hibernate.validator.constraints.Range", + Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_MIN, JAVAX_VALIDATION_CONSTRAINTS_MAX )), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_SAFE_HTML("org.hibernate.validator.constraints.SafeHtml"), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_SCRIPT_ASSERT("org.hibernate.validator.constraints.ScriptAssert"), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_URL("org.hibernate.validator.constraints.URL", + Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_PATTERN )), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_UNIQUE_ELEMENTS("org.hibernate.validator.constraints.UniqueElements"), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_CNPJ("org.hibernate.validator.constraints.br.CNPJ", + Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_PATTERN )), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_CPF("org.hibernate.validator.constraints.br.CPF", + Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_PATTERN )), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_TITULO_ELEITORAL("org.hibernate.validator.constraints.br.TituloEleitoral", + Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_PATTERN, ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD11_CHECK ) ), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_NIP("org.hibernate.validator.constraints.pl.NIP"), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_PESEL("org.hibernate.validator.constraints.pl.PESEL"), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_REGON("org.hibernate.validator.constraints.pl.REGON"), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_TIME_DURATION_MAX("org.hibernate.validator.constraints.time.DurationMax"), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_TIME_DURATION_MIN("org.hibernate.validator.constraints.time.DurationMin"); + + private static final Map> CONSTRAINT_MAPPING; + + static { + CONSTRAINT_MAPPING = new HashMap<>(); + for ( BuiltinConstraint constraint : values() ) { + if ( constraint.constraintDependencies.isEmpty() ) { + CONSTRAINT_MAPPING.put( constraint.annotationClassName, Collections.singleton( constraint ) ); + } + else { + Set constraints = new HashSet<>(); + constraints.add( constraint ); + constraints.addAll( constraint.constraintDependencies ); + CONSTRAINT_MAPPING.put( constraint.annotationClassName, constraints ); + } + } + } + + private String annotationClassName; + private List constraintDependencies; + + BuiltinConstraint(String constraint) { + this( constraint, Collections.emptyList() ); + } + + BuiltinConstraint(String constraint, List composingConstraints) { + this.annotationClassName = constraint; + this.constraintDependencies = composingConstraints; + } + + static Set resolve(Set constraints) { + Set resolvedConstraints = new HashSet<>(); + for ( String constraint : constraints ) { + Set builtinConstraints = CONSTRAINT_MAPPING.get( constraint ); + if ( builtinConstraints != null ) { + resolvedConstraints.addAll( builtinConstraints ); + } + } + return resolvedConstraints; + } + + static boolean isBuiltin(String constraint) { + return CONSTRAINT_MAPPING.containsKey( constraint ); + } + + static Set set() { + return CONSTRAINT_MAPPING.keySet(); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java index b38a5543b3..d912d9481f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java @@ -6,6 +6,55 @@ */ package org.hibernate.validator.internal.metadata.core; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_ASSERT_FALSE; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_ASSERT_TRUE; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_DECIMAL_MAX; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_DECIMAL_MIN; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_DIGITS; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_EMAIL; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_FUTURE; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_FUTURE_OR_PRESENT; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_MAX; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_MIN; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_NEGATIVE; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_NEGATIVE_OR_ZERO; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_NOT_BLANK; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_NOT_EMPTY; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_NOT_NULL; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_NULL; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_PAST; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_PAST_OR_PRESENT; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_PATTERN; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_POSITIVE; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_POSITIVE_OR_ZERO; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.JAVAX_VALIDATION_CONSTRAINTS_SIZE; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_CNPJ; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_CPF; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_TITULO_ELEITORAL; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CODE_POINT_LENGTH; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CREDIT_CARD_NUMBER; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CURRENCY; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_EAN; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_EMAIL; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_ISBN; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_LENGTH; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_LUHN_CHECK; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD10_CHECK; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD11_CHECK; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD_CHECK; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NOT_BLANK; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NOT_EMPTY; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PARAMETER_SCRIPT_ASSERT; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_NIP; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_PESEL; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_REGON; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_RANGE; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_SAFE_HTML; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_SCRIPT_ASSERT; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_TIME_DURATION_MAX; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_TIME_DURATION_MIN; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_UNIQUE_ELEMENTS; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_URL; import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES; import java.lang.annotation.Annotation; @@ -17,6 +66,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -310,6 +360,7 @@ * @author Guillaume Smet */ public class ConstraintHelper { + public static final String GROUPS = "groups"; public static final String PAYLOAD = "payload"; public static final String MESSAGE = "message"; @@ -323,7 +374,7 @@ public class ConstraintHelper { private static final String JSOUP_CLASS_NAME = "org.jsoup.Jsoup"; @Immutable - private final Map, List>> builtinConstraints; + private final Map, List>> enabledBuiltinConstraints; private final ConcurrentMap, Boolean> externalConstraints = new ConcurrentHashMap<>(); @@ -331,405 +382,425 @@ public class ConstraintHelper { private final ValidatorDescriptorMap validatorDescriptors = new ValidatorDescriptorMap(); + public static ConstraintHelper forAllBuiltinConstraints() { + return new ConstraintHelper( new HashSet<>( Arrays.asList( BuiltinConstraint.values() ) ) ); + } + + public static ConstraintHelper forBuiltinConstraints(Set enabledConstraints) { + return new ConstraintHelper( BuiltinConstraint.resolve( enabledConstraints ) ); + } + @SuppressWarnings("deprecation") - public ConstraintHelper() { + private ConstraintHelper(Set enabledBuiltinConstraints) { + if ( enabledBuiltinConstraints.isEmpty() ) { + this.enabledBuiltinConstraints = Collections.emptyMap(); + return; + } + Map, List>> tmpConstraints = new HashMap<>(); // Bean Validation constraints - putConstraint( tmpConstraints, AssertFalse.class, AssertFalseValidator.class ); - putConstraint( tmpConstraints, AssertTrue.class, AssertTrueValidator.class ); - - if ( isJavaMoneyInClasspath() ) { - putConstraints( tmpConstraints, DecimalMax.class, Arrays.asList( - DecimalMaxValidatorForBigDecimal.class, - DecimalMaxValidatorForBigInteger.class, - DecimalMaxValidatorForByte.class, - DecimalMaxValidatorForDouble.class, - DecimalMaxValidatorForFloat.class, - DecimalMaxValidatorForLong.class, - DecimalMaxValidatorForInteger.class, - DecimalMaxValidatorForNumber.class, - DecimalMaxValidatorForShort.class, - DecimalMaxValidatorForCharSequence.class, - DecimalMaxValidatorForMonetaryAmount.class - ) ); - putConstraints( tmpConstraints, DecimalMin.class, Arrays.asList( - DecimalMinValidatorForBigDecimal.class, - DecimalMinValidatorForBigInteger.class, - DecimalMinValidatorForByte.class, - DecimalMinValidatorForDouble.class, - DecimalMinValidatorForFloat.class, - DecimalMinValidatorForLong.class, - DecimalMinValidatorForInteger.class, - DecimalMinValidatorForNumber.class, - DecimalMinValidatorForShort.class, - DecimalMinValidatorForCharSequence.class, - DecimalMinValidatorForMonetaryAmount.class - ) ); - putConstraints( tmpConstraints, Digits.class, Arrays.asList( - DigitsValidatorForCharSequence.class, - DigitsValidatorForNumber.class, - DigitsValidatorForMonetaryAmount.class - ) ); - } - else { - putConstraints( tmpConstraints, DecimalMax.class, Arrays.asList( - DecimalMaxValidatorForBigDecimal.class, - DecimalMaxValidatorForBigInteger.class, - DecimalMaxValidatorForByte.class, - DecimalMaxValidatorForDouble.class, - DecimalMaxValidatorForFloat.class, - DecimalMaxValidatorForLong.class, - DecimalMaxValidatorForInteger.class, - DecimalMaxValidatorForNumber.class, - DecimalMaxValidatorForShort.class, - DecimalMaxValidatorForCharSequence.class - ) ); - putConstraints( tmpConstraints, DecimalMin.class, Arrays.asList( - DecimalMinValidatorForBigDecimal.class, - DecimalMinValidatorForBigInteger.class, - DecimalMinValidatorForByte.class, - DecimalMinValidatorForDouble.class, - DecimalMinValidatorForFloat.class, - DecimalMinValidatorForLong.class, - DecimalMinValidatorForInteger.class, - DecimalMinValidatorForNumber.class, - DecimalMinValidatorForShort.class, - DecimalMinValidatorForCharSequence.class - ) ); - putConstraints( tmpConstraints, Digits.class, Arrays.asList( - DigitsValidatorForCharSequence.class, - DigitsValidatorForNumber.class - ) ); - } - - putConstraint( tmpConstraints, Email.class, EmailValidator.class ); - - List>> futureValidators = new ArrayList<>( 18 ); - futureValidators.add( FutureValidatorForCalendar.class ); - futureValidators.add( FutureValidatorForDate.class ); - if ( isJodaTimeInClasspath() ) { - futureValidators.add( FutureValidatorForReadableInstant.class ); - futureValidators.add( FutureValidatorForReadablePartial.class ); - } - // Java 8 date/time API validators - futureValidators.add( FutureValidatorForHijrahDate.class ); - futureValidators.add( FutureValidatorForInstant.class ); - futureValidators.add( FutureValidatorForJapaneseDate.class ); - futureValidators.add( FutureValidatorForLocalDate.class ); - futureValidators.add( FutureValidatorForLocalDateTime.class ); - futureValidators.add( FutureValidatorForLocalTime.class ); - futureValidators.add( FutureValidatorForMinguoDate.class ); - futureValidators.add( FutureValidatorForMonthDay.class ); - futureValidators.add( FutureValidatorForOffsetDateTime.class ); - futureValidators.add( FutureValidatorForOffsetTime.class ); - futureValidators.add( FutureValidatorForThaiBuddhistDate.class ); - futureValidators.add( FutureValidatorForYear.class ); - futureValidators.add( FutureValidatorForYearMonth.class ); - futureValidators.add( FutureValidatorForZonedDateTime.class ); - - putConstraints( tmpConstraints, Future.class, futureValidators ); - - List>> futureOrPresentValidators = new ArrayList<>( 18 ); - futureOrPresentValidators.add( FutureOrPresentValidatorForCalendar.class ); - futureOrPresentValidators.add( FutureOrPresentValidatorForDate.class ); - if ( isJodaTimeInClasspath() ) { - futureOrPresentValidators.add( FutureOrPresentValidatorForReadableInstant.class ); - futureOrPresentValidators.add( FutureOrPresentValidatorForReadablePartial.class ); - } - // Java 8 date/time API validators - futureOrPresentValidators.add( FutureOrPresentValidatorForHijrahDate.class ); - futureOrPresentValidators.add( FutureOrPresentValidatorForInstant.class ); - futureOrPresentValidators.add( FutureOrPresentValidatorForJapaneseDate.class ); - futureOrPresentValidators.add( FutureOrPresentValidatorForLocalDate.class ); - futureOrPresentValidators.add( FutureOrPresentValidatorForLocalDateTime.class ); - futureOrPresentValidators.add( FutureOrPresentValidatorForLocalTime.class ); - futureOrPresentValidators.add( FutureOrPresentValidatorForMinguoDate.class ); - futureOrPresentValidators.add( FutureOrPresentValidatorForMonthDay.class ); - futureOrPresentValidators.add( FutureOrPresentValidatorForOffsetDateTime.class ); - futureOrPresentValidators.add( FutureOrPresentValidatorForOffsetTime.class ); - futureOrPresentValidators.add( FutureOrPresentValidatorForThaiBuddhistDate.class ); - futureOrPresentValidators.add( FutureOrPresentValidatorForYear.class ); - futureOrPresentValidators.add( FutureOrPresentValidatorForYearMonth.class ); - futureOrPresentValidators.add( FutureOrPresentValidatorForZonedDateTime.class ); - - putConstraints( tmpConstraints, FutureOrPresent.class, futureOrPresentValidators ); - - if ( isJavaMoneyInClasspath() ) { - putConstraints( tmpConstraints, Max.class, Arrays.asList( - MaxValidatorForBigDecimal.class, - MaxValidatorForBigInteger.class, - MaxValidatorForByte.class, - MaxValidatorForDouble.class, - MaxValidatorForFloat.class, - MaxValidatorForInteger.class, - MaxValidatorForLong.class, - MaxValidatorForNumber.class, - MaxValidatorForShort.class, - MaxValidatorForCharSequence.class, - MaxValidatorForMonetaryAmount.class - ) ); - putConstraints( tmpConstraints, Min.class, Arrays.asList( - MinValidatorForBigDecimal.class, - MinValidatorForBigInteger.class, - MinValidatorForByte.class, - MinValidatorForDouble.class, - MinValidatorForFloat.class, - MinValidatorForInteger.class, - MinValidatorForLong.class, - MinValidatorForNumber.class, - MinValidatorForShort.class, - MinValidatorForCharSequence.class, - MinValidatorForMonetaryAmount.class - ) ); - } - else { - putConstraints( tmpConstraints, Max.class, Arrays.asList( - MaxValidatorForBigDecimal.class, - MaxValidatorForBigInteger.class, - MaxValidatorForDouble.class, - MaxValidatorForFloat.class, - MaxValidatorForLong.class, - MaxValidatorForNumber.class, - MaxValidatorForCharSequence.class - ) ); - putConstraints( tmpConstraints, Min.class, Arrays.asList( - MinValidatorForBigDecimal.class, - MinValidatorForBigInteger.class, - MinValidatorForByte.class, - MinValidatorForDouble.class, - MinValidatorForFloat.class, - MinValidatorForInteger.class, - MinValidatorForLong.class, - MinValidatorForNumber.class, - MinValidatorForShort.class, - MinValidatorForCharSequence.class - ) ); - } - - if ( isJavaMoneyInClasspath() ) { - putConstraints( tmpConstraints, Negative.class, Arrays.asList( - NegativeValidatorForBigDecimal.class, - NegativeValidatorForBigInteger.class, - NegativeValidatorForDouble.class, - NegativeValidatorForFloat.class, - NegativeValidatorForLong.class, - NegativeValidatorForInteger.class, - NegativeValidatorForShort.class, - NegativeValidatorForByte.class, - NegativeValidatorForNumber.class, - NegativeValidatorForMonetaryAmount.class ) ); - - putConstraints( tmpConstraints, NegativeOrZero.class, Arrays.asList( - NegativeOrZeroValidatorForBigDecimal.class, - NegativeOrZeroValidatorForBigInteger.class, - NegativeOrZeroValidatorForDouble.class, - NegativeOrZeroValidatorForFloat.class, - NegativeOrZeroValidatorForLong.class, - NegativeOrZeroValidatorForInteger.class, - NegativeOrZeroValidatorForShort.class, - NegativeOrZeroValidatorForByte.class, - NegativeOrZeroValidatorForNumber.class, - NegativeOrZeroValidatorForMonetaryAmount.class ) ); - } - else { - putConstraints( tmpConstraints, Negative.class, Arrays.asList( - NegativeValidatorForBigDecimal.class, - NegativeValidatorForBigInteger.class, - NegativeValidatorForDouble.class, - NegativeValidatorForFloat.class, - NegativeValidatorForLong.class, - NegativeValidatorForInteger.class, - NegativeValidatorForShort.class, - NegativeValidatorForByte.class, - NegativeValidatorForNumber.class - ) ); - - putConstraints( tmpConstraints, NegativeOrZero.class, Arrays.asList( - NegativeOrZeroValidatorForBigDecimal.class, - NegativeOrZeroValidatorForBigInteger.class, - NegativeOrZeroValidatorForDouble.class, - NegativeOrZeroValidatorForFloat.class, - NegativeOrZeroValidatorForLong.class, - NegativeOrZeroValidatorForInteger.class, - NegativeOrZeroValidatorForShort.class, - NegativeOrZeroValidatorForByte.class, - NegativeOrZeroValidatorForNumber.class - ) ); - } - putConstraint( tmpConstraints, NotBlank.class, NotBlankValidator.class ); - - List>> notEmptyValidators = new ArrayList<>( 11 ); - notEmptyValidators.add( NotEmptyValidatorForCharSequence.class ); - notEmptyValidators.add( NotEmptyValidatorForCollection.class ); - notEmptyValidators.add( NotEmptyValidatorForArray.class ); - notEmptyValidators.add( NotEmptyValidatorForMap.class ); - notEmptyValidators.add( NotEmptyValidatorForArraysOfBoolean.class ); - notEmptyValidators.add( NotEmptyValidatorForArraysOfByte.class ); - notEmptyValidators.add( NotEmptyValidatorForArraysOfChar.class ); - notEmptyValidators.add( NotEmptyValidatorForArraysOfDouble.class ); - notEmptyValidators.add( NotEmptyValidatorForArraysOfFloat.class ); - notEmptyValidators.add( NotEmptyValidatorForArraysOfInt.class ); - notEmptyValidators.add( NotEmptyValidatorForArraysOfLong.class ); - notEmptyValidators.add( NotEmptyValidatorForArraysOfShort.class ); - putConstraints( tmpConstraints, NotEmpty.class, notEmptyValidators ); - - putConstraint( tmpConstraints, NotNull.class, NotNullValidator.class ); - putConstraint( tmpConstraints, Null.class, NullValidator.class ); - - List>> pastValidators = new ArrayList<>( 18 ); - pastValidators.add( PastValidatorForCalendar.class ); - pastValidators.add( PastValidatorForDate.class ); - if ( isJodaTimeInClasspath() ) { - pastValidators.add( PastValidatorForReadableInstant.class ); - pastValidators.add( PastValidatorForReadablePartial.class ); - } - // Java 8 date/time API validators - pastValidators.add( PastValidatorForHijrahDate.class ); - pastValidators.add( PastValidatorForInstant.class ); - pastValidators.add( PastValidatorForJapaneseDate.class ); - pastValidators.add( PastValidatorForLocalDate.class ); - pastValidators.add( PastValidatorForLocalDateTime.class ); - pastValidators.add( PastValidatorForLocalTime.class ); - pastValidators.add( PastValidatorForMinguoDate.class ); - pastValidators.add( PastValidatorForMonthDay.class ); - pastValidators.add( PastValidatorForOffsetDateTime.class ); - pastValidators.add( PastValidatorForOffsetTime.class ); - pastValidators.add( PastValidatorForThaiBuddhistDate.class ); - pastValidators.add( PastValidatorForYear.class ); - pastValidators.add( PastValidatorForYearMonth.class ); - pastValidators.add( PastValidatorForZonedDateTime.class ); - - putConstraints( tmpConstraints, Past.class, pastValidators ); - - List>> pastOrPresentValidators = new ArrayList<>( 18 ); - pastOrPresentValidators.add( PastOrPresentValidatorForCalendar.class ); - pastOrPresentValidators.add( PastOrPresentValidatorForDate.class ); - if ( isJodaTimeInClasspath() ) { - pastOrPresentValidators.add( PastOrPresentValidatorForReadableInstant.class ); - pastOrPresentValidators.add( PastOrPresentValidatorForReadablePartial.class ); - } - // Java 8 date/time API validators - pastOrPresentValidators.add( PastOrPresentValidatorForHijrahDate.class ); - pastOrPresentValidators.add( PastOrPresentValidatorForInstant.class ); - pastOrPresentValidators.add( PastOrPresentValidatorForJapaneseDate.class ); - pastOrPresentValidators.add( PastOrPresentValidatorForLocalDate.class ); - pastOrPresentValidators.add( PastOrPresentValidatorForLocalDateTime.class ); - pastOrPresentValidators.add( PastOrPresentValidatorForLocalTime.class ); - pastOrPresentValidators.add( PastOrPresentValidatorForMinguoDate.class ); - pastOrPresentValidators.add( PastOrPresentValidatorForMonthDay.class ); - pastOrPresentValidators.add( PastOrPresentValidatorForOffsetDateTime.class ); - pastOrPresentValidators.add( PastOrPresentValidatorForOffsetTime.class ); - pastOrPresentValidators.add( PastOrPresentValidatorForThaiBuddhistDate.class ); - pastOrPresentValidators.add( PastOrPresentValidatorForYear.class ); - pastOrPresentValidators.add( PastOrPresentValidatorForYearMonth.class ); - pastOrPresentValidators.add( PastOrPresentValidatorForZonedDateTime.class ); - - putConstraints( tmpConstraints, PastOrPresent.class, pastOrPresentValidators ); - - putConstraint( tmpConstraints, Pattern.class, PatternValidator.class ); - if ( isJavaMoneyInClasspath() ) { - putConstraints( tmpConstraints, Positive.class, Arrays.asList( - PositiveValidatorForBigDecimal.class, - PositiveValidatorForBigInteger.class, - PositiveValidatorForDouble.class, - PositiveValidatorForFloat.class, - PositiveValidatorForLong.class, - PositiveValidatorForInteger.class, - PositiveValidatorForShort.class, - PositiveValidatorForByte.class, - PositiveValidatorForNumber.class, - PositiveValidatorForMonetaryAmount.class ) ); - - putConstraints( tmpConstraints, PositiveOrZero.class, Arrays.asList( - PositiveOrZeroValidatorForBigDecimal.class, - PositiveOrZeroValidatorForBigInteger.class, - PositiveOrZeroValidatorForDouble.class, - PositiveOrZeroValidatorForFloat.class, - PositiveOrZeroValidatorForLong.class, - PositiveOrZeroValidatorForInteger.class, - PositiveOrZeroValidatorForShort.class, - PositiveOrZeroValidatorForByte.class, - PositiveOrZeroValidatorForNumber.class, - PositiveOrZeroValidatorForMonetaryAmount.class ) ); - } - else { - putConstraints( tmpConstraints, Positive.class, Arrays.asList( - PositiveValidatorForBigDecimal.class, - PositiveValidatorForBigInteger.class, - PositiveValidatorForDouble.class, - PositiveValidatorForFloat.class, - PositiveValidatorForLong.class, - PositiveValidatorForInteger.class, - PositiveValidatorForShort.class, - PositiveValidatorForByte.class, - PositiveValidatorForNumber.class - ) ); - - putConstraints( tmpConstraints, PositiveOrZero.class, Arrays.asList( - PositiveOrZeroValidatorForBigDecimal.class, - PositiveOrZeroValidatorForBigInteger.class, - PositiveOrZeroValidatorForDouble.class, - PositiveOrZeroValidatorForFloat.class, - PositiveOrZeroValidatorForLong.class, - PositiveOrZeroValidatorForInteger.class, - PositiveOrZeroValidatorForShort.class, - PositiveOrZeroValidatorForByte.class, - PositiveOrZeroValidatorForNumber.class - ) ); - } - - List>> sizeValidators = new ArrayList<>( 11 ); - sizeValidators.add( SizeValidatorForCharSequence.class ); - sizeValidators.add( SizeValidatorForCollection.class ); - sizeValidators.add( SizeValidatorForArray.class ); - sizeValidators.add( SizeValidatorForMap.class ); - sizeValidators.add( SizeValidatorForArraysOfBoolean.class ); - sizeValidators.add( SizeValidatorForArraysOfByte.class ); - sizeValidators.add( SizeValidatorForArraysOfChar.class ); - sizeValidators.add( SizeValidatorForArraysOfDouble.class ); - sizeValidators.add( SizeValidatorForArraysOfFloat.class ); - sizeValidators.add( SizeValidatorForArraysOfInt.class ); - sizeValidators.add( SizeValidatorForArraysOfLong.class ); - sizeValidators.add( SizeValidatorForArraysOfShort.class ); - putConstraints( tmpConstraints, Size.class, sizeValidators ); + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_ASSERT_FALSE ) ) { + putConstraint( tmpConstraints, AssertFalse.class, AssertFalseValidator.class ); + } + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_ASSERT_TRUE ) ) { + putConstraint( tmpConstraints, AssertTrue.class, AssertTrueValidator.class ); + } + + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_DECIMAL_MAX ) ) { + List>> decimalMaxValidators = new ArrayList<>(); + decimalMaxValidators.add( DecimalMaxValidatorForBigDecimal.class ); + decimalMaxValidators.add( DecimalMaxValidatorForBigInteger.class ); + decimalMaxValidators.add( DecimalMaxValidatorForByte.class ); + decimalMaxValidators.add( DecimalMaxValidatorForDouble.class ); + decimalMaxValidators.add( DecimalMaxValidatorForFloat.class ); + decimalMaxValidators.add( DecimalMaxValidatorForLong.class ); + decimalMaxValidators.add( DecimalMaxValidatorForInteger.class ); + decimalMaxValidators.add( DecimalMaxValidatorForNumber.class ); + decimalMaxValidators.add( DecimalMaxValidatorForShort.class ); + decimalMaxValidators.add( DecimalMaxValidatorForCharSequence.class ); + if ( isJavaMoneyInClasspath() ) { + decimalMaxValidators.add( DecimalMaxValidatorForMonetaryAmount.class ); + } + putConstraints( tmpConstraints, DecimalMax.class, decimalMaxValidators ); + } + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_DECIMAL_MIN ) ) { + List>> decimalMinValidators = new ArrayList<>(); + decimalMinValidators.add( DecimalMinValidatorForBigDecimal.class ); + decimalMinValidators.add( DecimalMinValidatorForBigInteger.class ); + decimalMinValidators.add( DecimalMinValidatorForByte.class ); + decimalMinValidators.add( DecimalMinValidatorForDouble.class ); + decimalMinValidators.add( DecimalMinValidatorForFloat.class ); + decimalMinValidators.add( DecimalMinValidatorForLong.class ); + decimalMinValidators.add( DecimalMinValidatorForInteger.class ); + decimalMinValidators.add( DecimalMinValidatorForNumber.class ); + decimalMinValidators.add( DecimalMinValidatorForShort.class ); + decimalMinValidators.add( DecimalMinValidatorForCharSequence.class ); + if ( isJavaMoneyInClasspath() ) { + decimalMinValidators.add( DecimalMinValidatorForMonetaryAmount.class ); + } + putConstraints( tmpConstraints, DecimalMin.class, decimalMinValidators ); + } + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_DIGITS ) ) { + List>> digitsValidators = new ArrayList<>(); + digitsValidators.add( DigitsValidatorForCharSequence.class ); + digitsValidators.add( DigitsValidatorForNumber.class ); + if ( isJavaMoneyInClasspath() ) { + digitsValidators.add( DigitsValidatorForMonetaryAmount.class ); + } + putConstraints( tmpConstraints, Digits.class, digitsValidators ); + } + + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_EMAIL ) ) { + putConstraint( tmpConstraints, Email.class, EmailValidator.class ); + } + + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_FUTURE ) ) { + List>> futureValidators = new ArrayList<>( 18 ); + futureValidators.add( FutureValidatorForCalendar.class ); + futureValidators.add( FutureValidatorForDate.class ); + if ( isJodaTimeInClasspath() ) { + futureValidators.add( FutureValidatorForReadableInstant.class ); + futureValidators.add( FutureValidatorForReadablePartial.class ); + } + // Java 8 date/time API validators + futureValidators.add( FutureValidatorForHijrahDate.class ); + futureValidators.add( FutureValidatorForInstant.class ); + futureValidators.add( FutureValidatorForJapaneseDate.class ); + futureValidators.add( FutureValidatorForLocalDate.class ); + futureValidators.add( FutureValidatorForLocalDateTime.class ); + futureValidators.add( FutureValidatorForLocalTime.class ); + futureValidators.add( FutureValidatorForMinguoDate.class ); + futureValidators.add( FutureValidatorForMonthDay.class ); + futureValidators.add( FutureValidatorForOffsetDateTime.class ); + futureValidators.add( FutureValidatorForOffsetTime.class ); + futureValidators.add( FutureValidatorForThaiBuddhistDate.class ); + futureValidators.add( FutureValidatorForYear.class ); + futureValidators.add( FutureValidatorForYearMonth.class ); + futureValidators.add( FutureValidatorForZonedDateTime.class ); + + putConstraints( tmpConstraints, Future.class, futureValidators ); + } + + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_FUTURE_OR_PRESENT ) ) { + List>> futureOrPresentValidators = new ArrayList<>( 18 ); + futureOrPresentValidators.add( FutureOrPresentValidatorForCalendar.class ); + futureOrPresentValidators.add( FutureOrPresentValidatorForDate.class ); + if ( isJodaTimeInClasspath() ) { + futureOrPresentValidators.add( FutureOrPresentValidatorForReadableInstant.class ); + futureOrPresentValidators.add( FutureOrPresentValidatorForReadablePartial.class ); + } + // Java 8 date/time API validators + futureOrPresentValidators.add( FutureOrPresentValidatorForHijrahDate.class ); + futureOrPresentValidators.add( FutureOrPresentValidatorForInstant.class ); + futureOrPresentValidators.add( FutureOrPresentValidatorForJapaneseDate.class ); + futureOrPresentValidators.add( FutureOrPresentValidatorForLocalDate.class ); + futureOrPresentValidators.add( FutureOrPresentValidatorForLocalDateTime.class ); + futureOrPresentValidators.add( FutureOrPresentValidatorForLocalTime.class ); + futureOrPresentValidators.add( FutureOrPresentValidatorForMinguoDate.class ); + futureOrPresentValidators.add( FutureOrPresentValidatorForMonthDay.class ); + futureOrPresentValidators.add( FutureOrPresentValidatorForOffsetDateTime.class ); + futureOrPresentValidators.add( FutureOrPresentValidatorForOffsetTime.class ); + futureOrPresentValidators.add( FutureOrPresentValidatorForThaiBuddhistDate.class ); + futureOrPresentValidators.add( FutureOrPresentValidatorForYear.class ); + futureOrPresentValidators.add( FutureOrPresentValidatorForYearMonth.class ); + futureOrPresentValidators.add( FutureOrPresentValidatorForZonedDateTime.class ); + + putConstraints( tmpConstraints, FutureOrPresent.class, futureOrPresentValidators ); + } + + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_MAX ) ) { + List>> maxValidators = new ArrayList<>(); + maxValidators.add( MaxValidatorForBigDecimal.class ); + maxValidators.add( MaxValidatorForBigInteger.class ); + maxValidators.add( MaxValidatorForByte.class ); + maxValidators.add( MaxValidatorForDouble.class ); + maxValidators.add( MaxValidatorForFloat.class ); + maxValidators.add( MaxValidatorForInteger.class ); + maxValidators.add( MaxValidatorForLong.class ); + maxValidators.add( MaxValidatorForNumber.class ); + maxValidators.add( MaxValidatorForShort.class ); + maxValidators.add( MaxValidatorForCharSequence.class ); + if ( isJavaMoneyInClasspath() ) { + maxValidators.add( MaxValidatorForMonetaryAmount.class ); + } + putConstraints( tmpConstraints, Max.class, maxValidators ); + } + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_MIN ) ) { + List>> minValidators = new ArrayList<>(); + minValidators.add( MinValidatorForBigDecimal.class ); + minValidators.add( MinValidatorForBigInteger.class ); + minValidators.add( MinValidatorForByte.class ); + minValidators.add( MinValidatorForDouble.class ); + minValidators.add( MinValidatorForFloat.class ); + minValidators.add( MinValidatorForInteger.class ); + minValidators.add( MinValidatorForLong.class ); + minValidators.add( MinValidatorForNumber.class ); + minValidators.add( MinValidatorForShort.class ); + minValidators.add( MinValidatorForCharSequence.class ); + if ( isJavaMoneyInClasspath() ) { + minValidators.add( MinValidatorForMonetaryAmount.class ); + } + putConstraints( tmpConstraints, Min.class, minValidators ); + } + + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NEGATIVE ) ) { + List>> negativeValidators = new ArrayList<>(); + negativeValidators.add( NegativeValidatorForBigDecimal.class ); + negativeValidators.add( NegativeValidatorForBigInteger.class ); + negativeValidators.add( NegativeValidatorForDouble.class ); + negativeValidators.add( NegativeValidatorForFloat.class ); + negativeValidators.add( NegativeValidatorForLong.class ); + negativeValidators.add( NegativeValidatorForInteger.class ); + negativeValidators.add( NegativeValidatorForShort.class ); + negativeValidators.add( NegativeValidatorForByte.class ); + negativeValidators.add( NegativeValidatorForNumber.class ); + if ( isJavaMoneyInClasspath() ) { + negativeValidators.add( NegativeValidatorForMonetaryAmount.class ); + } + putConstraints( tmpConstraints, Negative.class, negativeValidators ); + } + + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NEGATIVE_OR_ZERO ) ) { + List>> negativeOrZeroValidators = new ArrayList<>(); + negativeOrZeroValidators.add( NegativeOrZeroValidatorForBigDecimal.class ); + negativeOrZeroValidators.add( NegativeOrZeroValidatorForBigInteger.class ); + negativeOrZeroValidators.add( NegativeOrZeroValidatorForDouble.class ); + negativeOrZeroValidators.add( NegativeOrZeroValidatorForFloat.class ); + negativeOrZeroValidators.add( NegativeOrZeroValidatorForLong.class ); + negativeOrZeroValidators.add( NegativeOrZeroValidatorForInteger.class ); + negativeOrZeroValidators.add( NegativeOrZeroValidatorForShort.class ); + negativeOrZeroValidators.add( NegativeOrZeroValidatorForByte.class ); + negativeOrZeroValidators.add( NegativeOrZeroValidatorForNumber.class ); + if ( isJavaMoneyInClasspath() ) { + negativeOrZeroValidators.add( NegativeOrZeroValidatorForMonetaryAmount.class ); + } + putConstraints( tmpConstraints, NegativeOrZero.class, negativeOrZeroValidators ); + } + + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NOT_BLANK ) ) { + putConstraint( tmpConstraints, NotBlank.class, NotBlankValidator.class ); + } + + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NOT_EMPTY ) ) { + List>> notEmptyValidators = new ArrayList<>( 11 ); + notEmptyValidators.add( NotEmptyValidatorForCharSequence.class ); + notEmptyValidators.add( NotEmptyValidatorForCollection.class ); + notEmptyValidators.add( NotEmptyValidatorForArray.class ); + notEmptyValidators.add( NotEmptyValidatorForMap.class ); + notEmptyValidators.add( NotEmptyValidatorForArraysOfBoolean.class ); + notEmptyValidators.add( NotEmptyValidatorForArraysOfByte.class ); + notEmptyValidators.add( NotEmptyValidatorForArraysOfChar.class ); + notEmptyValidators.add( NotEmptyValidatorForArraysOfDouble.class ); + notEmptyValidators.add( NotEmptyValidatorForArraysOfFloat.class ); + notEmptyValidators.add( NotEmptyValidatorForArraysOfInt.class ); + notEmptyValidators.add( NotEmptyValidatorForArraysOfLong.class ); + notEmptyValidators.add( NotEmptyValidatorForArraysOfShort.class ); + putConstraints( tmpConstraints, NotEmpty.class, notEmptyValidators ); + } + + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NOT_NULL ) ) { + putConstraint( tmpConstraints, NotNull.class, NotNullValidator.class ); + } + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NULL ) ) { + putConstraint( tmpConstraints, Null.class, NullValidator.class ); + } + + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_PAST ) ) { + List>> pastValidators = new ArrayList<>( 18 ); + pastValidators.add( PastValidatorForCalendar.class ); + pastValidators.add( PastValidatorForDate.class ); + if ( isJodaTimeInClasspath() ) { + pastValidators.add( PastValidatorForReadableInstant.class ); + pastValidators.add( PastValidatorForReadablePartial.class ); + } + // Java 8 date/time API validators + pastValidators.add( PastValidatorForHijrahDate.class ); + pastValidators.add( PastValidatorForInstant.class ); + pastValidators.add( PastValidatorForJapaneseDate.class ); + pastValidators.add( PastValidatorForLocalDate.class ); + pastValidators.add( PastValidatorForLocalDateTime.class ); + pastValidators.add( PastValidatorForLocalTime.class ); + pastValidators.add( PastValidatorForMinguoDate.class ); + pastValidators.add( PastValidatorForMonthDay.class ); + pastValidators.add( PastValidatorForOffsetDateTime.class ); + pastValidators.add( PastValidatorForOffsetTime.class ); + pastValidators.add( PastValidatorForThaiBuddhistDate.class ); + pastValidators.add( PastValidatorForYear.class ); + pastValidators.add( PastValidatorForYearMonth.class ); + pastValidators.add( PastValidatorForZonedDateTime.class ); + + putConstraints( tmpConstraints, Past.class, pastValidators ); + } + + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_PAST_OR_PRESENT ) ) { + List>> pastOrPresentValidators = new ArrayList<>( 18 ); + pastOrPresentValidators.add( PastOrPresentValidatorForCalendar.class ); + pastOrPresentValidators.add( PastOrPresentValidatorForDate.class ); + if ( isJodaTimeInClasspath() ) { + pastOrPresentValidators.add( PastOrPresentValidatorForReadableInstant.class ); + pastOrPresentValidators.add( PastOrPresentValidatorForReadablePartial.class ); + } + // Java 8 date/time API validators + pastOrPresentValidators.add( PastOrPresentValidatorForHijrahDate.class ); + pastOrPresentValidators.add( PastOrPresentValidatorForInstant.class ); + pastOrPresentValidators.add( PastOrPresentValidatorForJapaneseDate.class ); + pastOrPresentValidators.add( PastOrPresentValidatorForLocalDate.class ); + pastOrPresentValidators.add( PastOrPresentValidatorForLocalDateTime.class ); + pastOrPresentValidators.add( PastOrPresentValidatorForLocalTime.class ); + pastOrPresentValidators.add( PastOrPresentValidatorForMinguoDate.class ); + pastOrPresentValidators.add( PastOrPresentValidatorForMonthDay.class ); + pastOrPresentValidators.add( PastOrPresentValidatorForOffsetDateTime.class ); + pastOrPresentValidators.add( PastOrPresentValidatorForOffsetTime.class ); + pastOrPresentValidators.add( PastOrPresentValidatorForThaiBuddhistDate.class ); + pastOrPresentValidators.add( PastOrPresentValidatorForYear.class ); + pastOrPresentValidators.add( PastOrPresentValidatorForYearMonth.class ); + pastOrPresentValidators.add( PastOrPresentValidatorForZonedDateTime.class ); + + putConstraints( tmpConstraints, PastOrPresent.class, pastOrPresentValidators ); + } + + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_PATTERN ) ) { + putConstraint( tmpConstraints, Pattern.class, PatternValidator.class ); + } + + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_POSITIVE ) ) { + List>> positiveValidators = new ArrayList<>(); + positiveValidators.add( PositiveValidatorForBigDecimal.class ); + positiveValidators.add( PositiveValidatorForBigInteger.class ); + positiveValidators.add( PositiveValidatorForDouble.class ); + positiveValidators.add( PositiveValidatorForFloat.class ); + positiveValidators.add( PositiveValidatorForLong.class ); + positiveValidators.add( PositiveValidatorForInteger.class ); + positiveValidators.add( PositiveValidatorForShort.class ); + positiveValidators.add( PositiveValidatorForByte.class ); + positiveValidators.add( PositiveValidatorForNumber.class ); + if ( isJavaMoneyInClasspath() ) { + positiveValidators.add( PositiveValidatorForMonetaryAmount.class ); + } + putConstraints( tmpConstraints, Positive.class, positiveValidators ); + } + + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_POSITIVE_OR_ZERO ) ) { + List>> positiveOrZeroValidators = new ArrayList<>(); + positiveOrZeroValidators.add( PositiveOrZeroValidatorForBigDecimal.class ); + positiveOrZeroValidators.add( PositiveOrZeroValidatorForBigInteger.class ); + positiveOrZeroValidators.add( PositiveOrZeroValidatorForDouble.class ); + positiveOrZeroValidators.add( PositiveOrZeroValidatorForFloat.class ); + positiveOrZeroValidators.add( PositiveOrZeroValidatorForLong.class ); + positiveOrZeroValidators.add( PositiveOrZeroValidatorForInteger.class ); + positiveOrZeroValidators.add( PositiveOrZeroValidatorForShort.class ); + positiveOrZeroValidators.add( PositiveOrZeroValidatorForByte.class ); + positiveOrZeroValidators.add( PositiveOrZeroValidatorForNumber.class ); + if ( isJavaMoneyInClasspath() ) { + positiveOrZeroValidators.add( PositiveOrZeroValidatorForMonetaryAmount.class ); + } + putConstraints( tmpConstraints, PositiveOrZero.class, positiveOrZeroValidators ); + } + + if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_SIZE ) ) { + List>> sizeValidators = new ArrayList<>( 11 ); + sizeValidators.add( SizeValidatorForCharSequence.class ); + sizeValidators.add( SizeValidatorForCollection.class ); + sizeValidators.add( SizeValidatorForArray.class ); + sizeValidators.add( SizeValidatorForMap.class ); + sizeValidators.add( SizeValidatorForArraysOfBoolean.class ); + sizeValidators.add( SizeValidatorForArraysOfByte.class ); + sizeValidators.add( SizeValidatorForArraysOfChar.class ); + sizeValidators.add( SizeValidatorForArraysOfDouble.class ); + sizeValidators.add( SizeValidatorForArraysOfFloat.class ); + sizeValidators.add( SizeValidatorForArraysOfInt.class ); + sizeValidators.add( SizeValidatorForArraysOfLong.class ); + sizeValidators.add( SizeValidatorForArraysOfShort.class ); + putConstraints( tmpConstraints, Size.class, sizeValidators ); + } // Hibernate Validator specific constraints - putConstraint( tmpConstraints, CNPJ.class, CNPJValidator.class ); - putConstraint( tmpConstraints, CPF.class, CPFValidator.class ); - if ( isJavaMoneyInClasspath() ) { + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_CNPJ ) ) { + putConstraint( tmpConstraints, CNPJ.class, CNPJValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_CPF ) ) { + putConstraint( tmpConstraints, CPF.class, CPFValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CURRENCY ) && isJavaMoneyInClasspath() ) { putConstraint( tmpConstraints, Currency.class, CurrencyValidatorForMonetaryAmount.class ); } - putConstraint( tmpConstraints, CreditCardNumber.class ); - putConstraint( tmpConstraints, DurationMax.class, DurationMaxValidator.class ); - putConstraint( tmpConstraints, DurationMin.class, DurationMinValidator.class ); - putConstraint( tmpConstraints, EAN.class, EANValidator.class ); - putConstraint( tmpConstraints, org.hibernate.validator.constraints.Email.class, org.hibernate.validator.internal.constraintvalidators.hv.EmailValidator.class ); - putConstraint( tmpConstraints, ISBN.class, ISBNValidator.class ); - putConstraint( tmpConstraints, Length.class, LengthValidator.class ); - putConstraint( tmpConstraints, CodePointLength.class, CodePointLengthValidator.class ); - putConstraint( tmpConstraints, LuhnCheck.class, LuhnCheckValidator.class ); - putConstraint( tmpConstraints, ModCheck.class, ModCheckValidator.class ); - putConstraint( tmpConstraints, Mod10Check.class, Mod10CheckValidator.class ); - putConstraint( tmpConstraints, Mod11Check.class, Mod11CheckValidator.class ); - putConstraint( tmpConstraints, NIP.class, NIPValidator.class ); - putConstraint( tmpConstraints, org.hibernate.validator.constraints.NotBlank.class, org.hibernate.validator.internal.constraintvalidators.hv.NotBlankValidator.class ); - putConstraint( tmpConstraints, org.hibernate.validator.constraints.NotEmpty.class ); - putConstraint( tmpConstraints, ParameterScriptAssert.class, ParameterScriptAssertValidator.class ); - putConstraint( tmpConstraints, PESEL.class, PESELValidator.class ); - putConstraint( tmpConstraints, Range.class ); - putConstraint( tmpConstraints, REGON.class, REGONValidator.class ); - if ( isJsoupInClasspath() ) { + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CREDIT_CARD_NUMBER ) ) { + putConstraint( tmpConstraints, CreditCardNumber.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_TIME_DURATION_MAX ) ) { + putConstraint( tmpConstraints, DurationMax.class, DurationMaxValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_TIME_DURATION_MIN ) ) { + putConstraint( tmpConstraints, DurationMin.class, DurationMinValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_EAN ) ) { + putConstraint( tmpConstraints, EAN.class, EANValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_EMAIL ) ) { + putConstraint( tmpConstraints, org.hibernate.validator.constraints.Email.class, org.hibernate.validator.internal.constraintvalidators.hv.EmailValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_ISBN ) ) { + putConstraint( tmpConstraints, ISBN.class, ISBNValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_LENGTH ) ) { + putConstraint( tmpConstraints, Length.class, LengthValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CODE_POINT_LENGTH ) ) { + putConstraint( tmpConstraints, CodePointLength.class, CodePointLengthValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_LUHN_CHECK ) ) { + putConstraint( tmpConstraints, LuhnCheck.class, LuhnCheckValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD_CHECK ) ) { + putConstraint( tmpConstraints, ModCheck.class, ModCheckValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD10_CHECK ) ) { + putConstraint( tmpConstraints, Mod10Check.class, Mod10CheckValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD11_CHECK ) ) { + putConstraint( tmpConstraints, Mod11Check.class, Mod11CheckValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_NIP ) ) { + putConstraint( tmpConstraints, NIP.class, NIPValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NOT_BLANK ) ) { + putConstraint( tmpConstraints, org.hibernate.validator.constraints.NotBlank.class, org.hibernate.validator.internal.constraintvalidators.hv.NotBlankValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NOT_EMPTY ) ) { + putConstraint( tmpConstraints, org.hibernate.validator.constraints.NotEmpty.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PARAMETER_SCRIPT_ASSERT ) ) { + putConstraint( tmpConstraints, ParameterScriptAssert.class, ParameterScriptAssertValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_PESEL ) ) { + putConstraint( tmpConstraints, PESEL.class, PESELValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_RANGE ) ) { + putConstraint( tmpConstraints, Range.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_REGON ) ) { + putConstraint( tmpConstraints, REGON.class, REGONValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_SAFE_HTML ) && isJsoupInClasspath() ) { putConstraint( tmpConstraints, SafeHtml.class, SafeHtmlValidator.class ); } - putConstraint( tmpConstraints, ScriptAssert.class, ScriptAssertValidator.class ); - putConstraint( tmpConstraints, TituloEleitoral.class ); - putConstraint( tmpConstraints, UniqueElements.class, UniqueElementsValidator.class ); - putConstraint( tmpConstraints, URL.class, URLValidator.class ); + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_SCRIPT_ASSERT ) ) { + putConstraint( tmpConstraints, ScriptAssert.class, ScriptAssertValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_TITULO_ELEITORAL ) ) { + putConstraint( tmpConstraints, TituloEleitoral.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_UNIQUE_ELEMENTS ) ) { + putConstraint( tmpConstraints, UniqueElements.class, UniqueElementsValidator.class ); + } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_URL ) ) { + putConstraint( tmpConstraints, URL.class, URLValidator.class ); + } - this.builtinConstraints = Collections.unmodifiableMap( tmpConstraints ); + this.enabledBuiltinConstraints = Collections.unmodifiableMap( tmpConstraints ); } private static void putConstraint(Map, List>> validators, @@ -764,11 +835,11 @@ private static void putConstraints(Map annotationType) { - return builtinConstraints.containsKey( annotationType ); + return BuiltinConstraint.isBuiltin( annotationType.getName() ); } - public Set> getBuiltinConstraints() { - return CollectionHelper.toImmutableSet( builtinConstraints.keySet() ); + public static Set getBuiltinConstraints() { + return BuiltinConstraint.set(); } /** @@ -1055,7 +1126,7 @@ private static boolean isJsoupInClasspath() { @SuppressWarnings("unchecked") private List> getDefaultValidatorDescriptors(Class annotationType) { //safe cause all CV for a given annotation A are CV - final List> builtInValidators = (List>) builtinConstraints + final List> builtInValidators = (List>) enabledBuiltinConstraints .get( annotationType ); if ( builtInValidators != null ) { diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/PredefinedScopeAllConstraintsTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/PredefinedScopeAllConstraintsTest.java new file mode 100644 index 0000000000..a157dbc051 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/PredefinedScopeAllConstraintsTest.java @@ -0,0 +1,457 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.constraintvalidators; + +import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; + +import java.lang.annotation.Annotation; +import java.math.BigDecimal; +import java.time.Duration; +import java.time.LocalDate; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import javax.money.MonetaryAmount; +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.constraints.AssertFalse; +import javax.validation.constraints.AssertTrue; +import javax.validation.constraints.DecimalMax; +import javax.validation.constraints.DecimalMin; +import javax.validation.constraints.Digits; +import javax.validation.constraints.Email; +import javax.validation.constraints.Future; +import javax.validation.constraints.FutureOrPresent; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.Negative; +import javax.validation.constraints.NegativeOrZero; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Null; +import javax.validation.constraints.Past; +import javax.validation.constraints.PastOrPresent; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Positive; +import javax.validation.constraints.PositiveOrZero; +import javax.validation.constraints.Size; + +import org.hibernate.validator.PredefinedScopeHibernateValidator; +import org.hibernate.validator.constraints.CodePointLength; +import org.hibernate.validator.constraints.CreditCardNumber; +import org.hibernate.validator.constraints.Currency; +import org.hibernate.validator.constraints.EAN; +import org.hibernate.validator.constraints.ISBN; +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.LuhnCheck; +import org.hibernate.validator.constraints.Mod10Check; +import org.hibernate.validator.constraints.Mod11Check; +import org.hibernate.validator.constraints.ModCheck; +import org.hibernate.validator.constraints.ParameterScriptAssert; +import org.hibernate.validator.constraints.Range; +import org.hibernate.validator.constraints.SafeHtml; +import org.hibernate.validator.constraints.ScriptAssert; +import org.hibernate.validator.constraints.URL; +import org.hibernate.validator.constraints.UniqueElements; +import org.hibernate.validator.constraints.br.CNPJ; +import org.hibernate.validator.constraints.br.CPF; +import org.hibernate.validator.constraints.br.TituloEleitoral; +import org.hibernate.validator.constraints.pl.NIP; +import org.hibernate.validator.constraints.pl.PESEL; +import org.hibernate.validator.constraints.pl.REGON; +import org.hibernate.validator.constraints.time.DurationMax; +import org.hibernate.validator.constraints.time.DurationMin; +import org.hibernate.validator.testutil.ConstraintViolationAssert; +import org.javamoney.moneta.Money; +import org.testng.annotations.Test; + +/** + * Test that all the messages of all the constraints are properly interpolated for all the supported locales. + * + * @author Guillaume Smet + */ +@SuppressWarnings("deprecation") +public class PredefinedScopeAllConstraintsTest { + + @Test + public void testConstraints() throws NoSuchMethodException, SecurityException { + testConstraint( AssertFalse.class, new AssertFalseBean() ); + testConstraint( AssertTrue.class, new AssertTrueBean() ); + testConstraint( DecimalMax.class, new DecimalMaxBean() ); + testConstraint( DecimalMin.class, new DecimalMinBean() ); + testConstraint( Digits.class, new DigitsBean() ); + testConstraint( Email.class, new EmailBean() ); + testConstraint( Future.class, new FutureBean() ); + testConstraint( FutureOrPresent.class, new FutureOrPresentBean() ); + testConstraint( Max.class, new MaxBean() ); + testConstraint( Min.class, new MinBean() ); + testConstraint( Negative.class, new NegativeBean() ); + testConstraint( NegativeOrZero.class, new NegativeOrZeroBean() ); + testConstraint( NotBlank.class, new NotBlankBean() ); + testConstraint( NotEmpty.class, new NotEmptyBean() ); + testConstraint( NotNull.class, new NotNullBean() ); + testConstraint( Null.class, new NullBean() ); + testConstraint( Past.class, new PastBean() ); + testConstraint( PastOrPresent.class, new PastOrPresentBean() ); + testConstraint( Pattern.class, new PatternBean() ); + testConstraint( Positive.class, new PositiveBean() ); + testConstraint( PositiveOrZero.class, new PositiveOrZeroBean() ); + testConstraint( Size.class, new SizeBean() ); + testConstraint( CreditCardNumber.class, new CreditCardNumberBean() ); + testConstraint( Currency.class, new CurrencyBean() ); + testConstraint( EAN.class, new EANBean() ); + testConstraint( org.hibernate.validator.constraints.Email.class, new HvEmailBean() ); + testConstraint( ISBN.class, new ISBNBean() ); + testConstraint( Length.class, new LengthBean() ); + testConstraint( CodePointLength.class, new CodePointLengthBean() ); + testConstraint( LuhnCheck.class, new LuhnCheckBean() ); + testConstraint( Mod10Check.class, new Mod10CheckBean() ); + testConstraint( Mod11Check.class, new Mod11CheckBean() ); + testConstraint( ModCheck.class, new ModCheckBean() ); + testConstraint( org.hibernate.validator.constraints.NotBlank.class, new HvNotBlankBean() ); + testConstraint( org.hibernate.validator.constraints.NotEmpty.class, new HvNotEmptyBean() ); + testConstraint( Range.class, new RangeBean() ); + testConstraint( SafeHtml.class, new SafeHtmlBean() ); + testConstraint( UniqueElements.class, new UniqueElementsBean() ); + testConstraint( URL.class, new URLBean() ); + testConstraint( CNPJ.class, new CNPJBean() ); + testConstraint( CPF.class, new CPFBean() ); + testConstraint( TituloEleitoral.class, new TituloEleitoralBean() ); + testConstraint( REGON.class, new REGONBean() ); + testConstraint( NIP.class, new NIPBean() ); + testConstraint( PESEL.class, new PESELBean() ); + testConstraint( DurationMax.class, new DurationMaxBean() ); + testConstraint( DurationMin.class, new DurationMinBean() ); + testConstraint( ScriptAssert.class, new ScriptAssertBean() ); + + Set> parameterScriptAssertBeanViolations = getValidator( ParameterScriptAssert.class, + ParameterScriptAssertBean.class ).forExecutables().validateParameters( + new ParameterScriptAssertBean(), ParameterScriptAssertBean.class.getDeclaredMethod( "doTest", boolean.class ), new Object[]{ false } ); + + ConstraintViolationAssert.assertThat( parameterScriptAssertBeanViolations ) + .containsOnlyViolations( + violationOf( ParameterScriptAssert.class ) ); + } + + private void testConstraint(Class constraint, T bean) { + Set> violations = getValidator( constraint, bean.getClass() ) + .validate( bean ); + ConstraintViolationAssert.assertThat( violations ) + .containsOnlyViolations( + violationOf( constraint ) ); + } + + private static Validator getValidator(Class constraint, Class beanClass) { + return Validation.byProvider( PredefinedScopeHibernateValidator.class ) + .configure() + .builtinConstraints( Collections.singleton( constraint.getName() ) ) + .initializeBeanMetaData( Collections.singleton( beanClass ) ) + .buildValidatorFactory() + .getValidator(); + } + + private static class AssertFalseBean { + + @AssertFalse + private boolean assertFalse = true; + } + + private static class AssertTrueBean { + + @AssertTrue + private boolean assertTrue = false; + } + + private static class DecimalMaxBean { + + @DecimalMax("3") + private double decimalMax = 4; + } + + private static class DecimalMinBean { + + @DecimalMin("3") + private double decimalMin = 2; + } + + private static class DigitsBean { + + @Digits(integer = 1, fraction = 3) + private BigDecimal digits = BigDecimal.valueOf( 13333.3333f ); + } + + private static class EmailBean { + + @Email + private String email = "invalid"; + } + + private static class FutureBean { + + @Future + private LocalDate future = LocalDate.of( 2010, 10, 4 ); + } + + private static class FutureOrPresentBean { + + @FutureOrPresent + private LocalDate futureOrPresent = LocalDate.of( 2010, 10, 4 ); + } + + private static class MaxBean { + + @Max(4) + private int max = 6; + } + + private static class MinBean { + + @Min(4) + private int min = 2; + } + + private static class NegativeBean { + + @Negative + private int negative = 4; + } + + private static class NegativeOrZeroBean { + + @NegativeOrZero + private int negativeOrZero = 4; + } + + private static class NotBlankBean { + + @NotBlank + private String notBlank = ""; + } + + private static class NotEmptyBean { + + @NotEmpty + private List notEmpty = Collections.emptyList(); + } + + private static class NotNullBean { + + @NotNull + private String notNull = null; + } + + private static class NullBean { + + @Null + private String nullConstraint = "not null"; + } + + private static class PastBean { + + @Past + private LocalDate past = LocalDate.of( 2890, 10, 4 ); + } + + private static class PastOrPresentBean { + + @PastOrPresent + private LocalDate pastOrPresent = LocalDate.of( 2890, 10, 4 ); + } + + private static class PatternBean { + + @Pattern(regexp = "[0-9]+") + private String pattern = "invalid"; + } + + private static class PositiveBean { + + @Positive + private int positive = -4; + } + + private static class PositiveOrZeroBean { + + @PositiveOrZero + private int positiveOrZero = -4; + } + + private static class SizeBean { + + @Size(min = 2, max = 4) + private String size = "666666"; + } + + private static class CreditCardNumberBean { + + @CreditCardNumber + private String creditCardNumber = "invalid"; + } + + private static class CurrencyBean { + + @Currency("EUR") + private MonetaryAmount currency = Money.of( 1000f, "USD" ); + } + + private static class EANBean { + + @EAN + private String ean = "invalid"; + } + + private static class HvEmailBean { + + @org.hibernate.validator.constraints.Email + private String hvEmail = "invalid"; + } + + private static class ISBNBean { + + @ISBN + private String isbn = "invalid"; + } + + private static class LengthBean { + + @Length(min = 2, max = 4) + private String length = "666666"; + } + + private static class CodePointLengthBean { + + @CodePointLength(min = 2, max = 4) + private String codePointLength = "666666"; + } + + private static class LuhnCheckBean { + + @LuhnCheck + private String luhnCheck = "4"; + } + + private static class Mod10CheckBean { + + @Mod10Check + private String mod10Check = "4"; + } + + private static class Mod11CheckBean { + + @Mod11Check + private String mod11Check = "4"; + } + + private static class ModCheckBean { + + @ModCheck(multiplier = 2, modType = ModCheck.ModType.MOD10) + private String modCheck = "4"; + } + + private static class HvNotBlankBean { + + @org.hibernate.validator.constraints.NotBlank + private String hvNotBlank = ""; + } + + private static class HvNotEmptyBean { + + @org.hibernate.validator.constraints.NotEmpty + private List hvNotEmpty = Collections.emptyList(); + } + + private static class RangeBean { + + @Range(min = 2, max = 4) + private int range = 6; + } + + private static class SafeHtmlBean { + + @SafeHtml + private String safeHtml = ""; + } + + private static class UniqueElementsBean { + + @UniqueElements + private List uniqueElements = Arrays.asList( "a", "a" ); + } + + private static class URLBean { + + @URL + private String url = "invalid"; + } + + private static class CNPJBean { + + @CNPJ + private String cnpj = "invalid"; + } + + private static class CPFBean { + + @CPF + private String cpf = "invalid"; + } + + private static class TituloEleitoralBean { + + @TituloEleitoral + private String tituloEleitoral = "invalid"; + } + + private static class REGONBean { + + @REGON + private String regon = "invalid"; + } + + private static class NIPBean { + + @NIP + private String nip = "invalid"; + } + + private static class PESELBean { + + @PESEL + private String pesel = "invalid"; + } + + private static class DurationMaxBean { + + @DurationMax(days = 4, hours = 4, minutes = 4, millis = 4, nanos = 4) + private Duration durationMax = Duration.ofDays( 8 ); + } + + private static class DurationMinBean { + + @DurationMin(days = 4, hours = 4, minutes = 4, millis = 4, nanos = 4) + private Duration durationMin = Duration.ofDays( 2 ); + } + + @ScriptAssert(lang = "groovy", script = "_this.scriptAssert") + private static class ScriptAssertBean { + + @SuppressWarnings("unused") + private boolean scriptAssert = false; + } + + private static class ParameterScriptAssertBean { + + @ParameterScriptAssert(lang = "groovy", script = "test") + public boolean doTest(boolean test) { + return test; + } + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java index b80ccd14f1..4f4b986847 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java @@ -42,7 +42,7 @@ public void setUp() { // Create some annotations for testing using AnnotationProxies ConstraintAnnotationDescriptor.Builder notNullAnnotationDescriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( NotNull.class ); notNullDescriptor = new ConstraintDescriptorImpl<>( - new ConstraintHelper(), + ConstraintHelper.forAllBuiltinConstraints(), null, notNullAnnotationDescriptorBuilder.build(), ConstraintLocationKind.FIELD @@ -50,7 +50,7 @@ public void setUp() { ConstraintAnnotationDescriptor.Builder sizeAnnotationDescriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( Size.class ); sizeDescriptor = new ConstraintDescriptorImpl<>( - new ConstraintHelper(), + ConstraintHelper.forAllBuiltinConstraints(), null, sizeAnnotationDescriptorBuilder.build(), ConstraintLocationKind.FIELD diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java index 5636bafda4..09bbbd198b 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java @@ -52,7 +52,7 @@ public void setUp() { // Create some annotations for testing using AnnotationProxies ConstraintAnnotationDescriptor.Builder descriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( NotNull.class ); notNullDescriptor = new ConstraintDescriptorImpl<>( - new ConstraintHelper(), + ConstraintHelper.forAllBuiltinConstraints(), null, descriptorBuilder.build(), ConstraintLocationKind.FIELD @@ -60,7 +60,7 @@ public void setUp() { ConstraintAnnotationDescriptor.Builder sizeAnnotationDescriptorBuilder = new ConstraintAnnotationDescriptor.Builder( Size.class ); sizeDescriptor = new ConstraintDescriptorImpl<>( - new ConstraintHelper(), + ConstraintHelper.forAllBuiltinConstraints(), null, sizeAnnotationDescriptorBuilder.build(), ConstraintLocationKind.FIELD @@ -214,7 +214,7 @@ public void testRecursiveMessageInterpolation() { ConstraintAnnotationDescriptor descriptor = descriptorBuilder.build(); ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl( - new ConstraintHelper(), + ConstraintHelper.forAllBuiltinConstraints(), null, descriptorBuilder.build(), ConstraintLocationKind.FIELD @@ -243,7 +243,7 @@ public void testCorrectMessageInterpolationIfParameterCannotBeReplaced() { ConstraintAnnotationDescriptor maxDescriptor = descriptorBuilder.build(); ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl( - new ConstraintHelper(), + ConstraintHelper.forAllBuiltinConstraints(), null, maxDescriptor, ConstraintLocationKind.FIELD diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/ConstraintHelperTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/ConstraintHelperTest.java index 2eb7604455..4708fae57b 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/ConstraintHelperTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/ConstraintHelperTest.java @@ -31,7 +31,7 @@ public class ConstraintHelperTest { @BeforeClass public static void init() { - constraintHelper = new ConstraintHelper(); + constraintHelper = ConstraintHelper.forAllBuiltinConstraints(); } @Test diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java index cb8a4a04b2..11f91dc1b5 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/metadata/core/MetaConstraintTest.java @@ -45,7 +45,7 @@ public class MetaConstraintTest { @BeforeClass public void setUp() throws Exception { - constraintHelper = new ConstraintHelper(); + constraintHelper = ConstraintHelper.forAllBuiltinConstraints(); typeResolutionHelper = new TypeResolutionHelper(); valueExtractorManager = new ValueExtractorManager( Collections.emptySet() ); constraintValidatorManager = new ConstraintValidatorManagerImpl( new ConstraintValidatorFactoryImpl(), getDummyConstraintValidatorInitializationContext() ); diff --git a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java index 2e94a98448..d92a8362d5 100644 --- a/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/predefinedscope/PredefinedScopeValidatorFactoryTest.java @@ -14,6 +14,7 @@ import java.lang.annotation.ElementType; import java.util.AbstractCollection; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -245,6 +246,7 @@ public void testBeanMetaDataClassNormalizer() { ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) .configure() + .builtinConstraints( new HashSet<>( Arrays.asList( Email.class.getName(), NotNull.class.getName() ) ) ) .initializeBeanMetaData( beanMetaDataToInitialize ) .locales( Collections.singleton( Locale.getDefault() ) ) .beanMetaDataClassNormalizer( new MyProxyInterfaceBeanMetaDataClassNormalizer() ) @@ -266,6 +268,7 @@ public void validatorSpecificTraversableResolver() { ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) .configure() + .builtinConstraints( new HashSet<>( Arrays.asList( Email.class.getName(), NotNull.class.getName() ) ) ) .initializeBeanMetaData( beanMetaDataToInitialize ) .buildValidatorFactory(); @@ -290,6 +293,7 @@ public void variousObjectTypes() { ValidatorFactory validatorFactory = Validation.byProvider( PredefinedScopeHibernateValidator.class ) .configure() + .builtinConstraints( new HashSet<>( Arrays.asList( Email.class.getName(), NotNull.class.getName() ) ) ) .initializeBeanMetaData( beanMetaDataToInitialize ) .buildValidatorFactory(); @@ -330,6 +334,7 @@ private static ValidatorFactory getValidatorFactory() { return Validation.byProvider( PredefinedScopeHibernateValidator.class ) .configure() + .builtinConstraints( new HashSet<>( Arrays.asList( Email.class.getName(), NotNull.class.getName() ) ) ) .initializeBeanMetaData( beanMetaDataToInitialize ) .buildValidatorFactory(); } @@ -344,6 +349,7 @@ private static ValidatorFactory getValidatorFactoryWithInitializedLocale(Locale return Validation.byProvider( PredefinedScopeHibernateValidator.class ) .configure() + .builtinConstraints( new HashSet<>( Arrays.asList( Email.class.getName(), NotNull.class.getName() ) ) ) .initializeBeanMetaData( beanMetaDataToInitialize ) .locales( Collections.singleton( locale ) ) .buildValidatorFactory(); diff --git a/engine/src/test/java/org/hibernate/validator/testutils/ConstraintValidatorInitializationHelper.java b/engine/src/test/java/org/hibernate/validator/testutils/ConstraintValidatorInitializationHelper.java index 1978dc0c6b..86ab72ad86 100644 --- a/engine/src/test/java/org/hibernate/validator/testutils/ConstraintValidatorInitializationHelper.java +++ b/engine/src/test/java/org/hibernate/validator/testutils/ConstraintValidatorInitializationHelper.java @@ -34,7 +34,7 @@ */ public class ConstraintValidatorInitializationHelper { - private static final ConstraintHelper CONSTRAINT_HELPER = new ConstraintHelper(); + private static final ConstraintHelper CONSTRAINT_HELPER = ConstraintHelper.forAllBuiltinConstraints(); private static final HibernateConstraintValidatorInitializationContext DUMMY_CONSTRAINT_VALIDATOR_INITIALIZATION_CONTEXT = getConstraintValidatorInitializationContext( new DefaultScriptEvaluatorFactory( null ), DefaultClockProvider.INSTANCE, Duration.ZERO ); @@ -73,7 +73,7 @@ public static HibernateConstraintValidatorInitializationContext getDummyConstrai } public static ConstraintCreationContext getDummyConstraintCreationContext() { - return new ConstraintCreationContext( new ConstraintHelper(), + return new ConstraintCreationContext( ConstraintHelper.forAllBuiltinConstraints(), new ConstraintValidatorManagerImpl( new ConstraintValidatorFactoryImpl(), getDummyConstraintValidatorInitializationContext() ), new TypeResolutionHelper(), new ValueExtractorManager( Collections.emptySet() ) ); From 301f87af77d3b21d9999853719ad59225d406628 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 15 Apr 2020 20:04:49 +0200 Subject: [PATCH 320/393] HV-1767 Remove unused method from ConstraintHelper --- .../internal/metadata/core/ConstraintHelper.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java index d912d9481f..ce4f07622f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java @@ -813,16 +813,6 @@ private static void putConstraint(Map void putConstraints(Map, List>> validators, - Class constraintType, Class> validatorType1, Class> validatorType2) { - List> descriptors = new ArrayList<>( 2 ); - - descriptors.add( ConstraintValidatorDescriptor.forClass( validatorType1, constraintType ) ); - descriptors.add( ConstraintValidatorDescriptor.forClass( validatorType2, constraintType ) ); - - validators.put( constraintType, CollectionHelper.toImmutableList( descriptors ) ); - } - private static void putConstraints(Map, List>> validators, Class constraintType, List>> validatorTypes) { List> descriptors = new ArrayList<>( validatorTypes.size() ); From 95a18107d9522d13ba5e380e1aa6f59c8b3639dc Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 16 Apr 2020 13:57:26 +0200 Subject: [PATCH 321/393] HV-1767 Optimize how optional features are detected --- .../metadata/core/ConstraintHelper.java | 38 +++++++++++------- .../privilegedactions/IsClassPresent.java | 39 +++++++++++++++++++ 2 files changed, 62 insertions(+), 15 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/IsClassPresent.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java index ce4f07622f..0ad4ee8fa7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java @@ -79,7 +79,6 @@ import javax.validation.Constraint; import javax.validation.ConstraintTarget; import javax.validation.ConstraintValidator; -import javax.validation.ValidationException; import javax.validation.constraints.AssertFalse; import javax.validation.constraints.AssertTrue; import javax.validation.constraints.DecimalMax; @@ -348,7 +347,7 @@ import org.hibernate.validator.internal.util.privilegedactions.GetAnnotationAttribute; import org.hibernate.validator.internal.util.privilegedactions.GetDeclaredMethods; import org.hibernate.validator.internal.util.privilegedactions.GetMethod; -import org.hibernate.validator.internal.util.privilegedactions.LoadClass; +import org.hibernate.validator.internal.util.privilegedactions.IsClassPresent; import org.hibernate.validator.internal.util.stereotypes.Immutable; /** @@ -382,6 +381,12 @@ public class ConstraintHelper { private final ValidatorDescriptorMap validatorDescriptors = new ValidatorDescriptorMap(); + private Boolean javaMoneyInClasspath; + + private Boolean jodaTimeInClassPath; + + private Boolean jsoupInClasspath; + public static ConstraintHelper forAllBuiltinConstraints() { return new ConstraintHelper( new HashSet<>( Arrays.asList( BuiltinConstraint.values() ) ) ); } @@ -1092,16 +1097,25 @@ public void clear() { multiValueConstraints.clear(); } - private static boolean isJodaTimeInClasspath() { - return isClassPresent( JODA_TIME_CLASS_NAME ); + private boolean isJodaTimeInClasspath() { + if ( jodaTimeInClassPath == null ) { + jodaTimeInClassPath = isClassPresent( JODA_TIME_CLASS_NAME ); + } + return jodaTimeInClassPath.booleanValue(); } - private static boolean isJavaMoneyInClasspath() { - return isClassPresent( JAVA_MONEY_CLASS_NAME ); + private boolean isJavaMoneyInClasspath() { + if ( javaMoneyInClasspath == null ) { + javaMoneyInClasspath = isClassPresent( JAVA_MONEY_CLASS_NAME ); + } + return javaMoneyInClasspath.booleanValue(); } - private static boolean isJsoupInClasspath() { - return isClassPresent( JSOUP_CLASS_NAME ); + private boolean isJsoupInClasspath() { + if ( jsoupInClasspath == null ) { + jsoupInClasspath = isClassPresent( JSOUP_CLASS_NAME ); + } + return jsoupInClasspath.booleanValue(); } /** @@ -1133,13 +1147,7 @@ private List> getDefault } private static boolean isClassPresent(String className) { - try { - run( LoadClass.action( className, ConstraintHelper.class.getClassLoader(), false ) ); - return true; - } - catch (ValidationException e) { - return false; - } + return run( IsClassPresent.action( className, ConstraintHelper.class.getClassLoader() ) ).booleanValue(); } /** diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/IsClassPresent.java b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/IsClassPresent.java new file mode 100644 index 0000000000..dffd319ae1 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/IsClassPresent.java @@ -0,0 +1,39 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.util.privilegedactions; + +import java.security.PrivilegedAction; + +/** + * Checks if an external class is present in the provided class loader. + */ +public final class IsClassPresent implements PrivilegedAction { + + private final String className; + + private final ClassLoader classLoader; + + public static IsClassPresent action(String className, ClassLoader classLoader) { + return new IsClassPresent( className, classLoader ); + } + + private IsClassPresent(String className, ClassLoader classLoader) { + this.className = className; + this.classLoader = classLoader; + } + + @Override + public Boolean run() { + try { + Class.forName( className, false, classLoader ); + return Boolean.TRUE; + } + catch (ClassNotFoundException e) { + return Boolean.FALSE; + } + } +} From fca1e49d679088058fb90896b21b84b81f25321c Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 16 Apr 2020 13:59:36 +0200 Subject: [PATCH 322/393] HV-1770 Rename method for more clarity before doing more changes --- .../metadata/core/ConstraintHelper.java | 104 +++++++++--------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java index 0ad4ee8fa7..03d0a458ef 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java @@ -407,10 +407,10 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { // Bean Validation constraints if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_ASSERT_FALSE ) ) { - putConstraint( tmpConstraints, AssertFalse.class, AssertFalseValidator.class ); + putBuiltinConstraint( tmpConstraints, AssertFalse.class, AssertFalseValidator.class ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_ASSERT_TRUE ) ) { - putConstraint( tmpConstraints, AssertTrue.class, AssertTrueValidator.class ); + putBuiltinConstraint( tmpConstraints, AssertTrue.class, AssertTrueValidator.class ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_DECIMAL_MAX ) ) { @@ -428,7 +428,7 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { if ( isJavaMoneyInClasspath() ) { decimalMaxValidators.add( DecimalMaxValidatorForMonetaryAmount.class ); } - putConstraints( tmpConstraints, DecimalMax.class, decimalMaxValidators ); + putBuiltinConstraints( tmpConstraints, DecimalMax.class, decimalMaxValidators ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_DECIMAL_MIN ) ) { List>> decimalMinValidators = new ArrayList<>(); @@ -445,7 +445,7 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { if ( isJavaMoneyInClasspath() ) { decimalMinValidators.add( DecimalMinValidatorForMonetaryAmount.class ); } - putConstraints( tmpConstraints, DecimalMin.class, decimalMinValidators ); + putBuiltinConstraints( tmpConstraints, DecimalMin.class, decimalMinValidators ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_DIGITS ) ) { List>> digitsValidators = new ArrayList<>(); @@ -454,11 +454,11 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { if ( isJavaMoneyInClasspath() ) { digitsValidators.add( DigitsValidatorForMonetaryAmount.class ); } - putConstraints( tmpConstraints, Digits.class, digitsValidators ); + putBuiltinConstraints( tmpConstraints, Digits.class, digitsValidators ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_EMAIL ) ) { - putConstraint( tmpConstraints, Email.class, EmailValidator.class ); + putBuiltinConstraint( tmpConstraints, Email.class, EmailValidator.class ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_FUTURE ) ) { @@ -485,7 +485,7 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { futureValidators.add( FutureValidatorForYearMonth.class ); futureValidators.add( FutureValidatorForZonedDateTime.class ); - putConstraints( tmpConstraints, Future.class, futureValidators ); + putBuiltinConstraints( tmpConstraints, Future.class, futureValidators ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_FUTURE_OR_PRESENT ) ) { @@ -512,7 +512,7 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { futureOrPresentValidators.add( FutureOrPresentValidatorForYearMonth.class ); futureOrPresentValidators.add( FutureOrPresentValidatorForZonedDateTime.class ); - putConstraints( tmpConstraints, FutureOrPresent.class, futureOrPresentValidators ); + putBuiltinConstraints( tmpConstraints, FutureOrPresent.class, futureOrPresentValidators ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_MAX ) ) { @@ -530,7 +530,7 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { if ( isJavaMoneyInClasspath() ) { maxValidators.add( MaxValidatorForMonetaryAmount.class ); } - putConstraints( tmpConstraints, Max.class, maxValidators ); + putBuiltinConstraints( tmpConstraints, Max.class, maxValidators ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_MIN ) ) { List>> minValidators = new ArrayList<>(); @@ -547,7 +547,7 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { if ( isJavaMoneyInClasspath() ) { minValidators.add( MinValidatorForMonetaryAmount.class ); } - putConstraints( tmpConstraints, Min.class, minValidators ); + putBuiltinConstraints( tmpConstraints, Min.class, minValidators ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NEGATIVE ) ) { @@ -564,7 +564,7 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { if ( isJavaMoneyInClasspath() ) { negativeValidators.add( NegativeValidatorForMonetaryAmount.class ); } - putConstraints( tmpConstraints, Negative.class, negativeValidators ); + putBuiltinConstraints( tmpConstraints, Negative.class, negativeValidators ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NEGATIVE_OR_ZERO ) ) { @@ -581,11 +581,11 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { if ( isJavaMoneyInClasspath() ) { negativeOrZeroValidators.add( NegativeOrZeroValidatorForMonetaryAmount.class ); } - putConstraints( tmpConstraints, NegativeOrZero.class, negativeOrZeroValidators ); + putBuiltinConstraints( tmpConstraints, NegativeOrZero.class, negativeOrZeroValidators ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NOT_BLANK ) ) { - putConstraint( tmpConstraints, NotBlank.class, NotBlankValidator.class ); + putBuiltinConstraint( tmpConstraints, NotBlank.class, NotBlankValidator.class ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NOT_EMPTY ) ) { @@ -602,14 +602,14 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { notEmptyValidators.add( NotEmptyValidatorForArraysOfInt.class ); notEmptyValidators.add( NotEmptyValidatorForArraysOfLong.class ); notEmptyValidators.add( NotEmptyValidatorForArraysOfShort.class ); - putConstraints( tmpConstraints, NotEmpty.class, notEmptyValidators ); + putBuiltinConstraints( tmpConstraints, NotEmpty.class, notEmptyValidators ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NOT_NULL ) ) { - putConstraint( tmpConstraints, NotNull.class, NotNullValidator.class ); + putBuiltinConstraint( tmpConstraints, NotNull.class, NotNullValidator.class ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_NULL ) ) { - putConstraint( tmpConstraints, Null.class, NullValidator.class ); + putBuiltinConstraint( tmpConstraints, Null.class, NullValidator.class ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_PAST ) ) { @@ -636,7 +636,7 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { pastValidators.add( PastValidatorForYearMonth.class ); pastValidators.add( PastValidatorForZonedDateTime.class ); - putConstraints( tmpConstraints, Past.class, pastValidators ); + putBuiltinConstraints( tmpConstraints, Past.class, pastValidators ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_PAST_OR_PRESENT ) ) { @@ -663,11 +663,11 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { pastOrPresentValidators.add( PastOrPresentValidatorForYearMonth.class ); pastOrPresentValidators.add( PastOrPresentValidatorForZonedDateTime.class ); - putConstraints( tmpConstraints, PastOrPresent.class, pastOrPresentValidators ); + putBuiltinConstraints( tmpConstraints, PastOrPresent.class, pastOrPresentValidators ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_PATTERN ) ) { - putConstraint( tmpConstraints, Pattern.class, PatternValidator.class ); + putBuiltinConstraint( tmpConstraints, Pattern.class, PatternValidator.class ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_POSITIVE ) ) { @@ -684,7 +684,7 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { if ( isJavaMoneyInClasspath() ) { positiveValidators.add( PositiveValidatorForMonetaryAmount.class ); } - putConstraints( tmpConstraints, Positive.class, positiveValidators ); + putBuiltinConstraints( tmpConstraints, Positive.class, positiveValidators ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_POSITIVE_OR_ZERO ) ) { @@ -701,7 +701,7 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { if ( isJavaMoneyInClasspath() ) { positiveOrZeroValidators.add( PositiveOrZeroValidatorForMonetaryAmount.class ); } - putConstraints( tmpConstraints, PositiveOrZero.class, positiveOrZeroValidators ); + putBuiltinConstraints( tmpConstraints, PositiveOrZero.class, positiveOrZeroValidators ); } if ( enabledBuiltinConstraints.contains( JAVAX_VALIDATION_CONSTRAINTS_SIZE ) ) { @@ -718,107 +718,107 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { sizeValidators.add( SizeValidatorForArraysOfInt.class ); sizeValidators.add( SizeValidatorForArraysOfLong.class ); sizeValidators.add( SizeValidatorForArraysOfShort.class ); - putConstraints( tmpConstraints, Size.class, sizeValidators ); + putBuiltinConstraints( tmpConstraints, Size.class, sizeValidators ); } // Hibernate Validator specific constraints if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_CNPJ ) ) { - putConstraint( tmpConstraints, CNPJ.class, CNPJValidator.class ); + putBuiltinConstraint( tmpConstraints, CNPJ.class, CNPJValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_CPF ) ) { - putConstraint( tmpConstraints, CPF.class, CPFValidator.class ); + putBuiltinConstraint( tmpConstraints, CPF.class, CPFValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CURRENCY ) && isJavaMoneyInClasspath() ) { - putConstraint( tmpConstraints, Currency.class, CurrencyValidatorForMonetaryAmount.class ); + putBuiltinConstraint( tmpConstraints, Currency.class, CurrencyValidatorForMonetaryAmount.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CREDIT_CARD_NUMBER ) ) { - putConstraint( tmpConstraints, CreditCardNumber.class ); + putBuiltinConstraint( tmpConstraints, CreditCardNumber.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_TIME_DURATION_MAX ) ) { - putConstraint( tmpConstraints, DurationMax.class, DurationMaxValidator.class ); + putBuiltinConstraint( tmpConstraints, DurationMax.class, DurationMaxValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_TIME_DURATION_MIN ) ) { - putConstraint( tmpConstraints, DurationMin.class, DurationMinValidator.class ); + putBuiltinConstraint( tmpConstraints, DurationMin.class, DurationMinValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_EAN ) ) { - putConstraint( tmpConstraints, EAN.class, EANValidator.class ); + putBuiltinConstraint( tmpConstraints, EAN.class, EANValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_EMAIL ) ) { - putConstraint( tmpConstraints, org.hibernate.validator.constraints.Email.class, org.hibernate.validator.internal.constraintvalidators.hv.EmailValidator.class ); + putBuiltinConstraint( tmpConstraints, org.hibernate.validator.constraints.Email.class, org.hibernate.validator.internal.constraintvalidators.hv.EmailValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_ISBN ) ) { - putConstraint( tmpConstraints, ISBN.class, ISBNValidator.class ); + putBuiltinConstraint( tmpConstraints, ISBN.class, ISBNValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_LENGTH ) ) { - putConstraint( tmpConstraints, Length.class, LengthValidator.class ); + putBuiltinConstraint( tmpConstraints, Length.class, LengthValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_CODE_POINT_LENGTH ) ) { - putConstraint( tmpConstraints, CodePointLength.class, CodePointLengthValidator.class ); + putBuiltinConstraint( tmpConstraints, CodePointLength.class, CodePointLengthValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_LUHN_CHECK ) ) { - putConstraint( tmpConstraints, LuhnCheck.class, LuhnCheckValidator.class ); + putBuiltinConstraint( tmpConstraints, LuhnCheck.class, LuhnCheckValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD_CHECK ) ) { - putConstraint( tmpConstraints, ModCheck.class, ModCheckValidator.class ); + putBuiltinConstraint( tmpConstraints, ModCheck.class, ModCheckValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD10_CHECK ) ) { - putConstraint( tmpConstraints, Mod10Check.class, Mod10CheckValidator.class ); + putBuiltinConstraint( tmpConstraints, Mod10Check.class, Mod10CheckValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD11_CHECK ) ) { - putConstraint( tmpConstraints, Mod11Check.class, Mod11CheckValidator.class ); + putBuiltinConstraint( tmpConstraints, Mod11Check.class, Mod11CheckValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_NIP ) ) { - putConstraint( tmpConstraints, NIP.class, NIPValidator.class ); + putBuiltinConstraint( tmpConstraints, NIP.class, NIPValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NOT_BLANK ) ) { - putConstraint( tmpConstraints, org.hibernate.validator.constraints.NotBlank.class, org.hibernate.validator.internal.constraintvalidators.hv.NotBlankValidator.class ); + putBuiltinConstraint( tmpConstraints, org.hibernate.validator.constraints.NotBlank.class, org.hibernate.validator.internal.constraintvalidators.hv.NotBlankValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NOT_EMPTY ) ) { - putConstraint( tmpConstraints, org.hibernate.validator.constraints.NotEmpty.class ); + putBuiltinConstraint( tmpConstraints, org.hibernate.validator.constraints.NotEmpty.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PARAMETER_SCRIPT_ASSERT ) ) { - putConstraint( tmpConstraints, ParameterScriptAssert.class, ParameterScriptAssertValidator.class ); + putBuiltinConstraint( tmpConstraints, ParameterScriptAssert.class, ParameterScriptAssertValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_PESEL ) ) { - putConstraint( tmpConstraints, PESEL.class, PESELValidator.class ); + putBuiltinConstraint( tmpConstraints, PESEL.class, PESELValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_RANGE ) ) { - putConstraint( tmpConstraints, Range.class ); + putBuiltinConstraint( tmpConstraints, Range.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_REGON ) ) { - putConstraint( tmpConstraints, REGON.class, REGONValidator.class ); + putBuiltinConstraint( tmpConstraints, REGON.class, REGONValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_SAFE_HTML ) && isJsoupInClasspath() ) { - putConstraint( tmpConstraints, SafeHtml.class, SafeHtmlValidator.class ); + putBuiltinConstraint( tmpConstraints, SafeHtml.class, SafeHtmlValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_SCRIPT_ASSERT ) ) { - putConstraint( tmpConstraints, ScriptAssert.class, ScriptAssertValidator.class ); + putBuiltinConstraint( tmpConstraints, ScriptAssert.class, ScriptAssertValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_BR_TITULO_ELEITORAL ) ) { - putConstraint( tmpConstraints, TituloEleitoral.class ); + putBuiltinConstraint( tmpConstraints, TituloEleitoral.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_UNIQUE_ELEMENTS ) ) { - putConstraint( tmpConstraints, UniqueElements.class, UniqueElementsValidator.class ); + putBuiltinConstraint( tmpConstraints, UniqueElements.class, UniqueElementsValidator.class ); } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_URL ) ) { - putConstraint( tmpConstraints, URL.class, URLValidator.class ); + putBuiltinConstraint( tmpConstraints, URL.class, URLValidator.class ); } this.enabledBuiltinConstraints = Collections.unmodifiableMap( tmpConstraints ); } - private static void putConstraint(Map, List>> validators, + private static void putBuiltinConstraint(Map, List>> validators, Class constraintType) { validators.put( constraintType, Collections.emptyList() ); } - private static void putConstraint(Map, List>> validators, + private static void putBuiltinConstraint(Map, List>> validators, Class constraintType, Class> validatorType) { validators.put( constraintType, Collections.singletonList( ConstraintValidatorDescriptor.forClass( validatorType, constraintType ) ) ); } - private static void putConstraints(Map, List>> validators, + private static void putBuiltinConstraints(Map, List>> validators, Class constraintType, List>> validatorTypes) { List> descriptors = new ArrayList<>( validatorTypes.size() ); From c84093baf508b6093a5aa6f02a555394aeafae7c Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 16 Apr 2020 14:01:59 +0200 Subject: [PATCH 323/393] HV-1770 Relax constraint consistency checking for built-in constraints --- .../ClassBasedValidatorDescriptor.java | 9 +++++++++ .../ConstraintValidatorDescriptor.java | 5 +++++ .../internal/metadata/core/ConstraintHelper.java | 4 ++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ClassBasedValidatorDescriptor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ClassBasedValidatorDescriptor.java index fd5f8c96ce..5fc6530cd6 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ClassBasedValidatorDescriptor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ClassBasedValidatorDescriptor.java @@ -52,6 +52,15 @@ public static ClassBasedValidatorDescriptor of(Class( validatorClass ); } + /** + * Constraint checking is relaxed for built-in constraints as they have been carefully crafted so we are sure types + * are right. + */ + public static ClassBasedValidatorDescriptor ofBuiltin(Class> validatorClass, + Class registeredConstraintAnnotationType) { + return new ClassBasedValidatorDescriptor( validatorClass ); + } + private static EnumSet determineValidationTargets(Class> validatorClass) { SupportedValidationTarget supportedTargetAnnotation = validatorClass.getAnnotation( SupportedValidationTarget.class ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorDescriptor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorDescriptor.java index cb4da5b2ec..5cf692e8d4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorDescriptor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorDescriptor.java @@ -49,6 +49,11 @@ static ConstraintValidatorDescriptor forClass(Class ConstraintValidatorDescriptor forBuiltinClass(Class> validatorClass, + Class constraintAnnotationType) { + return ClassBasedValidatorDescriptor.ofBuiltin( validatorClass, constraintAnnotationType ); + } + static ConstraintValidatorDescriptor forLambda(Class annotationType, Type validatedType, ValidationCallable lambda) { return new LambdaBasedValidatorDescriptor<>( validatedType, lambda ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java index 03d0a458ef..82e60f7a1b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java @@ -815,7 +815,7 @@ private static void putBuiltinConstraint(Map void putBuiltinConstraint(Map, List>> validators, Class constraintType, Class> validatorType) { - validators.put( constraintType, Collections.singletonList( ConstraintValidatorDescriptor.forClass( validatorType, constraintType ) ) ); + validators.put( constraintType, Collections.singletonList( ConstraintValidatorDescriptor.forBuiltinClass( validatorType, constraintType ) ) ); } private static void putBuiltinConstraints(Map, List>> validators, @@ -823,7 +823,7 @@ private static void putBuiltinConstraints(Map> descriptors = new ArrayList<>( validatorTypes.size() ); for ( Class> validatorType : validatorTypes ) { - descriptors.add( ConstraintValidatorDescriptor.forClass( validatorType, constraintType ) ); + descriptors.add( ConstraintValidatorDescriptor.forBuiltinClass( validatorType, constraintType ) ); } validators.put( constraintType, CollectionHelper.toImmutableList( descriptors ) ); From ea74084ca26289696f6ccf50a579a782152f0a5f Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 16 Apr 2020 14:45:52 +0200 Subject: [PATCH 324/393] HV-1769 Only create the default TraversableResolver if none has been specified --- .../engine/AbstractConfigurationImpl.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java index f2a4b11465..702effaf6b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java @@ -54,6 +54,7 @@ import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader; import org.hibernate.validator.internal.util.privilegedactions.GetInstancesFromServiceLoader; import org.hibernate.validator.internal.util.privilegedactions.SetContextClassLoader; +import org.hibernate.validator.internal.util.stereotypes.Lazy; import org.hibernate.validator.internal.xml.config.ValidationBootstrapParameters; import org.hibernate.validator.internal.xml.config.ValidationXmlParser; import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; @@ -88,11 +89,19 @@ public abstract class AbstractConfigurationImpl provider) { private AbstractConfigurationImpl() { this.validationBootstrapParameters = new ValidationBootstrapParameters(); - this.defaultTraversableResolver = TraversableResolvers.getDefault(); this.defaultConstraintValidatorFactory = new ConstraintValidatorFactoryImpl(); this.defaultParameterNameProvider = new DefaultParameterNameProvider(); this.defaultClockProvider = DefaultClockProvider.INSTANCE; @@ -566,6 +574,9 @@ public final MessageInterpolator getDefaultMessageInterpolator() { @Override public final TraversableResolver getDefaultTraversableResolver() { + if ( defaultTraversableResolver == null ) { + defaultTraversableResolver = TraversableResolvers.getDefault(); + } return defaultTraversableResolver; } @@ -632,7 +643,7 @@ private void parseValidationXml() { LOG.ignoringXmlConfiguration(); if ( validationBootstrapParameters.getTraversableResolver() == null ) { - validationBootstrapParameters.setTraversableResolver( defaultTraversableResolver ); + validationBootstrapParameters.setTraversableResolver( getDefaultTraversableResolver() ); } if ( validationBootstrapParameters.getConstraintValidatorFactory() == null ) { validationBootstrapParameters.setConstraintValidatorFactory( defaultConstraintValidatorFactory ); @@ -681,7 +692,7 @@ private void applyXmlSettings(ValidationBootstrapParameters xmlParameters) { validationBootstrapParameters.setTraversableResolver( xmlParameters.getTraversableResolver() ); } else { - validationBootstrapParameters.setTraversableResolver( defaultTraversableResolver ); + validationBootstrapParameters.setTraversableResolver( getDefaultTraversableResolver() ); } } From a4818b458959b24436de4254296f7d1b92502775 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 17 Apr 2020 12:39:16 +0200 Subject: [PATCH 325/393] HV-1760 Clean up Min/Max/... implementations for CharSequence --- .../DecimalMaxValidatorForCharSequence.java | 56 ------------------- .../DecimalMinValidatorForCharSequence.java | 56 ------------------- .../bv/MaxValidatorForCharSequence.java | 43 -------------- .../bound/MaxValidatorForCharSequence.java | 30 ++++++++++ .../bound}/MinValidatorForCharSequence.java | 25 ++------- .../DecimalMaxValidatorForCharSequence.java | 29 ++++++++++ .../DecimalMinValidatorForCharSequence.java | 29 ++++++++++ .../metadata/core/ConstraintHelper.java | 8 +-- .../bv/MaxValidatorForStringTest.java | 4 +- .../bv/MinValidatorForStringTest.java | 4 +- 10 files changed, 102 insertions(+), 182 deletions(-) delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/DecimalMaxValidatorForCharSequence.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/DecimalMinValidatorForCharSequence.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/MaxValidatorForCharSequence.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForCharSequence.java rename engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/{ => number/bound}/MinValidatorForCharSequence.java (50%) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForCharSequence.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForCharSequence.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/DecimalMaxValidatorForCharSequence.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/DecimalMaxValidatorForCharSequence.java deleted file mode 100644 index fec9eaf271..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/DecimalMaxValidatorForCharSequence.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.constraintvalidators.bv; - -import java.lang.invoke.MethodHandles; -import java.math.BigDecimal; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; -import javax.validation.constraints.DecimalMax; - -import org.hibernate.validator.internal.util.logging.Log; -import org.hibernate.validator.internal.util.logging.LoggerFactory; - -/** - * Check that the character sequence (e.g. string) being validated represents a number, and has a value - * less than or equal to the maximum value specified. - * - * @author Alaa Nassef - */ -public class DecimalMaxValidatorForCharSequence implements ConstraintValidator { - - private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - - private BigDecimal maxValue; - private boolean inclusive; - - @Override - public void initialize(DecimalMax maxValue) { - try { - this.maxValue = new BigDecimal( maxValue.value() ); - } - catch (NumberFormatException nfe) { - throw LOG.getInvalidBigDecimalFormatException( maxValue.value(), nfe ); - } - this.inclusive = maxValue.inclusive(); - } - - @Override - public boolean isValid(CharSequence value, ConstraintValidatorContext constraintValidatorContext) { - //null values are valid - if ( value == null ) { - return true; - } - try { - int comparisonResult = new BigDecimal( value.toString() ).compareTo( maxValue ); - return inclusive ? comparisonResult <= 0 : comparisonResult < 0; - } - catch (NumberFormatException nfe) { - return false; - } - } -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/DecimalMinValidatorForCharSequence.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/DecimalMinValidatorForCharSequence.java deleted file mode 100644 index d8e189ffad..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/DecimalMinValidatorForCharSequence.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.constraintvalidators.bv; - -import java.lang.invoke.MethodHandles; -import java.math.BigDecimal; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; -import javax.validation.constraints.DecimalMin; - -import org.hibernate.validator.internal.util.logging.Log; -import org.hibernate.validator.internal.util.logging.LoggerFactory; - -/** - * Check that the character sequence (e.g. string) being validated represents a number, and has a value - * greater than or equal to the minimum value specified. - * - * @author Hardy Ferentschik - */ -public class DecimalMinValidatorForCharSequence implements ConstraintValidator { - - private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() ); - - private BigDecimal minValue; - private boolean inclusive; - - @Override - public void initialize(DecimalMin minValue) { - try { - this.minValue = new BigDecimal( minValue.value() ); - } - catch (NumberFormatException nfe) { - throw LOG.getInvalidBigDecimalFormatException( minValue.value(), nfe ); - } - this.inclusive = minValue.inclusive(); - } - - @Override - public boolean isValid(CharSequence value, ConstraintValidatorContext constraintValidatorContext) { - //null values are valid - if ( value == null ) { - return true; - } - try { - int comparisonResult = new BigDecimal( value.toString() ).compareTo( minValue ); - return inclusive ? comparisonResult >= 0 : comparisonResult > 0; - } - catch (NumberFormatException nfe) { - return false; - } - } -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/MaxValidatorForCharSequence.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/MaxValidatorForCharSequence.java deleted file mode 100644 index 1ae99601a0..0000000000 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/MaxValidatorForCharSequence.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.internal.constraintvalidators.bv; - -import java.math.BigDecimal; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; -import javax.validation.constraints.Max; - -/** - * Check that the character sequence (e.g. string) validated represents a number, and has a value - * less than or equal to the maximum value specified. - * - * @author Alaa Nassef - * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI - */ -public class MaxValidatorForCharSequence implements ConstraintValidator { - - private BigDecimal maxValue; - - @Override - public void initialize(Max maxValue) { - this.maxValue = BigDecimal.valueOf( maxValue.value() ); - } - - @Override - public boolean isValid(CharSequence value, ConstraintValidatorContext constraintValidatorContext) { - //null values are valid - if ( value == null ) { - return true; - } - try { - return new BigDecimal( value.toString() ).compareTo( maxValue ) != 1; - } - catch (NumberFormatException nfe) { - return false; - } - } -} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForCharSequence.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForCharSequence.java new file mode 100644 index 0000000000..8189e2952f --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MaxValidatorForCharSequence.java @@ -0,0 +1,30 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.bound; + +import java.math.BigDecimal; + +/** + * Check that the character sequence (e.g. string) validated represents a number, and has a value less than or equal to + * the maximum value specified. + * + * @author Alaa Nassef + * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI + * @author Guillaume Smet + */ +public class MaxValidatorForCharSequence extends AbstractMaxValidator { + + @Override + protected int compare(CharSequence number) { + try { + return NumberComparatorHelper.compare( new BigDecimal( number.toString() ), maxValue ); + } + catch (NumberFormatException nfe) { + return 1; + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/MinValidatorForCharSequence.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForCharSequence.java similarity index 50% rename from engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/MinValidatorForCharSequence.java rename to engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForCharSequence.java index eedd1d9732..7488f11bc1 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/MinValidatorForCharSequence.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/MinValidatorForCharSequence.java @@ -4,12 +4,9 @@ * License: Apache License, Version 2.0 * See the license.txt file in the root directory or . */ -package org.hibernate.validator.internal.constraintvalidators.bv; +package org.hibernate.validator.internal.constraintvalidators.bv.number.bound; import java.math.BigDecimal; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; -import javax.validation.constraints.Min; /** * Check that the character sequence (e.g. string) being validated represents a number, and has a value @@ -17,27 +14,17 @@ * * @author Alaa Nassef * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI + * @author Guillaume Smet */ -public class MinValidatorForCharSequence implements ConstraintValidator { - - private BigDecimal minValue; +public class MinValidatorForCharSequence extends AbstractMinValidator { @Override - public void initialize(Min minValue) { - this.minValue = BigDecimal.valueOf( minValue.value() ); - } - - @Override - public boolean isValid(CharSequence value, ConstraintValidatorContext constraintValidatorContext) { - //null values are valid - if ( value == null ) { - return true; - } + protected int compare(CharSequence number) { try { - return new BigDecimal( value.toString() ).compareTo( minValue ) != -1; + return NumberComparatorHelper.compare( new BigDecimal( number.toString() ), minValue ); } catch (NumberFormatException nfe) { - return false; + return -1; } } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForCharSequence.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForCharSequence.java new file mode 100644 index 0000000000..ce4d7a6c8b --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMaxValidatorForCharSequence.java @@ -0,0 +1,29 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal; + +import java.math.BigDecimal; + +/** + * Check that the character sequence (e.g. string) being validated represents a number, and has a value + * less than or equal to the maximum value specified. + * + * @author Alaa Nassef + * @author Guillaume Smet + */ +public class DecimalMaxValidatorForCharSequence extends AbstractDecimalMaxValidator { + + @Override + protected int compare(CharSequence number) { + try { + return DecimalNumberComparatorHelper.compare( new BigDecimal( number.toString() ), maxValue ); + } + catch (NumberFormatException nfe) { + return 1; + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForCharSequence.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForCharSequence.java new file mode 100644 index 0000000000..39f8ac2c2e --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/bound/decimal/DecimalMinValidatorForCharSequence.java @@ -0,0 +1,29 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal; + +import java.math.BigDecimal; + +/** + * Check that the character sequence (e.g. string) being validated represents a number, and has a value greater than or + * equal to the minimum value specified. + * + * @author Hardy Ferentschik + * @author Guillaume Smet + */ +public class DecimalMinValidatorForCharSequence extends AbstractDecimalMinValidator { + + @Override + protected int compare(CharSequence number) { + try { + return DecimalNumberComparatorHelper.compare( new BigDecimal( number.toString() ), minValue ); + } + catch (NumberFormatException nfe) { + return -1; + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java index 82e60f7a1b..5ccafed9d1 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java @@ -130,13 +130,9 @@ import org.hibernate.validator.constraints.time.DurationMin; import org.hibernate.validator.internal.constraintvalidators.bv.AssertFalseValidator; import org.hibernate.validator.internal.constraintvalidators.bv.AssertTrueValidator; -import org.hibernate.validator.internal.constraintvalidators.bv.DecimalMaxValidatorForCharSequence; -import org.hibernate.validator.internal.constraintvalidators.bv.DecimalMinValidatorForCharSequence; import org.hibernate.validator.internal.constraintvalidators.bv.DigitsValidatorForCharSequence; import org.hibernate.validator.internal.constraintvalidators.bv.DigitsValidatorForNumber; import org.hibernate.validator.internal.constraintvalidators.bv.EmailValidator; -import org.hibernate.validator.internal.constraintvalidators.bv.MaxValidatorForCharSequence; -import org.hibernate.validator.internal.constraintvalidators.bv.MinValidatorForCharSequence; import org.hibernate.validator.internal.constraintvalidators.bv.NotBlankValidator; import org.hibernate.validator.internal.constraintvalidators.bv.NotNullValidator; import org.hibernate.validator.internal.constraintvalidators.bv.NullValidator; @@ -166,6 +162,7 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForBigInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForByte; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForCharSequence; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForDouble; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForFloat; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForInteger; @@ -175,6 +172,7 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForBigInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForByte; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForCharSequence; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForDouble; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForFloat; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForInteger; @@ -184,6 +182,7 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForBigInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForByte; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForCharSequence; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForDouble; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForFloat; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForInteger; @@ -193,6 +192,7 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForBigInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForByte; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForCharSequence; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForDouble; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForFloat; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForInteger; diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MaxValidatorForStringTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MaxValidatorForStringTest.java index f81b2edb50..6a24171fae 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MaxValidatorForStringTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MaxValidatorForStringTest.java @@ -14,8 +14,8 @@ import javax.validation.constraints.DecimalMax; import javax.validation.constraints.Max; -import org.hibernate.validator.internal.constraintvalidators.bv.DecimalMaxValidatorForCharSequence; -import org.hibernate.validator.internal.constraintvalidators.bv.MaxValidatorForCharSequence; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MaxValidatorForCharSequence; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForCharSequence; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMaxValidatorForNumber; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.testutil.MyCustomStringImpl; diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MinValidatorForStringTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MinValidatorForStringTest.java index 4701cd58e1..5a06df9e86 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MinValidatorForStringTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/MinValidatorForStringTest.java @@ -14,8 +14,8 @@ import javax.validation.constraints.DecimalMin; import javax.validation.constraints.Min; -import org.hibernate.validator.internal.constraintvalidators.bv.DecimalMinValidatorForCharSequence; -import org.hibernate.validator.internal.constraintvalidators.bv.MinValidatorForCharSequence; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForCharSequence; +import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForCharSequence; import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.decimal.DecimalMinValidatorForNumber; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.testutil.MyCustomStringImpl; From 2ab7c757a42c61ec42f54a2bce5c15a021eaabe8 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 17 Apr 2020 12:55:57 +0200 Subject: [PATCH 326/393] HV-1760 Support CharSequence for Negative/Positive/... It was documented and it's better for consistency with the Min/Max/... constraints. --- ...egativeOrZeroValidatorForCharSequence.java | 36 ++++++ .../NegativeValidatorForCharSequence.java | 36 ++++++ ...ositiveOrZeroValidatorForCharSequence.java | 36 ++++++ .../PositiveValidatorForCharSequence.java | 36 ++++++ .../metadata/core/ConstraintHelper.java | 8 ++ ...egativePositiveValidatorForStringTest.java | 108 ++++++++++++++++++ 6 files changed, 260 insertions(+) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForCharSequence.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeValidatorForCharSequence.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForCharSequence.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveValidatorForCharSequence.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/NegativePositiveValidatorForStringTest.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForCharSequence.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForCharSequence.java new file mode 100644 index 0000000000..e944d3b98d --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForCharSequence.java @@ -0,0 +1,36 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.sign; + +import java.math.BigDecimal; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import javax.validation.constraints.NegativeOrZero; + +/** + * Check that the number being validated is negative. + * + * @author Guillaume Smet + */ +public class NegativeOrZeroValidatorForCharSequence implements ConstraintValidator { + + @Override + public boolean isValid(CharSequence value, ConstraintValidatorContext context) { + // null values are valid + if ( value == null ) { + return true; + } + + try { + return NumberSignHelper.signum( new BigDecimal( value.toString() ) ) <= 0; + } + catch (NumberFormatException nfe) { + return false; + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeValidatorForCharSequence.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeValidatorForCharSequence.java new file mode 100644 index 0000000000..dc8cb5870a --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeValidatorForCharSequence.java @@ -0,0 +1,36 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.sign; + +import java.math.BigDecimal; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import javax.validation.constraints.Negative; + +/** + * Check that the number being validated is negative. + * + * @author Guillaume Smet + */ +public class NegativeValidatorForCharSequence implements ConstraintValidator { + + @Override + public boolean isValid(CharSequence value, ConstraintValidatorContext context) { + // null values are valid + if ( value == null ) { + return true; + } + + try { + return NumberSignHelper.signum( new BigDecimal( value.toString() ) ) < 0; + } + catch (NumberFormatException nfe) { + return false; + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForCharSequence.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForCharSequence.java new file mode 100644 index 0000000000..7b997bc179 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForCharSequence.java @@ -0,0 +1,36 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.sign; + +import java.math.BigDecimal; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import javax.validation.constraints.PositiveOrZero; + +/** + * Check that the number being validated is positive. + * + * @author Guillaume Smet + */ +public class PositiveOrZeroValidatorForCharSequence implements ConstraintValidator { + + @Override + public boolean isValid(CharSequence value, ConstraintValidatorContext context) { + // null values are valid + if ( value == null ) { + return true; + } + + try { + return NumberSignHelper.signum( new BigDecimal( value.toString() ) ) >= 0; + } + catch (NumberFormatException nfe) { + return false; + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveValidatorForCharSequence.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveValidatorForCharSequence.java new file mode 100644 index 0000000000..79a4d14e3b --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveValidatorForCharSequence.java @@ -0,0 +1,36 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.bv.number.sign; + +import java.math.BigDecimal; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import javax.validation.constraints.Positive; + +/** + * Check that the number being validated is positive. + * + * @author Guillaume Smet + */ +public class PositiveValidatorForCharSequence implements ConstraintValidator { + + @Override + public boolean isValid(CharSequence value, ConstraintValidatorContext context) { + // null values are valid + if ( value == null ) { + return true; + } + + try { + return NumberSignHelper.signum( new BigDecimal( value.toString() ) ) > 0; + } + catch (NumberFormatException nfe) { + return false; + } + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java index 5ccafed9d1..63ee0c30c7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java @@ -202,6 +202,7 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeOrZeroValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeOrZeroValidatorForBigInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeOrZeroValidatorForByte; +import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeOrZeroValidatorForCharSequence; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeOrZeroValidatorForDouble; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeOrZeroValidatorForFloat; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeOrZeroValidatorForInteger; @@ -211,6 +212,7 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeValidatorForBigInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeValidatorForByte; +import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeValidatorForCharSequence; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeValidatorForDouble; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeValidatorForFloat; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeValidatorForInteger; @@ -220,6 +222,7 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.PositiveOrZeroValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.PositiveOrZeroValidatorForBigInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.PositiveOrZeroValidatorForByte; +import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.PositiveOrZeroValidatorForCharSequence; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.PositiveOrZeroValidatorForDouble; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.PositiveOrZeroValidatorForFloat; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.PositiveOrZeroValidatorForInteger; @@ -229,6 +232,7 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.PositiveValidatorForBigDecimal; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.PositiveValidatorForBigInteger; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.PositiveValidatorForByte; +import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.PositiveValidatorForCharSequence; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.PositiveValidatorForDouble; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.PositiveValidatorForFloat; import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.PositiveValidatorForInteger; @@ -561,6 +565,7 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { negativeValidators.add( NegativeValidatorForShort.class ); negativeValidators.add( NegativeValidatorForByte.class ); negativeValidators.add( NegativeValidatorForNumber.class ); + negativeValidators.add( NegativeValidatorForCharSequence.class ); if ( isJavaMoneyInClasspath() ) { negativeValidators.add( NegativeValidatorForMonetaryAmount.class ); } @@ -578,6 +583,7 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { negativeOrZeroValidators.add( NegativeOrZeroValidatorForShort.class ); negativeOrZeroValidators.add( NegativeOrZeroValidatorForByte.class ); negativeOrZeroValidators.add( NegativeOrZeroValidatorForNumber.class ); + negativeOrZeroValidators.add( NegativeOrZeroValidatorForCharSequence.class ); if ( isJavaMoneyInClasspath() ) { negativeOrZeroValidators.add( NegativeOrZeroValidatorForMonetaryAmount.class ); } @@ -681,6 +687,7 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { positiveValidators.add( PositiveValidatorForShort.class ); positiveValidators.add( PositiveValidatorForByte.class ); positiveValidators.add( PositiveValidatorForNumber.class ); + positiveValidators.add( PositiveValidatorForCharSequence.class ); if ( isJavaMoneyInClasspath() ) { positiveValidators.add( PositiveValidatorForMonetaryAmount.class ); } @@ -698,6 +705,7 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { positiveOrZeroValidators.add( PositiveOrZeroValidatorForShort.class ); positiveOrZeroValidators.add( PositiveOrZeroValidatorForByte.class ); positiveOrZeroValidators.add( PositiveOrZeroValidatorForNumber.class ); + positiveOrZeroValidators.add( PositiveOrZeroValidatorForCharSequence.class ); if ( isJavaMoneyInClasspath() ) { positiveOrZeroValidators.add( PositiveOrZeroValidatorForMonetaryAmount.class ); } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/NegativePositiveValidatorForStringTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/NegativePositiveValidatorForStringTest.java new file mode 100644 index 0000000000..f702729915 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/NegativePositiveValidatorForStringTest.java @@ -0,0 +1,108 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.constraintvalidators.bv; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import javax.validation.constraints.Negative; +import javax.validation.constraints.NegativeOrZero; +import javax.validation.constraints.Positive; +import javax.validation.constraints.PositiveOrZero; + +import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeOrZeroValidatorForCharSequence; +import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.NegativeValidatorForCharSequence; +import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.PositiveOrZeroValidatorForCharSequence; +import org.hibernate.validator.internal.constraintvalidators.bv.number.sign.PositiveValidatorForCharSequence; +import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; +import org.testng.annotations.Test; + +/** + * @author Guillaume Smet + */ +public class NegativePositiveValidatorForStringTest { + + @Test + public void testIsValidPositiveValidator() { + ConstraintAnnotationDescriptor.Builder descriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( Positive.class ); + descriptorBuilder.setMessage( "{validator.positive}" ); + Positive m = descriptorBuilder.build().getAnnotation(); + + PositiveValidatorForCharSequence constraint = new PositiveValidatorForCharSequence(); + constraint.initialize( m ); + + assertTrue( constraint.isValid( null, null ) ); + assertTrue( constraint.isValid( "15", null ) ); + assertTrue( constraint.isValid( "15.0", null ) ); + assertFalse( constraint.isValid( "0", null ) ); + assertFalse( constraint.isValid( "-10", null ) ); + assertFalse( constraint.isValid( "-14.99", null ) ); + + // number format exception + assertFalse( constraint.isValid( "15l", null ) ); + } + + @Test + public void testIsValidPositiveOrZeroValidator() { + ConstraintAnnotationDescriptor.Builder descriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( PositiveOrZero.class ); + descriptorBuilder.setMessage( "{validator.positiveOrZero}" ); + PositiveOrZero m = descriptorBuilder.build().getAnnotation(); + + PositiveOrZeroValidatorForCharSequence constraint = new PositiveOrZeroValidatorForCharSequence(); + constraint.initialize( m ); + + assertTrue( constraint.isValid( null, null ) ); + assertTrue( constraint.isValid( "15", null ) ); + assertTrue( constraint.isValid( "15.0", null ) ); + assertTrue( constraint.isValid( "0", null ) ); + assertFalse( constraint.isValid( "-10", null ) ); + assertFalse( constraint.isValid( "-14.99", null ) ); + + // number format exception + assertFalse( constraint.isValid( "15l", null ) ); + } + + @Test + public void testIsValidNegativeValidator() { + ConstraintAnnotationDescriptor.Builder descriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( Negative.class ); + descriptorBuilder.setMessage( "{validator.negative}" ); + Negative m = descriptorBuilder.build().getAnnotation(); + + NegativeValidatorForCharSequence constraint = new NegativeValidatorForCharSequence(); + constraint.initialize( m ); + + assertTrue( constraint.isValid( null, null ) ); + assertFalse( constraint.isValid( "15", null ) ); + assertFalse( constraint.isValid( "15.0", null ) ); + assertFalse( constraint.isValid( "0", null ) ); + assertTrue( constraint.isValid( "-10", null ) ); + assertTrue( constraint.isValid( "-14.99", null ) ); + + // number format exception + assertFalse( constraint.isValid( "15l", null ) ); + } + + @Test + public void testIsValidNegativeOrZeroValidator() { + ConstraintAnnotationDescriptor.Builder descriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( NegativeOrZero.class ); + descriptorBuilder.setMessage( "{validator.negativeOrZero}" ); + NegativeOrZero m = descriptorBuilder.build().getAnnotation(); + + NegativeOrZeroValidatorForCharSequence constraint = new NegativeOrZeroValidatorForCharSequence(); + constraint.initialize( m ); + + assertTrue( constraint.isValid( null, null ) ); + assertFalse( constraint.isValid( "15", null ) ); + assertFalse( constraint.isValid( "15.0", null ) ); + assertTrue( constraint.isValid( "0", null ) ); + assertTrue( constraint.isValid( "-10", null ) ); + assertTrue( constraint.isValid( "-14.99", null ) ); + + // number format exception + assertFalse( constraint.isValid( "15l", null ) ); + } +} From 66abd3efb54bf1701429c3ec0f61031ce12c54ad Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 17 Apr 2020 12:58:21 +0200 Subject: [PATCH 327/393] HV-1760 Fix javadoc for *OrZero validators --- .../bv/number/sign/NegativeOrZeroValidatorForBigDecimal.java | 2 +- .../bv/number/sign/NegativeOrZeroValidatorForBigInteger.java | 2 +- .../bv/number/sign/NegativeOrZeroValidatorForByte.java | 2 +- .../bv/number/sign/NegativeOrZeroValidatorForCharSequence.java | 2 +- .../bv/number/sign/NegativeOrZeroValidatorForDouble.java | 2 +- .../bv/number/sign/NegativeOrZeroValidatorForFloat.java | 2 +- .../bv/number/sign/NegativeOrZeroValidatorForInteger.java | 2 +- .../bv/number/sign/NegativeOrZeroValidatorForLong.java | 2 +- .../bv/number/sign/NegativeOrZeroValidatorForNumber.java | 2 +- .../bv/number/sign/NegativeOrZeroValidatorForShort.java | 2 +- .../bv/number/sign/PositiveOrZeroValidatorForBigDecimal.java | 2 +- .../bv/number/sign/PositiveOrZeroValidatorForBigInteger.java | 2 +- .../bv/number/sign/PositiveOrZeroValidatorForByte.java | 2 +- .../bv/number/sign/PositiveOrZeroValidatorForCharSequence.java | 2 +- .../bv/number/sign/PositiveOrZeroValidatorForDouble.java | 2 +- .../bv/number/sign/PositiveOrZeroValidatorForFloat.java | 2 +- .../bv/number/sign/PositiveOrZeroValidatorForInteger.java | 2 +- .../bv/number/sign/PositiveOrZeroValidatorForLong.java | 2 +- .../bv/number/sign/PositiveOrZeroValidatorForNumber.java | 2 +- .../bv/number/sign/PositiveOrZeroValidatorForShort.java | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForBigDecimal.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForBigDecimal.java index 9f2168b1f4..1ace30b394 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForBigDecimal.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForBigDecimal.java @@ -13,7 +13,7 @@ import javax.validation.constraints.NegativeOrZero; /** - * Check that the number being validated is negative. + * Check that the number being validated is negative or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForBigInteger.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForBigInteger.java index 6889543afb..f763ff3e66 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForBigInteger.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForBigInteger.java @@ -13,7 +13,7 @@ import javax.validation.constraints.NegativeOrZero; /** - * Check that the number being validated is negative. + * Check that the number being validated is negative or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForByte.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForByte.java index e657259334..111a7c2804 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForByte.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForByte.java @@ -11,7 +11,7 @@ import javax.validation.constraints.NegativeOrZero; /** - * Check that the number being validated is negative. + * Check that the number being validated is negative or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForCharSequence.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForCharSequence.java index e944d3b98d..6b267381cf 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForCharSequence.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForCharSequence.java @@ -13,7 +13,7 @@ import javax.validation.constraints.NegativeOrZero; /** - * Check that the number being validated is negative. + * Check that the number being validated is negative or zero. * * @author Guillaume Smet */ diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForDouble.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForDouble.java index 33efd6e6d4..a132f8c711 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForDouble.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForDouble.java @@ -13,7 +13,7 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.InfinityNumberComparatorHelper; /** - * Check that the number being validated is negative. + * Check that the number being validated is negative or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForFloat.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForFloat.java index aaf6bc5d97..c7f502ad14 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForFloat.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForFloat.java @@ -13,7 +13,7 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.InfinityNumberComparatorHelper; /** - * Check that the number being validated is negative. + * Check that the number being validated is negative or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForInteger.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForInteger.java index 9be390fbb8..276b4a6036 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForInteger.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForInteger.java @@ -11,7 +11,7 @@ import javax.validation.constraints.NegativeOrZero; /** - * Check that the number being validated is negative. + * Check that the number being validated is negative or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForLong.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForLong.java index 3a711dfd58..2e23439730 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForLong.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForLong.java @@ -11,7 +11,7 @@ import javax.validation.constraints.NegativeOrZero; /** - * Check that the number being validated is negative. + * Check that the number being validated is negative or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForNumber.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForNumber.java index 2ce970c610..d8fc77b87b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForNumber.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForNumber.java @@ -11,7 +11,7 @@ import javax.validation.constraints.NegativeOrZero; /** - * Check that the number being validated is negative. + * Check that the number being validated is negative or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForShort.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForShort.java index 856b05743a..412f675b0e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForShort.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/NegativeOrZeroValidatorForShort.java @@ -11,7 +11,7 @@ import javax.validation.constraints.NegativeOrZero; /** - * Check that the number being validated is negative. + * Check that the number being validated is negative or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForBigDecimal.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForBigDecimal.java index ed96ba917b..9183f23395 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForBigDecimal.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForBigDecimal.java @@ -13,7 +13,7 @@ import javax.validation.constraints.PositiveOrZero; /** - * Check that the number being validated is positive. + * Check that the number being validated is positive or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForBigInteger.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForBigInteger.java index e0172f1adf..aa30292cf0 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForBigInteger.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForBigInteger.java @@ -13,7 +13,7 @@ import javax.validation.constraints.PositiveOrZero; /** - * Check that the number being validated is positive. + * Check that the number being validated is positive or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForByte.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForByte.java index d4b3e09e11..f3ec5557ac 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForByte.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForByte.java @@ -11,7 +11,7 @@ import javax.validation.constraints.PositiveOrZero; /** - * Check that the number being validated is positive. + * Check that the number being validated is positive or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForCharSequence.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForCharSequence.java index 7b997bc179..cacb3a98c9 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForCharSequence.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForCharSequence.java @@ -13,7 +13,7 @@ import javax.validation.constraints.PositiveOrZero; /** - * Check that the number being validated is positive. + * Check that the number being validated is positive or zero. * * @author Guillaume Smet */ diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForDouble.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForDouble.java index a70f15183c..0dbff5295e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForDouble.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForDouble.java @@ -13,7 +13,7 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.InfinityNumberComparatorHelper; /** - * Check that the number being validated is positive. + * Check that the number being validated is positive or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForFloat.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForFloat.java index 1255893b80..38a91ae294 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForFloat.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForFloat.java @@ -13,7 +13,7 @@ import org.hibernate.validator.internal.constraintvalidators.bv.number.InfinityNumberComparatorHelper; /** - * Check that the number being validated is positive. + * Check that the number being validated is positive or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForInteger.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForInteger.java index 56caf73f49..ba6fae0564 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForInteger.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForInteger.java @@ -11,7 +11,7 @@ import javax.validation.constraints.PositiveOrZero; /** - * Check that the number being validated positive. + * Check that the number being validated positive or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForLong.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForLong.java index 1b2861b447..e6bbdcc9bc 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForLong.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForLong.java @@ -11,7 +11,7 @@ import javax.validation.constraints.PositiveOrZero; /** - * Check that the number being validated positive. + * Check that the number being validated positive or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForNumber.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForNumber.java index 2278085cda..7ed717bc78 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForNumber.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForNumber.java @@ -11,7 +11,7 @@ import javax.validation.constraints.PositiveOrZero; /** - * Check that the number being validated is positive. + * Check that the number being validated is positive or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForShort.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForShort.java index 6f6f480215..eaaeab1c57 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForShort.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/number/sign/PositiveOrZeroValidatorForShort.java @@ -11,7 +11,7 @@ import javax.validation.constraints.PositiveOrZero; /** - * Check that the number being validated is positive. + * Check that the number being validated is positive or zero. * * @author Hardy Ferentschik * @author Xavier Sosnovsky From cc2b3587f2e6f4c0c5c91c1ae76f95d2e22ce001 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 17 Apr 2020 12:02:16 +0000 Subject: [PATCH 328/393] [Jenkins release job] README.md updated by release build 6.1.4.Final --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f779246c41..1bd8ec9ba1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hibernate Validator -*Version: 6.1.3.Final - 10-04-2020* +*Version: 6.1.4.Final - 17-04-2020* ## What is it? @@ -35,7 +35,7 @@ Logging will delegate any log requests to that provider. org.hibernate.validator hibernate-validator - 6.1.3.Final + 6.1.4.Final You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. @@ -54,7 +54,7 @@ extension by adding the following dependency: org.hibernate.validator hibernate-validator-cdi - 6.1.3.Final + 6.1.4.Final * _hibernate-validator-annotation-processor-<version>.jar_ is an optional jar which can be integrated with your build From 15a57c6ec9acf5ae502e28cfcb1db4131af0bb02 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 17 Apr 2020 12:02:16 +0000 Subject: [PATCH 329/393] [Jenkins release job] changelog.txt updated by release build 6.1.4.Final --- changelog.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/changelog.txt b/changelog.txt index ca5e7e0070..fdc1352da8 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,17 @@ Hibernate Validator Changelog ============================= +6.1.4.Final (17-04-2020) +------------------------- + +** Bug + * HV-1760 - validators - @Negative*/@Positive* do not support CharSequence as documented + +** Improvement + * HV-1770 - engine - Relax constraint consistency checking for built-in constraints + * HV-1769 - engine - Only create the default TraversableResolver if none has been specified + * HV-1767 - engine - Reduce the overhead of ConstraintHelper initialization in the predefined scope case + 6.1.3.Final (10-04-2020) ------------------------- From de380ed57329842ffd613637e3cfc76026bcadb9 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 17 Apr 2020 12:02:23 +0000 Subject: [PATCH 330/393] [Jenkins release job] Preparing release 6.1.4.Final --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 59c19db310..65a5b9207f 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4-SNAPSHOT + 6.1.4.Final ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index b4dd834c9f..d3e4a91eaf 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4-SNAPSHOT + 6.1.4.Final ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index 4deda9adc1..f70c8707cb 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4-SNAPSHOT + 6.1.4.Final ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index 10f2fac979..90ca91a43e 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4-SNAPSHOT + 6.1.4.Final ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index b7d925afb4..03f69df4d1 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4-SNAPSHOT + 6.1.4.Final ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index f68f0ecde1..763079eabc 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4-SNAPSHOT + 6.1.4.Final ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 37bc261fdd..7edefc0d96 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4-SNAPSHOT + 6.1.4.Final ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index f6b0817a02..5a5c985fae 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4-SNAPSHOT + 6.1.4.Final 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 7d627d5dbd..08cb59ffda 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.4-SNAPSHOT + 6.1.4.Final ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index a7dc8e5d0f..895820b919 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.4-SNAPSHOT + 6.1.4.Final ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 9e5867237d..883ca01b0c 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.4-SNAPSHOT + 6.1.4.Final ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index 9c6b9294c3..b9ae057e60 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4-SNAPSHOT + 6.1.4.Final ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index a79626ba2b..03a2607c25 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4-SNAPSHOT + 6.1.4.Final ../pom.xml diff --git a/pom.xml b/pom.xml index 2e47778273..261e0f7b20 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4-SNAPSHOT + 6.1.4.Final pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 33822787af..81ae577182 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.4-SNAPSHOT + 6.1.4.Final org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index 6054919232..3108f8b4be 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.4-SNAPSHOT + 6.1.4.Final org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index 297bf58af5..9eefaadcfc 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.4-SNAPSHOT + 6.1.4.Final org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index 9dddc1ac27..81edbffcbb 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.4-SNAPSHOT + 6.1.4.Final org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index a14f5a2dbe..9822b08db0 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4-SNAPSHOT + 6.1.4.Final hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 447ae37af8..51cfea30bb 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4-SNAPSHOT + 6.1.4.Final ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 330474de80..20e24790f1 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4-SNAPSHOT + 6.1.4.Final hibernate-validator-test-utils From 86bd5ad89e1a8492d8b411e0f303071178aa21f9 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 17 Apr 2020 12:05:27 +0000 Subject: [PATCH 331/393] [Jenkins release job] Preparing next development iteration --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 65a5b9207f..d804576379 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4.Final + 6.1.5-SNAPSHOT ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index d3e4a91eaf..7c66196603 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4.Final + 6.1.5-SNAPSHOT ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index f70c8707cb..bc31053f8a 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4.Final + 6.1.5-SNAPSHOT ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index 90ca91a43e..e0513b7778 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4.Final + 6.1.5-SNAPSHOT ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 03f69df4d1..9d9c31632e 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4.Final + 6.1.5-SNAPSHOT ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index 763079eabc..e4b6a38370 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4.Final + 6.1.5-SNAPSHOT ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 7edefc0d96..c6886f1296 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4.Final + 6.1.5-SNAPSHOT ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index 5a5c985fae..b680be6572 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4.Final + 6.1.5-SNAPSHOT 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 08cb59ffda..ef7dc36597 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.4.Final + 6.1.5-SNAPSHOT ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 895820b919..65de4d6167 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.4.Final + 6.1.5-SNAPSHOT ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 883ca01b0c..7543e37360 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.4.Final + 6.1.5-SNAPSHOT ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index b9ae057e60..627442801a 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4.Final + 6.1.5-SNAPSHOT ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index 03a2607c25..b6759ae664 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4.Final + 6.1.5-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 261e0f7b20..3e31ca35f5 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4.Final + 6.1.5-SNAPSHOT pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 81ae577182..f27fed2e0a 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.4.Final + 6.1.5-SNAPSHOT org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index 3108f8b4be..6e61b9f092 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.4.Final + 6.1.5-SNAPSHOT org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index 9eefaadcfc..0d249ce3c5 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.4.Final + 6.1.5-SNAPSHOT org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index 81edbffcbb..343e9c7ccf 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.4.Final + 6.1.5-SNAPSHOT org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 9822b08db0..d5274f8f13 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4.Final + 6.1.5-SNAPSHOT hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 51cfea30bb..34a82fe6dd 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4.Final + 6.1.5-SNAPSHOT ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 20e24790f1..da68267f7c 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.4.Final + 6.1.5-SNAPSHOT hibernate-validator-test-utils From 59666863d8398057859a8e44479489ddcec76a40 Mon Sep 17 00:00:00 2001 From: Sven Brand <47313047+Br4ndysv3n@users.noreply.github.com> Date: Mon, 27 Apr 2020 17:43:34 +0200 Subject: [PATCH 332/393] HV-1771 Fix DecimalMin message German translation --- .../org/hibernate/validator/ValidationMessages_de.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties index 079d45b168..f375f24174 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties @@ -1,7 +1,7 @@ javax.validation.constraints.AssertFalse.message = muss falsch sein javax.validation.constraints.AssertTrue.message = muss wahr sein javax.validation.constraints.DecimalMax.message = muss kleiner ${inclusive == true ? 'oder gleich ' : ''}{value} sein -javax.validation.constraints.DecimalMin.message = muss gr\u00f6\u00dfer ${inclusive == true ? 'oder gleich sein ' : ''}{value} +javax.validation.constraints.DecimalMin.message = muss gr\u00f6\u00dfer ${inclusive == true ? 'oder gleich ' : ''}{value} sein javax.validation.constraints.Digits.message = numerischer Wert au\u00dferhalb des g\u00fcltigen Bereichs (<{integer} digits>.<{fraction} digits> erwartet) javax.validation.constraints.Email.message = muss eine korrekt formatierte E-Mail-Adresse sein javax.validation.constraints.Future.message = muss ein Datum in der Zukunft sein From c0677678bac286b55989743763c01f66476edfed Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 29 Apr 2020 16:00:32 +0200 Subject: [PATCH 333/393] HV-1772 Allow overriding MessageInterpolator when config is reused --- .../engine/AbstractConfigurationImpl.java | 17 +++--- ...figurationReuseHibernateValidatorTest.java | 59 +++++++++++++++++++ 2 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/bootstrap/ConfigurationReuseHibernateValidatorTest.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java index 702effaf6b..04b093db81 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java @@ -409,6 +409,9 @@ public T externalClassLoader(ClassLoader externalClassLoader) { Contracts.assertNotNull( externalClassLoader, MESSAGES.parameterMustNotBeNull( "externalClassLoader" ) ); this.externalClassLoader = externalClassLoader; + // we need to reset the messageInterpolator field as it might vary depending on the class loader + this.messageInterpolator = null; + return thisAsT(); } @@ -468,15 +471,13 @@ public final boolean isIgnoreXmlConfiguration() { @Override public final MessageInterpolator getMessageInterpolator() { + // apply explicitly given MI, otherwise use default one + MessageInterpolator selectedInterpolator = validationBootstrapParameters.getMessageInterpolator(); + if ( selectedInterpolator != null ) { + return selectedInterpolator; + } if ( messageInterpolator == null ) { - // apply explicitly given MI, otherwise use default one - MessageInterpolator interpolator = validationBootstrapParameters.getMessageInterpolator(); - if ( interpolator != null ) { - messageInterpolator = interpolator; - } - else { - messageInterpolator = getDefaultMessageInterpolatorConfiguredWithClassLoader(); - } + messageInterpolator = getDefaultMessageInterpolatorConfiguredWithClassLoader(); } return messageInterpolator; diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/bootstrap/ConfigurationReuseHibernateValidatorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/bootstrap/ConfigurationReuseHibernateValidatorTest.java new file mode 100644 index 0000000000..16b9b4ca2d --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/bootstrap/ConfigurationReuseHibernateValidatorTest.java @@ -0,0 +1,59 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.bootstrap; + +import static org.testng.Assert.assertSame; + +import java.util.Locale; + +import javax.validation.Configuration; +import javax.validation.MessageInterpolator; +import javax.validation.Validation; +import javax.validation.ValidatorFactory; + +import org.testng.annotations.Test; + +/** + * @author Steven Walters + * @author Guillaume Smet + */ +public class ConfigurationReuseHibernateValidatorTest { + + public static class MessageInterpolatorImpl implements MessageInterpolator { + + private final String prefix; + + public MessageInterpolatorImpl(String prefix) { + this.prefix = prefix; + } + + @Override + public String interpolate(String messageTemplate, Context context) { + return prefix + ": " + messageTemplate; + } + + @Override + public String interpolate(String messageTemplate, Context context, Locale locale) { + return prefix + ": " + messageTemplate + locale.toLanguageTag(); + } + + public String toString() { + return getClass().getSimpleName() + prefix; + } + } + + @Test + public void testMessageInterpolatorChange() { + Configuration config = Validation.byDefaultProvider().configure(); + MessageInterpolator interpolator1 = new MessageInterpolatorImpl( "One" ); + MessageInterpolator interpolator2 = new MessageInterpolatorImpl( "Two" ); + ValidatorFactory factory1 = config.messageInterpolator( interpolator1 ).buildValidatorFactory(); + ValidatorFactory factory2 = config.messageInterpolator( interpolator2 ).buildValidatorFactory(); + assertSame( factory1.getMessageInterpolator(), interpolator1 ); + assertSame( factory2.getMessageInterpolator(), interpolator2 ); + } +} From c1b392f750fc1049eb38410a85be516ef225071e Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 30 Apr 2020 16:17:10 +0200 Subject: [PATCH 334/393] HV-1773 Be more explicit about issues with EL injection and how to avoid them --- documentation/src/main/asciidoc/ch06.asciidoc | 30 ++++++++++---- .../chapter06/elinjection/SafeValidator.java | 39 +++++++++++++++++++ .../elinjection/UnsafeValidator.java | 35 +++++++++++++++++ 3 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 documentation/src/test/java/org/hibernate/validator/referenceguide/chapter06/elinjection/SafeValidator.java create mode 100644 documentation/src/test/java/org/hibernate/validator/referenceguide/chapter06/elinjection/UnsafeValidator.java diff --git a/documentation/src/main/asciidoc/ch06.asciidoc b/documentation/src/main/asciidoc/ch06.asciidoc index a3ca32e39a..23adc09e16 100644 --- a/documentation/src/main/asciidoc/ch06.asciidoc +++ b/documentation/src/main/asciidoc/ch06.asciidoc @@ -173,18 +173,34 @@ It is important to add each configured constraint violation by calling `addConst Only after that the new constraint violation will be created. ==== -[WARNING] +[[el-injection-caution]] +[CAUTION] ==== -Note that the custom message template is passed directly to the Expression Language engine. +**Be aware that the custom message template is passed directly to the Expression Language engine.** Thus, you should be very careful when integrating user input in a custom message template as it will be interpreted -by the Expression Language engine, which is usually not the behavior you expect and could allow malicious users to leak -sensitive data. +by the Expression Language engine, which is usually not the behavior you want and **could allow malicious users to leak +sensitive data or even execute arbitrary code**. + +If you need to integrate user input in your message, you must <> +by unwrapping the context to `HibernateConstraintValidatorContext`. + +The following validator is very unsafe as it includes user input in the violation message. +If the validated `value` contains EL expressions, they will be executed by the EL engine. + +[source, JAVA, indent=0] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter06/elinjection/UnsafeValidator.java[tags=include] +---- + +The following pattern must be used instead: -If you need to integrate user input, you should: +[source] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter06/elinjection/SafeValidator.java[tags=include] +---- - * either escape it by using the http://beanvalidation.org/2.0/spec/#validationapi-message-defaultmessageinterpolation[Jakarta Bean Validation message interpolation escaping rules]; - * or, even better, <> by unwrapping the context to `HibernateConstraintValidatorContext`. +By using expression variables, Hibernate Validator properly handles escaping and EL expressions won't be executed. ==== Refer to <> to learn how to use the `ConstraintValidatorContext` API to diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter06/elinjection/SafeValidator.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter06/elinjection/SafeValidator.java new file mode 100644 index 0000000000..182ab328da --- /dev/null +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter06/elinjection/SafeValidator.java @@ -0,0 +1,39 @@ +package org.hibernate.validator.referenceguide.chapter06.elinjection; + +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorContext; +import org.hibernate.validator.referenceguide.chapter06.constraintvalidatorpayload.ZipCode; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +//tag::include[] +public class SafeValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + if ( value == null ) { + return true; + } + + HibernateConstraintValidatorContext hibernateContext = context.unwrap( + HibernateConstraintValidatorContext.class ); + hibernateContext.disableDefaultConstraintViolation(); + + if ( isInvalid( value ) ) { + hibernateContext + .addExpressionVariable( "validatedValue", value ) + .buildConstraintViolationWithTemplate( "${validatedValue} is not a valid ZIP code" ) + .addConstraintViolation(); + + return false; + } + + return true; + } + + private boolean isInvalid(String value) { + // ... + return false; + } +} +// end::include[] diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter06/elinjection/UnsafeValidator.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter06/elinjection/UnsafeValidator.java new file mode 100644 index 0000000000..6adf4632a1 --- /dev/null +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter06/elinjection/UnsafeValidator.java @@ -0,0 +1,35 @@ +package org.hibernate.validator.referenceguide.chapter06.elinjection; + +import org.hibernate.validator.referenceguide.chapter06.constraintvalidatorpayload.ZipCode; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +//tag::include[] +public class UnsafeValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + if ( value == null ) { + return true; + } + + context.disableDefaultConstraintViolation(); + + if ( isInvalid( value ) ) { + context + .buildConstraintViolationWithTemplate( value + " is not a valid ZIP code" ) + .addConstraintViolation(); + + return false; + } + + return true; + } + + private boolean isInvalid(String value) { + // ... + return false; + } +} +// end::include[] From 438a0fc9bd7e30b4de2b5ba5a96e7f070e3d88e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Mon, 24 Feb 2020 17:23:37 +0100 Subject: [PATCH 335/393] HV-1774 Test arbitrary code injection through buildConstraintViolationWithTemplate() --- .../ConstraintValidatorContextTest.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextTest.java b/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextTest.java index 141b9aa4e3..85a311e30f 100644 --- a/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextTest.java @@ -208,6 +208,20 @@ public void testAddParameterNodeForFieldLevelConstraintCausesException() throws } } + @Test + public void testInjectionCausedByRecklessConcatenation() { + String maliciousPayload = "$\\A{1 + 1}"; + + // Simulate user entry, through a web form for example + MyObjectWithELInjectionRiskCausedByRecklessConcatenation object = new MyObjectWithELInjectionRiskCausedByRecklessConcatenation(); + object.field1 = maliciousPayload; + Set> constraintViolations = validator.validate( object ); + assertThat( constraintViolations ).containsOnlyViolations( + violationOf( ValidationWithELInjectionRiskCausedByRecklessConcatenation.class ) + .withMessage( "Value '" + maliciousPayload + "' is invalid" ) + ); + } + @MyClassLevelValidation private static class MyObject { @NotNull @@ -278,6 +292,13 @@ public String getName() { } } + @ValidationWithELInjectionRiskCausedByRecklessConcatenation + private static class MyObjectWithELInjectionRiskCausedByRecklessConcatenation { + + String field1; + + } + @Retention(RUNTIME) @Constraint(validatedBy = MyClassLevelValidation.Validator.class) public @interface MyClassLevelValidation { @@ -486,4 +507,34 @@ public boolean isValid(String value, ConstraintValidatorContext context) { } } } + + @Retention(RUNTIME) + @Constraint(validatedBy = ValidationWithELInjectionRiskCausedByRecklessConcatenation.Validator.class) + public @interface ValidationWithELInjectionRiskCausedByRecklessConcatenation { + String message() default "failed"; + + Class[] groups() default { }; + + Class[] payload() default { }; + + class Validator + implements ConstraintValidator { + + @Override + public boolean isValid(MyObjectWithELInjectionRiskCausedByRecklessConcatenation value, ConstraintValidatorContext context) { + context.disableDefaultConstraintViolation(); + + // This is bad practice: message parameters should be used instead. + // Regardless, it can happen and should work as well as possible. + context.buildConstraintViolationWithTemplate( "Value '" + escape( value.field1 ) + "' is invalid" ) + .addConstraintViolation(); + + return false; + } + + private String escape(String value) { + return value.replaceAll( "\\$+\\{", "{" ); + } + } + } } From 6ae28a1bc8f7ccb208fa004bdb7c6da569be8a59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Mon, 24 Feb 2020 17:58:41 +0100 Subject: [PATCH 336/393] HV-1774 Do not interpret '$\A{1+1}' in message templates --- .../messageinterpolation/parser/ELState.java | 6 +++++- .../TokenCollectorTest.java | 21 ++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java index 9460fae057..fda95a153c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java @@ -56,7 +56,11 @@ public void handleEndTerm(char character, TokenCollector tokenCollector) throws @Override public void handleEscapeCharacter(char character, TokenCollector tokenCollector) throws MessageDescriptorFormatException { - tokenCollector.transitionState( new EscapedState( this ) ); + tokenCollector.appendToToken( EL_DESIGNATOR ); + tokenCollector.appendToToken( character ); + // Do not go back to this state after the escape: $\ is not the start of an EL expression + ParserState stateAfterEscape = new MessageState(); + tokenCollector.transitionState( new EscapedState( stateAfterEscape ) ); } @Override diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorTest.java index 972a9e0513..ab9299f17a 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorTest.java @@ -8,7 +8,11 @@ import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTermType; import org.hibernate.validator.internal.engine.messageinterpolation.parser.MessageDescriptorFormatException; +import org.hibernate.validator.internal.engine.messageinterpolation.parser.Token; import org.hibernate.validator.internal.engine.messageinterpolation.parser.TokenCollector; + +import org.assertj.core.api.Assertions; +import org.assertj.core.api.ListAssert; import org.testng.annotations.Test; /** @@ -29,10 +33,25 @@ public void testParameterWithoutOpeningBraceThrowsException() throws Exception { } @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*") - public void testELExpressionWithoutOpeningBraceThrowsException() throws Exception { + public void testELExpressionDollarThenClosingBraceThrowsException() throws Exception { new TokenCollector( "$}", InterpolationTermType.EL ); } + @Test + public void testELExpressionDollarThenEscapeInterpretedAsLiterals() { + ListAssert assertion = Assertions.assertThat( + new TokenCollector( "$\\A{1+1}", InterpolationTermType.EL ) + .getTokenList() + ) + .hasSize( 2 ); + assertion.element( 0 ) + .returns( "$\\A", Token::getTokenValue ) + .returns( false, Token::isParameter ); + assertion.element( 1 ) + .returns( "{1+1}", Token::getTokenValue ) + .returns( false, Token::isParameter ); + } + @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*") public void testTermWithoutClosingBraceThrowsException() throws Exception { new TokenCollector( "{foo", InterpolationTermType.PARAMETER ); From d3b39a74bdc18ea6b112b1e9e6a8f77550066381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 25 Feb 2020 15:17:03 +0100 Subject: [PATCH 337/393] HV-1774 Add a few tests to demonstrate the behavior of TokenCollector --- .../AbstractTokenCollectorTest.java | 186 ++++++++++++++++++ .../TokenCollectorMessageExpressionTest.java | 110 +++++++++++ .../TokenCollectorMessageParameterTest.java | 115 +++++++++++ .../TokenCollectorTest.java | 64 ------ 4 files changed, 411 insertions(+), 64 deletions(-) create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/AbstractTokenCollectorTest.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorMessageExpressionTest.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorMessageParameterTest.java delete mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorTest.java diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/AbstractTokenCollectorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/AbstractTokenCollectorTest.java new file mode 100644 index 0000000000..004d5c9bd2 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/AbstractTokenCollectorTest.java @@ -0,0 +1,186 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.engine.messageinterpolation; + +import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTermType; +import org.hibernate.validator.internal.engine.messageinterpolation.parser.MessageDescriptorFormatException; +import org.hibernate.validator.internal.engine.messageinterpolation.parser.Token; +import org.hibernate.validator.internal.engine.messageinterpolation.parser.TokenCollector; + +import org.assertj.core.api.Assertions; +import org.testng.annotations.Test; + +/** + * Abstract base for {@code TokenCollector} tests. + * + * @author Hardy Ferentschik + */ +public abstract class AbstractTokenCollectorTest { + + protected abstract InterpolationTermType getInterpolationTermType(); + + @Test + public void testLiteral() { + Assertions.assertThat( + new TokenCollector( "foo bar", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 1 ) + .element( 0 ) + .returns( "foo bar", Token::getTokenValue ) + .returns( false, Token::isParameter ); + } + + @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000169.*") + public void testNestedParametersThrowException() { + new TokenCollector( "#{foo {}", getInterpolationTermType() ); + } + + @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*") + public void testClosingBraceWithoutOpeningBraceThrowsException() { + new TokenCollector( "foo}", getInterpolationTermType() ); + } + + @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*") + public void testOpeningBraceWithoutClosingBraceThrowsException() { + new TokenCollector( "{foo", getInterpolationTermType() ); + } + + @Test + public void testBackslashEscapesNonMetaCharacter() { + Assertions.assertThat( + new TokenCollector( "foo \\bar", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 1 ) + .element( 0 ) + // Backslashes are removed later, in AbstractMessageInterpolator.replaceEscapedLiterals + .returns( "foo \\bar", Token::getTokenValue ) + .returns( false, Token::isParameter ); + } + + @Test + public void testBackslashEscapesDollar() { + Assertions.assertThat( + new TokenCollector( "foo \\$ bar", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 1 ) + .element( 0 ) + // Backslashes are removed later, in AbstractMessageInterpolator.replaceEscapedLiterals + .returns( "foo \\$ bar", Token::getTokenValue ) + .returns( false, Token::isParameter ); + } + + @Test + public void testBackslashEscapesOpeningBrace() { + Assertions.assertThat( + new TokenCollector( "foo \\{ bar", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 1 ) + .element( 0 ) + // Backslashes are removed later, in AbstractMessageInterpolator.replaceEscapedLiterals + .returns( "foo \\{ bar", Token::getTokenValue ) + .returns( false, Token::isParameter ); + } + + @Test + public void testBackslashEscapesClosingBrace() { + Assertions.assertThat( + new TokenCollector( "foo \\} bar", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 1 ) + .element( 0 ) + // Backslashes are removed later, in AbstractMessageInterpolator.replaceEscapedLiterals + .returns( "foo \\} bar", Token::getTokenValue ) + .returns( false, Token::isParameter ); + } + + @Test + public void testBackslashEscapesBackslash() { + Assertions.assertThat( + new TokenCollector( "foo \\\\ bar", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 1 ) + .element( 0 ) + // Backslashes are removed later, in AbstractMessageInterpolator.replaceEscapedLiterals + .returns( "foo \\\\ bar", Token::getTokenValue ) + .returns( false, Token::isParameter ); + } + + @Test + public void testBackslashEscapesEL() { + Assertions.assertThat( + new TokenCollector( "foo \\$\\{bar\\}", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 1 ) + .element( 0 ) + // Backslashes are removed later, in AbstractMessageInterpolator.replaceEscapedLiterals + .returns( "foo \\$\\{bar\\}", Token::getTokenValue ) + // What's important is that we did NOT detect the expression + .returns( false, Token::isParameter ); + } + + @Test + public void testBackslashEscapesParameter() { + Assertions.assertThat( + new TokenCollector( "foo \\{bar\\}", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 1 ) + .element( 0 ) + // Backslashes are removed later, in AbstractMessageInterpolator.replaceEscapedLiterals + .returns( "foo \\{bar\\}", Token::getTokenValue ) + // What's important is that we did NOT detect the parameter + .returns( false, Token::isParameter ); + } + + @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*") + public void testTrailingClosingBraceThrowsException() { + new TokenCollector( "this message contains a invalid parameter start token {", getInterpolationTermType() ); + } + + @Test + public void testDollarThenNonMetaCharacterInterpretedAsLiteral() { + Assertions.assertThat( + new TokenCollector( "$a", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 1 ) + .element( 0 ) + .returns( "$a", Token::getTokenValue ) + .returns( false, Token::isParameter ); + } + + @Test + public void testTrailingDollarInterpretedAsLiteral() { + Assertions.assertThat( + new TokenCollector( "foo $", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 1 ) + .element( 0 ) + .returns( "foo $", Token::getTokenValue ) + .returns( false, Token::isParameter ); + } + + @Test + public void testTrailingBackslashInterpretedAsLiteral() { + Assertions.assertThat( + new TokenCollector( "foo \\", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 1 ) + .element( 0 ) + .returns( "foo \\", Token::getTokenValue ) + .returns( false, Token::isParameter ); + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorMessageExpressionTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorMessageExpressionTest.java new file mode 100644 index 0000000000..229e34174e --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorMessageExpressionTest.java @@ -0,0 +1,110 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.engine.messageinterpolation; + +import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTermType; +import org.hibernate.validator.internal.engine.messageinterpolation.parser.MessageDescriptorFormatException; +import org.hibernate.validator.internal.engine.messageinterpolation.parser.Token; +import org.hibernate.validator.internal.engine.messageinterpolation.parser.TokenCollector; + +import org.assertj.core.api.Assertions; +import org.assertj.core.api.ListAssert; +import org.testng.annotations.Test; + +/** + * Tests for {@code TokenCollector} in message expression mode. + * + * @author Hardy Ferentschik + */ +public class TokenCollectorMessageExpressionTest extends AbstractTokenCollectorTest { + @Override + protected InterpolationTermType getInterpolationTermType() { + return InterpolationTermType.EL; + } + + // Several tests inherited from the abstract class + + @Test + public void testMessageParameter() { + ListAssert assertion = Assertions.assertThat( + new TokenCollector( "foo {bar}", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 2 ); + assertion.element( 0 ) + .returns( "foo ", Token::getTokenValue ) + .returns( false, Token::isParameter ); + assertion.element( 1 ) + .returns( "{bar}", Token::getTokenValue ) + .returns( false, Token::isParameter ); + } + + @Test + public void testMessageExpression() { + ListAssert assertion = Assertions.assertThat( + new TokenCollector( "foo ${bar}", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 2 ); + assertion.element( 0 ) + .returns( "foo ", Token::getTokenValue ) + .returns( false, Token::isParameter ); + assertion.element( 1 ) + .returns( "${bar}", Token::getTokenValue ) + .returns( true, Token::isParameter ); + } + + @Test + public void testDollarThenDollarThenParameterInterpretedAsLiterals() { + ListAssert assertion = Assertions.assertThat( + new TokenCollector( "$${1+1}", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 2 ); + assertion.element( 0 ) + .returns( "$$", Token::getTokenValue ) + .returns( false, Token::isParameter ); + assertion.element( 1 ) + .returns( "{1+1}", Token::getTokenValue ) + .returns( false, Token::isParameter ); + } + + @Test + public void testDollarThenDollarThenLiteralsInterpretedAsLiterals() { + ListAssert assertion = Assertions.assertThat( + new TokenCollector( "$$foo", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 2 ); + assertion.element( 0 ) + .returns( "$$", Token::getTokenValue ) + .returns( false, Token::isParameter ); + assertion.element( 1 ) + .returns( "foo", Token::getTokenValue ) + .returns( false, Token::isParameter ); + } + + @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*") + public void testDollarThenClosingBraceThrowsException() { + new TokenCollector( "$}", getInterpolationTermType() ); + } + + @Test + public void testDollarThenEscapeInterpretedAsLiterals() { + ListAssert assertion = Assertions.assertThat( + new TokenCollector( "$\\A{1+1}", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 2 ); + assertion.element( 0 ) + .returns( "$\\A", Token::getTokenValue ) + .returns( false, Token::isParameter ); + assertion.element( 1 ) + .returns( "{1+1}", Token::getTokenValue ) + .returns( false, Token::isParameter ); + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorMessageParameterTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorMessageParameterTest.java new file mode 100644 index 0000000000..9189f496b3 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorMessageParameterTest.java @@ -0,0 +1,115 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.engine.messageinterpolation; + +import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTermType; +import org.hibernate.validator.internal.engine.messageinterpolation.parser.MessageDescriptorFormatException; +import org.hibernate.validator.internal.engine.messageinterpolation.parser.Token; +import org.hibernate.validator.internal.engine.messageinterpolation.parser.TokenCollector; + +import org.assertj.core.api.Assertions; +import org.assertj.core.api.ListAssert; +import org.testng.annotations.Test; + +/** + * Tests for {@code TokenCollector} in message parameter mode. + * + * @author Hardy Ferentschik + */ +public class TokenCollectorMessageParameterTest extends AbstractTokenCollectorTest { + @Override + protected InterpolationTermType getInterpolationTermType() { + return InterpolationTermType.PARAMETER; + } + + // Several tests inherited from the abstract class + + @Test + public void testMessageParameter() { + ListAssert assertion = Assertions.assertThat( + new TokenCollector( "foo {bar}", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 2 ); + assertion.element( 0 ) + .returns( "foo ", Token::getTokenValue ) + .returns( false, Token::isParameter ); + assertion.element( 1 ) + .returns( "{bar}", Token::getTokenValue ) + .returns( true, Token::isParameter ); + } + + @Test + public void testMessageExpression() { + ListAssert assertion = Assertions.assertThat( + new TokenCollector( "foo ${bar}", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 2 ); + /* + * 6.3.1.1: + * Parameter interpolation has precedence over message expressions. + * For example for the message descriptor ${value}, + * trying to evaluate {value} as message parameter has precedence + * over evaluating ${value} as message expression. + */ + assertion.element( 0 ) + .returns( "foo $", Token::getTokenValue ) + .returns( false, Token::isParameter ); + assertion.element( 1 ) + .returns( "{bar}", Token::getTokenValue ) + .returns( true, Token::isParameter ); + } + + @Test + public void testDollarThenDollarThenParameterInterpretedAsLiteralAndParameter() { + ListAssert assertion = Assertions.assertThat( + new TokenCollector( "$${1+1}", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 2 ); + assertion.element( 0 ) + .returns( "$$", Token::getTokenValue ) + .returns( false, Token::isParameter ); + assertion.element( 1 ) + .returns( "{1+1}", Token::getTokenValue ) + .returns( true, Token::isParameter ); + } + + @Test + public void testDollarThenDollarThenLiteralsInterpretedAsLiterals() { + ListAssert assertion = Assertions.assertThat( + new TokenCollector( "$$foo", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 1 ); + assertion.element( 0 ) + .returns( "$$foo", Token::getTokenValue ) + .returns( false, Token::isParameter ); + } + + @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*") + public void testDollarThenClosingBraceThrowsException() { + // Fails because of the dangling closing brace; the dollar sign is irrelevant + new TokenCollector( "$}", getInterpolationTermType() ); + } + + @Test + public void testDollarThenEscapeInterpretedAsLiterals() { + ListAssert assertion = Assertions.assertThat( + new TokenCollector( "$\\A{1+1}", getInterpolationTermType() ) + .getTokenList() + ) + .hasSize( 2 ); + assertion.element( 0 ) + .returns( "$\\A", Token::getTokenValue ) + .returns( false, Token::isParameter ); + assertion.element( 1 ) + .returns( "{1+1}", Token::getTokenValue ) + .returns( true, Token::isParameter ); + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorTest.java deleted file mode 100644 index ab9299f17a..0000000000 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.test.internal.engine.messageinterpolation; - -import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTermType; -import org.hibernate.validator.internal.engine.messageinterpolation.parser.MessageDescriptorFormatException; -import org.hibernate.validator.internal.engine.messageinterpolation.parser.Token; -import org.hibernate.validator.internal.engine.messageinterpolation.parser.TokenCollector; - -import org.assertj.core.api.Assertions; -import org.assertj.core.api.ListAssert; -import org.testng.annotations.Test; - -/** - * Tests for {@code TokenCollector}. - * - * @author Hardy Ferentschik - */ -public class TokenCollectorTest { - - @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000169.*") - public void testNestedParametersThrowException() throws Exception { - new TokenCollector( "#{foo {}", InterpolationTermType.PARAMETER ); - } - - @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*") - public void testParameterWithoutOpeningBraceThrowsException() throws Exception { - new TokenCollector( "foo}", InterpolationTermType.PARAMETER ); - } - - @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*") - public void testELExpressionDollarThenClosingBraceThrowsException() throws Exception { - new TokenCollector( "$}", InterpolationTermType.EL ); - } - - @Test - public void testELExpressionDollarThenEscapeInterpretedAsLiterals() { - ListAssert assertion = Assertions.assertThat( - new TokenCollector( "$\\A{1+1}", InterpolationTermType.EL ) - .getTokenList() - ) - .hasSize( 2 ); - assertion.element( 0 ) - .returns( "$\\A", Token::getTokenValue ) - .returns( false, Token::isParameter ); - assertion.element( 1 ) - .returns( "{1+1}", Token::getTokenValue ) - .returns( false, Token::isParameter ); - } - - @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*") - public void testTermWithoutClosingBraceThrowsException() throws Exception { - new TokenCollector( "{foo", InterpolationTermType.PARAMETER ); - } - - @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*") - public void testSingleClosingBraceThrowsException() throws Exception { - new TokenCollector( "this message contains a invalid parameter start token {", InterpolationTermType.EL ); - } -} From 5415140b2aea35fa4eb5e0a07323a9f23c04aeda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 25 Feb 2020 13:05:53 +0100 Subject: [PATCH 338/393] HV-1774 Fix an invalid error message for unbalanced '{'/'}' --- .../internal/engine/messageinterpolation/parser/ELState.java | 2 +- .../messageinterpolation/parser/InterpolationTermState.java | 2 +- .../engine/messageinterpolation/parser/MessageState.java | 2 +- .../org/hibernate/validator/internal/util/logging/Log.java | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java index fda95a153c..9f480f8482 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java @@ -47,7 +47,7 @@ public void handleBeginTerm(char character, TokenCollector tokenCollector) throw @Override public void handleEndTerm(char character, TokenCollector tokenCollector) throws MessageDescriptorFormatException { - throw LOG.getNonTerminatedParameterException( + throw LOG.getUnbalancedBeginEndParameterException( tokenCollector.getOriginalMessageDescriptor(), character ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/InterpolationTermState.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/InterpolationTermState.java index 9b00c35948..809db34dd7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/InterpolationTermState.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/InterpolationTermState.java @@ -22,7 +22,7 @@ public class InterpolationTermState implements ParserState { @Override public void terminate(TokenCollector tokenCollector) throws MessageDescriptorFormatException { - throw LOG.getNonTerminatedParameterException( + throw LOG.getUnbalancedBeginEndParameterException( tokenCollector.getOriginalMessageDescriptor(), BEGIN_TERM ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/MessageState.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/MessageState.java index a8b1de63fd..88171668a2 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/MessageState.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/MessageState.java @@ -43,7 +43,7 @@ public void handleBeginTerm(char character, TokenCollector tokenCollector) throw @Override public void handleEndTerm(char character, TokenCollector tokenCollector) throws MessageDescriptorFormatException { - throw LOG.getNonTerminatedParameterException( + throw LOG.getUnbalancedBeginEndParameterException( tokenCollector.getOriginalMessageDescriptor(), character ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 8e3a7ec9ca..cfe3761558 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -614,8 +614,8 @@ ConstraintDefinitionException getValidatorForCrossParameterConstraintMustEitherV ValidationException getOverridingConstraintDefinitionsInMultipleMappingFilesException(String constraintClassName); @Message(id = 168, - value = "The message descriptor '%1$s' contains an unbalanced meta character '%2$c' parameter.") - MessageDescriptorFormatException getNonTerminatedParameterException(String messageDescriptor, char character); + value = "The message descriptor '%1$s' contains an unbalanced meta character '%2$c'.") + MessageDescriptorFormatException getUnbalancedBeginEndParameterException(String messageDescriptor, char character); @Message(id = 169, value = "The message descriptor '%1$s' has nested parameters.") From c2e89a9fb53b82ad4209e49eb97761a5d6141071 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Wed, 6 May 2020 14:24:24 +0000 Subject: [PATCH 339/393] [Jenkins release job] README.md updated by release build 6.1.5.Final --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1bd8ec9ba1..ed3093767a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hibernate Validator -*Version: 6.1.4.Final - 17-04-2020* +*Version: 6.1.5.Final - 06-05-2020* ## What is it? @@ -35,7 +35,7 @@ Logging will delegate any log requests to that provider. org.hibernate.validator hibernate-validator - 6.1.4.Final + 6.1.5.Final You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. @@ -54,7 +54,7 @@ extension by adding the following dependency: org.hibernate.validator hibernate-validator-cdi - 6.1.4.Final + 6.1.5.Final * _hibernate-validator-annotation-processor-<version>.jar_ is an optional jar which can be integrated with your build From 69e43b61adf5cff967451a14bae919f9b71668a7 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Wed, 6 May 2020 14:24:24 +0000 Subject: [PATCH 340/393] [Jenkins release job] changelog.txt updated by release build 6.1.5.Final --- changelog.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/changelog.txt b/changelog.txt index fdc1352da8..6c69f576c7 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,17 @@ Hibernate Validator Changelog ============================= +6.1.5.Final (06-05-2020) +------------------------- + +** Bug + * HV-1774 - engine - Invalid parsing of EL expression can lead to invalid EL expressions considered valid + * HV-1772 - engine - Building multiple ValidatorFactory instances from a single Configuration violates specification for MessageInterpolator + * HV-1771 - translations - Fix DecimalMin message German translation + +** Improvement + * HV-1773 - documentation - Be more explicit about issues with EL injection and how to avoid them + 6.1.4.Final (17-04-2020) ------------------------- From 8bd23be81cb7c34604b7ed401ac5d9045110681d Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Wed, 6 May 2020 14:24:29 +0000 Subject: [PATCH 341/393] [Jenkins release job] Preparing release 6.1.5.Final --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index d804576379..84e9461722 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5-SNAPSHOT + 6.1.5.Final ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 7c66196603..87c77e0b00 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5-SNAPSHOT + 6.1.5.Final ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index bc31053f8a..d96a8e25ea 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5-SNAPSHOT + 6.1.5.Final ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index e0513b7778..bf1465e9ff 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5-SNAPSHOT + 6.1.5.Final ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 9d9c31632e..dcbeed85d4 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5-SNAPSHOT + 6.1.5.Final ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index e4b6a38370..b4d90a2140 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5-SNAPSHOT + 6.1.5.Final ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index c6886f1296..0842788fbf 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5-SNAPSHOT + 6.1.5.Final ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index b680be6572..df7dab377b 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5-SNAPSHOT + 6.1.5.Final 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index ef7dc36597..5c8478bf0b 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.5-SNAPSHOT + 6.1.5.Final ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 65de4d6167..25f8f60c1f 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.5-SNAPSHOT + 6.1.5.Final ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 7543e37360..7ff2545197 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.5-SNAPSHOT + 6.1.5.Final ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index 627442801a..fbf487a2af 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5-SNAPSHOT + 6.1.5.Final ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index b6759ae664..1840136b38 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5-SNAPSHOT + 6.1.5.Final ../pom.xml diff --git a/pom.xml b/pom.xml index 3e31ca35f5..b37b546a77 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5-SNAPSHOT + 6.1.5.Final pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index f27fed2e0a..0fdff82f9d 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.5-SNAPSHOT + 6.1.5.Final org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index 6e61b9f092..6766a8b44b 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.5-SNAPSHOT + 6.1.5.Final org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index 0d249ce3c5..eb5da39042 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.5-SNAPSHOT + 6.1.5.Final org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index 343e9c7ccf..430db4e735 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.5-SNAPSHOT + 6.1.5.Final org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index d5274f8f13..a428ae94ed 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5-SNAPSHOT + 6.1.5.Final hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 34a82fe6dd..7493c4f3a3 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5-SNAPSHOT + 6.1.5.Final ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index da68267f7c..6c369d4d07 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5-SNAPSHOT + 6.1.5.Final hibernate-validator-test-utils From db05d7245f6a180bd5e59dbf4cbc7f594724541d Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Wed, 6 May 2020 14:27:34 +0000 Subject: [PATCH 342/393] [Jenkins release job] Preparing next development iteration --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 84e9461722..680234f86a 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5.Final + 6.1.6-SNAPSHOT ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 87c77e0b00..e28a1aa3a1 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5.Final + 6.1.6-SNAPSHOT ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index d96a8e25ea..01e47da1a0 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5.Final + 6.1.6-SNAPSHOT ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index bf1465e9ff..c128d1f5aa 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5.Final + 6.1.6-SNAPSHOT ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index dcbeed85d4..b090b20f27 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5.Final + 6.1.6-SNAPSHOT ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index b4d90a2140..381f87910e 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5.Final + 6.1.6-SNAPSHOT ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 0842788fbf..a419e11300 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5.Final + 6.1.6-SNAPSHOT ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index df7dab377b..1a4b6ed7a8 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5.Final + 6.1.6-SNAPSHOT 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 5c8478bf0b..07a381a04e 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.5.Final + 6.1.6-SNAPSHOT ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 25f8f60c1f..0e8a32c067 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.5.Final + 6.1.6-SNAPSHOT ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 7ff2545197..8c3f06ba11 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.5.Final + 6.1.6-SNAPSHOT ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index fbf487a2af..17c11b325e 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5.Final + 6.1.6-SNAPSHOT ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index 1840136b38..505f879753 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5.Final + 6.1.6-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index b37b546a77..3a0272475b 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5.Final + 6.1.6-SNAPSHOT pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 0fdff82f9d..d8872f2b31 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.5.Final + 6.1.6-SNAPSHOT org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index 6766a8b44b..9a3ba3350c 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.5.Final + 6.1.6-SNAPSHOT org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index eb5da39042..23fd75a8d7 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.5.Final + 6.1.6-SNAPSHOT org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index 430db4e735..63ba6992d8 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.5.Final + 6.1.6-SNAPSHOT org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index a428ae94ed..f1e950283a 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5.Final + 6.1.6-SNAPSHOT hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 7493c4f3a3..5efa3c1498 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5.Final + 6.1.6-SNAPSHOT ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 6c369d4d07..a81cf5c224 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.5.Final + 6.1.6-SNAPSHOT hibernate-validator-test-utils From 038f0f071c06b1d1a338b60901bd53370e7a8130 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 2 Jun 2020 14:46:58 +0200 Subject: [PATCH 343/393] HV-1782 Remove trailing dot from @Max constraint German translation --- .../org/hibernate/validator/ValidationMessages_de.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties index f375f24174..6ed149adcf 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_de.properties @@ -6,7 +6,7 @@ javax.validation.constraints.Digits.message = numerischer Wert au\u00df javax.validation.constraints.Email.message = muss eine korrekt formatierte E-Mail-Adresse sein javax.validation.constraints.Future.message = muss ein Datum in der Zukunft sein javax.validation.constraints.FutureOrPresent.message = muss ein Datum in der Gegenwart oder in der Zukunft sein -javax.validation.constraints.Max.message = muss kleiner-gleich {value} sein. +javax.validation.constraints.Max.message = muss kleiner-gleich {value} sein javax.validation.constraints.Min.message = muss gr\u00f6\u00dfer-gleich {value} sein javax.validation.constraints.Negative.message = muss kleiner als 0 sein javax.validation.constraints.NegativeOrZero.message = muss kleiner-gleich 0 sein From 423ecc16033f559d30cb679c4fafe9716cb241d2 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Tue, 19 May 2020 17:13:28 -0400 Subject: [PATCH 344/393] HV-1780 Add @Normalized contraint that validates unicode normalization form --- .../ap/internal/util/ConstraintHelper.java | 1 + .../validator/ap/internal/util/TypeNames.java | 1 + .../ap/ConstraintValidationProcessorTest.java | 20 ++++ .../ModelWithNormalizedConstraints.java | 28 ++++++ documentation/src/main/asciidoc/ch02.asciidoc | 4 + .../validator/cfg/defs/NormalizedDef.java | 31 ++++++ .../validator/constraints/Normalized.java | 62 ++++++++++++ .../hv/NormalizedValidator.java | 37 +++++++ .../metadata/core/BuiltinConstraint.java | 1 + .../metadata/core/ConstraintHelper.java | 6 ++ .../validator/ValidationMessages.properties | 1 + .../MessagePropertiesTest.java | 5 + .../PredefinedScopeAllConstraintsTest.java | 9 ++ .../hv/NormalizedValidatorTest.java | 96 +++++++++++++++++++ 14 files changed, 302 insertions(+) create mode 100644 annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/ModelWithNormalizedConstraints.java create mode 100644 engine/src/main/java/org/hibernate/validator/cfg/defs/NormalizedDef.java create mode 100644 engine/src/main/java/org/hibernate/validator/constraints/Normalized.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/NormalizedValidator.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/NormalizedValidatorTest.java diff --git a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/ConstraintHelper.java b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/ConstraintHelper.java index 9b5090f802..52e0d702d0 100644 --- a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/ConstraintHelper.java +++ b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/ConstraintHelper.java @@ -304,6 +304,7 @@ public ConstraintHelper(Types typeUtils, AnnotationApiHelper annotationApiHelper registerAllowedTypesForBuiltInConstraint( HibernateValidatorTypes.PESEL_CHECK, CharSequence.class ); registerAllowedTypesForBuiltInConstraint( HibernateValidatorTypes.NOT_BLANK, CharSequence.class ); registerAllowedTypesForBuiltInConstraint( HibernateValidatorTypes.NOT_EMPTY, TYPES_SUPPORTED_BY_SIZE_AND_NOT_EMPTY_ANNOTATIONS ); + registerAllowedTypesForBuiltInConstraint( HibernateValidatorTypes.NORMALIZED, CharSequence.class ); registerAllowedTypesForBuiltInConstraint( HibernateValidatorTypes.SAFE_HTML, CharSequence.class ); registerAllowedTypesForBuiltInConstraint( HibernateValidatorTypes.SCRIPT_ASSERT, Object.class ); registerAllowedTypesForBuiltInConstraint( HibernateValidatorTypes.UNIQUE_ELEMENTS, Collection.class ); diff --git a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/TypeNames.java b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/TypeNames.java index b2a1ef1c9c..bb6622139a 100644 --- a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/TypeNames.java +++ b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/TypeNames.java @@ -78,6 +78,7 @@ public static class HibernateValidatorTypes { public static final String REGON_CHECK = ORG_HIBERNATE_VALIDATOR_CONSTRAINTS + ".pl.REGON"; public static final String NIP_CHECK = ORG_HIBERNATE_VALIDATOR_CONSTRAINTS + ".pl.NIP"; public static final String PESEL_CHECK = ORG_HIBERNATE_VALIDATOR_CONSTRAINTS + ".pl.PESEL"; + public static final String NORMALIZED = ORG_HIBERNATE_VALIDATOR_CONSTRAINTS + ".Normalized"; public static final String NOT_BLANK = ORG_HIBERNATE_VALIDATOR_CONSTRAINTS + ".NotBlank"; public static final String NOT_EMPTY = ORG_HIBERNATE_VALIDATOR_CONSTRAINTS + ".NotEmpty"; public static final String SAFE_HTML = ORG_HIBERNATE_VALIDATOR_CONSTRAINTS + ".SafeHtml"; diff --git a/annotation-processor/src/test/java/org/hibernate/validator/ap/ConstraintValidationProcessorTest.java b/annotation-processor/src/test/java/org/hibernate/validator/ap/ConstraintValidationProcessorTest.java index bf6f60e705..b5777ceb06 100644 --- a/annotation-processor/src/test/java/org/hibernate/validator/ap/ConstraintValidationProcessorTest.java +++ b/annotation-processor/src/test/java/org/hibernate/validator/ap/ConstraintValidationProcessorTest.java @@ -26,6 +26,7 @@ import org.hibernate.validator.ap.testmodel.ModelWithJava8DateTime; import org.hibernate.validator.ap.testmodel.ModelWithJavaMoneyTypes; import org.hibernate.validator.ap.testmodel.ModelWithJodaTypes; +import org.hibernate.validator.ap.testmodel.ModelWithNormalizedConstraints; import org.hibernate.validator.ap.testmodel.ModelWithUniqueElementsConstraints; import org.hibernate.validator.ap.testmodel.ModelWithoutConstraints; import org.hibernate.validator.ap.testmodel.MultipleConstraintsOfSameType; @@ -724,6 +725,25 @@ public void codePointLengthConstraints() { ); } + @Test + @TestForIssue(jiraKey = "HV-1780") + public void normalizedConstraints() { + File[] sourceFiles = new File[] { + compilerHelper.getSourceFile( ModelWithNormalizedConstraints.class ) + }; + + boolean compilationResult = + compilerHelper.compile( new ConstraintValidationProcessor(), diagnostics, false, true, sourceFiles ); + + assertFalse( compilationResult ); + assertThatDiagnosticsMatch( + diagnostics, + new DiagnosticExpectation( Kind.ERROR, 17 ), + new DiagnosticExpectation( Kind.ERROR, 20 ), + new DiagnosticExpectation( Kind.ERROR, 23 ) + ); + } + @Test public void isbnConstraints() { File[] sourceFiles = new File[] { diff --git a/annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/ModelWithNormalizedConstraints.java b/annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/ModelWithNormalizedConstraints.java new file mode 100644 index 0000000000..2551e5189d --- /dev/null +++ b/annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/ModelWithNormalizedConstraints.java @@ -0,0 +1,28 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.ap.testmodel; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import org.hibernate.validator.constraints.Normalized; + +public class ModelWithNormalizedConstraints { + + @Normalized + public Collection collection; + + @Normalized + public List list; + + @Normalized + public Set set; + + @Normalized + public String string; +} diff --git a/documentation/src/main/asciidoc/ch02.asciidoc b/documentation/src/main/asciidoc/ch02.asciidoc index 391d464e48..1a93ee42c7 100644 --- a/documentation/src/main/asciidoc/ch02.asciidoc +++ b/documentation/src/main/asciidoc/ch02.asciidoc @@ -707,6 +707,10 @@ With one exception also these constraints apply to the field/property level, onl Supported data types::: `CharSequence` Hibernate metadata impact::: None +`@Normalized(form=)`:: Validates that the annotated character sequence is normalized according to the given `form`. + Supported data types::: `CharSequence` + Hibernate metadata impact::: None + `@Range(min=, max=)`:: Checks whether the annotated value lies between (inclusive) the specified minimum and maximum Supported data types::: `BigDecimal`, `BigInteger`, `CharSequence`, `byte`, `short`, `int`, `long` and the respective wrappers of the primitive types Hibernate metadata impact::: None diff --git a/engine/src/main/java/org/hibernate/validator/cfg/defs/NormalizedDef.java b/engine/src/main/java/org/hibernate/validator/cfg/defs/NormalizedDef.java new file mode 100644 index 0000000000..5e6c63c2ca --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/cfg/defs/NormalizedDef.java @@ -0,0 +1,31 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ + +package org.hibernate.validator.cfg.defs; + +import org.hibernate.validator.cfg.ConstraintDef; +import org.hibernate.validator.constraints.Normalized; + +import java.text.Normalizer; + + +/** + * Constraint definition for {@link Normalized}. + * @author Craig Andrews + * @since 6.1.6 + */ +public class NormalizedDef extends ConstraintDef { + + public NormalizedDef() { + super( Normalized.class ); + } + + public NormalizedDef normalizationStrategy(Normalizer.Form form) { + addParameter( "normalizationForm", form ); + return this; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/constraints/Normalized.java b/engine/src/main/java/org/hibernate/validator/constraints/Normalized.java new file mode 100644 index 0000000000..71eddf7bb6 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/constraints/Normalized.java @@ -0,0 +1,62 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.constraints; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.text.Normalizer; + +import javax.validation.Constraint; +import javax.validation.Payload; + +import org.hibernate.validator.constraints.Normalized.List; + + +/** + * Validate that a character sequence is of normalization form. + *

    + * It is possible to validate a normalized value by setting the normalization strategy. + * + * @author Craig Andrews + * @since 6.1.6 + */ +@Documented +@Constraint(validatedBy = { }) +@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) +@Retention(RUNTIME) +@Repeatable(List.class) +public @interface Normalized { + + Normalizer.Form form() default Normalizer.Form.NFC; + + String message() default "{org.hibernate.validator.constraints.Normalized.message}"; + + Class[] groups() default { }; + + Class[] payload() default { }; + + /** + * Defines several {@code @Normalized} annotations on the same element. + */ + @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) + @Retention(RUNTIME) + @Documented + public @interface List { + Normalized[] value(); + } +} + diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/NormalizedValidator.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/NormalizedValidator.java new file mode 100644 index 0000000000..b8e107584e --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/NormalizedValidator.java @@ -0,0 +1,37 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.constraintvalidators.hv; + +import java.text.Normalizer; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.hibernate.validator.constraints.Normalized; + +/** + * Check that a character sequence is normalized. + * + * @author Craig Andrews + */ +public class NormalizedValidator implements ConstraintValidator { + + private Normalizer.Form form; + + @Override + public void initialize(Normalized parameters) { + form = parameters.form(); + } + + @Override + public boolean isValid(CharSequence value, ConstraintValidatorContext constraintValidatorContext) { + if ( value == null ) { + return true; + } + return Normalizer.isNormalized( value, form ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/BuiltinConstraint.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/BuiltinConstraint.java index 9a7197359b..14522d23d8 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/BuiltinConstraint.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/BuiltinConstraint.java @@ -64,6 +64,7 @@ enum BuiltinConstraint { ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD10_CHECK("org.hibernate.validator.constraints.Mod10Check"), ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD11_CHECK("org.hibernate.validator.constraints.Mod11Check"), ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD_CHECK("org.hibernate.validator.constraints.ModCheck"), + ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NORMALIZED("org.hibernate.validator.constraints.Normalized"), ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_EAN("org.hibernate.validator.constraints.EAN", Arrays.asList( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD10_CHECK ) ), ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NOT_BLANK("org.hibernate.validator.constraints.NotBlank", Arrays.asList( JAVAX_VALIDATION_CONSTRAINTS_NOT_NULL ) ), diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java index 63ee0c30c7..b303d4b01c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/ConstraintHelper.java @@ -42,6 +42,7 @@ import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD10_CHECK; import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD11_CHECK; import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD_CHECK; +import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NORMALIZED; import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NOT_BLANK; import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NOT_EMPTY; import static org.hibernate.validator.internal.metadata.core.BuiltinConstraint.ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PARAMETER_SCRIPT_ASSERT; @@ -114,6 +115,7 @@ import org.hibernate.validator.constraints.Mod10Check; import org.hibernate.validator.constraints.Mod11Check; import org.hibernate.validator.constraints.ModCheck; +import org.hibernate.validator.constraints.Normalized; import org.hibernate.validator.constraints.ParameterScriptAssert; import org.hibernate.validator.constraints.Range; import org.hibernate.validator.constraints.SafeHtml; @@ -331,6 +333,7 @@ import org.hibernate.validator.internal.constraintvalidators.hv.Mod10CheckValidator; import org.hibernate.validator.internal.constraintvalidators.hv.Mod11CheckValidator; import org.hibernate.validator.internal.constraintvalidators.hv.ModCheckValidator; +import org.hibernate.validator.internal.constraintvalidators.hv.NormalizedValidator; import org.hibernate.validator.internal.constraintvalidators.hv.ParameterScriptAssertValidator; import org.hibernate.validator.internal.constraintvalidators.hv.SafeHtmlValidator; import org.hibernate.validator.internal.constraintvalidators.hv.ScriptAssertValidator; @@ -776,6 +779,9 @@ private ConstraintHelper(Set enabledBuiltinConstraints) { if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_MOD11_CHECK ) ) { putBuiltinConstraint( tmpConstraints, Mod11Check.class, Mod11CheckValidator.class ); } + if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_NORMALIZED ) ) { + putBuiltinConstraint( tmpConstraints, Normalized.class, NormalizedValidator.class ); + } if ( enabledBuiltinConstraints.contains( ORG_HIBERNATE_VALIDATOR_CONSTRAINTS_PL_NIP ) ) { putBuiltinConstraint( tmpConstraints, NIP.class, NIPValidator.class ); } diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages.properties index c3064d0066..dbc354de94 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages.properties @@ -32,6 +32,7 @@ org.hibernate.validator.constraints.LuhnCheck.message = the check org.hibernate.validator.constraints.Mod10Check.message = the check digit for ${validatedValue} is invalid, Modulo 10 checksum failed org.hibernate.validator.constraints.Mod11Check.message = the check digit for ${validatedValue} is invalid, Modulo 11 checksum failed org.hibernate.validator.constraints.ModCheck.message = the check digit for ${validatedValue} is invalid, {modType} checksum failed +org.hibernate.validator.constraints.Normalized.message = must be normalized org.hibernate.validator.constraints.NotBlank.message = may not be empty org.hibernate.validator.constraints.NotEmpty.message = may not be empty org.hibernate.validator.constraints.ParametersScriptAssert.message = script expression "{script}" didn't evaluate to true diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/MessagePropertiesTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/MessagePropertiesTest.java index ad05550768..31ff853c1a 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/MessagePropertiesTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/MessagePropertiesTest.java @@ -56,6 +56,7 @@ import org.hibernate.validator.constraints.Mod10Check; import org.hibernate.validator.constraints.Mod11Check; import org.hibernate.validator.constraints.ModCheck; +import org.hibernate.validator.constraints.Normalized; import org.hibernate.validator.constraints.ParameterScriptAssert; import org.hibernate.validator.constraints.Range; import org.hibernate.validator.constraints.SafeHtml; @@ -157,6 +158,7 @@ public void testMessageProperties() throws NoSuchMethodException, SecurityExcept violationOf( Mod10Check.class ), violationOf( Mod11Check.class ), violationOf( ModCheck.class ), + violationOf( Normalized.class ), violationOf( org.hibernate.validator.constraints.NotBlank.class ), violationOf( org.hibernate.validator.constraints.NotEmpty.class ), violationOf( Range.class ), @@ -308,6 +310,9 @@ private static class Bean { @ModCheck(multiplier = 2, modType = ModCheck.ModType.MOD10) private String modCheck = "4"; + @Normalized(form = java.text.Normalizer.Form.NFKC) + private String normalized = "\uFE64script\uFE65"; + @org.hibernate.validator.constraints.NotBlank private String hvNotBlank = ""; diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/PredefinedScopeAllConstraintsTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/PredefinedScopeAllConstraintsTest.java index a157dbc051..db18219ade 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/PredefinedScopeAllConstraintsTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/PredefinedScopeAllConstraintsTest.java @@ -55,6 +55,7 @@ import org.hibernate.validator.constraints.Mod10Check; import org.hibernate.validator.constraints.Mod11Check; import org.hibernate.validator.constraints.ModCheck; +import org.hibernate.validator.constraints.Normalized; import org.hibernate.validator.constraints.ParameterScriptAssert; import org.hibernate.validator.constraints.Range; import org.hibernate.validator.constraints.SafeHtml; @@ -116,6 +117,7 @@ public void testConstraints() throws NoSuchMethodException, SecurityException { testConstraint( Mod10Check.class, new Mod10CheckBean() ); testConstraint( Mod11Check.class, new Mod11CheckBean() ); testConstraint( ModCheck.class, new ModCheckBean() ); + testConstraint( Normalized.class, new NormalizedBean() ); testConstraint( org.hibernate.validator.constraints.NotBlank.class, new HvNotBlankBean() ); testConstraint( org.hibernate.validator.constraints.NotEmpty.class, new HvNotEmptyBean() ); testConstraint( Range.class, new RangeBean() ); @@ -356,6 +358,13 @@ private static class ModCheckBean { private String modCheck = "4"; } + private static class NormalizedBean { + + @Normalized(form = java.text.Normalizer.Form.NFKC) + private String normalized = "\uFE64script\uFE65"; + + } + private static class HvNotBlankBean { @org.hibernate.validator.constraints.NotBlank diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/NormalizedValidatorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/NormalizedValidatorTest.java new file mode 100644 index 0000000000..50681e6d81 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/NormalizedValidatorTest.java @@ -0,0 +1,96 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.constraintvalidators.hv; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import org.hibernate.validator.constraints.Normalized; +import org.hibernate.validator.internal.constraintvalidators.hv.NormalizedValidator; +import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; +import org.hibernate.validator.testutil.MyCustomStringImpl; + +import java.text.Normalizer; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * Tests the {@link Normalized} constraint. + * + * @author Kazuki Shimizu + */ +public class NormalizedValidatorTest { + + private ConstraintAnnotationDescriptor.Builder descriptorBuilder; + + @BeforeMethod + public void setUp() throws Exception { + descriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( Normalized.class ); + } + + @Test + public void testIsValid() { + descriptorBuilder.setMessage( "{validator.Normalized}" ); + Normalized l = descriptorBuilder.build().getAnnotation(); + NormalizedValidator constraint = new NormalizedValidator(); + constraint.initialize( l ); + assertTrue( constraint.isValid( null, null ) ); + assertTrue( constraint.isValid( "", null ) ); + assertTrue( constraint.isValid( "foobar", null ) ); + assertTrue( constraint.isValid( "\uFE64script\uFE65", null ) ); + } + + @Test + public void testIsValidCharSequence() { + Normalized l = descriptorBuilder.build().getAnnotation(); + NormalizedValidator constraint = new NormalizedValidator(); + constraint.initialize( l ); + assertTrue( constraint.isValid( new MyCustomStringImpl( "foobar" ), null ) ); + assertTrue( constraint.isValid( new MyCustomStringImpl( "\uFE64script\uFE65" ), null ) ); + } + + @Test + public void testIsValidNormalizationStrategyIsNfc() { + descriptorBuilder.setAttribute( "form", Normalizer.Form.NFC ); + Normalized l = descriptorBuilder.build().getAnnotation(); + NormalizedValidator constraint = new NormalizedValidator(); + constraint.initialize( l ); + assertTrue( constraint.isValid( "foobar", null ) ); + assertTrue( constraint.isValid( "\uFE64script\uFE65", null ) ); + } + + @Test + public void testIsValidNormalizationStrategyIsNfkc() { + descriptorBuilder.setAttribute( "form", Normalizer.Form.NFKC ); + Normalized l = descriptorBuilder.build().getAnnotation(); + NormalizedValidator constraint = new NormalizedValidator(); + constraint.initialize( l ); + assertTrue( constraint.isValid( "foobar", null ) ); + assertFalse( constraint.isValid( "\uFE64script\uFE65", null ) ); + } + + @Test + public void testIsValidNormalizationStrategyIsNfd() { + descriptorBuilder.setAttribute( "form", Normalizer.Form.NFD ); + Normalized l = descriptorBuilder.build().getAnnotation(); + NormalizedValidator constraint = new NormalizedValidator(); + constraint.initialize( l ); + assertTrue( constraint.isValid( "foobar", null ) ); + assertTrue( constraint.isValid( "\uFE64script\uFE65", null ) ); + } + + @Test + public void testIsValidNormalizationStrategyIsNfkd() { + descriptorBuilder.setAttribute( "form", Normalizer.Form.NFKD ); + Normalized l = descriptorBuilder.build().getAnnotation(); + NormalizedValidator constraint = new NormalizedValidator(); + constraint.initialize( l ); + assertTrue( constraint.isValid( "foobar", null ) ); + assertFalse( constraint.isValid( "\uFE64script\uFE65", null ) ); + } +} From 51186fe8a3eb589d79376c38b50264b3771ccb2a Mon Sep 17 00:00:00 2001 From: agatsenko Date: Tue, 30 Jun 2020 23:36:15 +0300 Subject: [PATCH 345/393] HV-1761 fix interpolation of primitive arrays --- .../ParameterTermResolver.java | 45 ++++- .../ParameterTermResolverTest.java | 160 ++++++++++++++++++ 2 files changed, 199 insertions(+), 6 deletions(-) create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ParameterTermResolverTest.java diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/ParameterTermResolver.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/ParameterTermResolver.java index a880afe755..83337d0fea 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/ParameterTermResolver.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/ParameterTermResolver.java @@ -18,6 +18,7 @@ * @author Hardy Ferentschik * @author Adam Stawicki * @author Guillaume Smet + * @author Alexander Gatsenko */ public class ParameterTermResolver implements TermResolver { @@ -26,12 +27,7 @@ public String interpolate(Context context, String expression) { String resolvedExpression; Object variable = getVariable( context, removeCurlyBraces( expression ) ); if ( variable != null ) { - if ( variable.getClass().isArray() ) { - resolvedExpression = Arrays.toString( (Object[]) variable ); - } - else { - resolvedExpression = variable.toString(); - } + resolvedExpression = resolveExpression( variable ); } else { resolvedExpression = expression; @@ -52,4 +48,41 @@ private Object getVariable(Context context, String parameter) { private String removeCurlyBraces(String parameter) { return parameter.substring( 1, parameter.length() - 1 ); } + + private String resolveExpression(Object variable) { + final String resolvedExpression; + if ( variable.getClass().isArray() ) { + if ( variable.getClass() == boolean[].class ) { + resolvedExpression = Arrays.toString( (boolean[]) variable ); + } + else if ( variable.getClass() == char[].class ) { + resolvedExpression = Arrays.toString( (char[]) variable ); + } + else if ( variable.getClass() == byte[].class ) { + resolvedExpression = Arrays.toString( (byte[]) variable ); + } + else if ( variable.getClass() == short[].class ) { + resolvedExpression = Arrays.toString( (short[]) variable ); + } + else if ( variable.getClass() == int[].class ) { + resolvedExpression = Arrays.toString( (int[]) variable ); + } + else if ( variable.getClass() == long[].class ) { + resolvedExpression = Arrays.toString( (long[]) variable ); + } + else if ( variable.getClass() == float[].class ) { + resolvedExpression = Arrays.toString( (float[]) variable ); + } + else if ( variable.getClass() == double[].class ) { + resolvedExpression = Arrays.toString( (double[]) variable ); + } + else { + resolvedExpression = Arrays.toString( (Object[]) variable ); + } + } + else { + resolvedExpression = variable.toString(); + } + return resolvedExpression; + } } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ParameterTermResolverTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ParameterTermResolverTest.java new file mode 100644 index 0000000000..8f6feb5f42 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ParameterTermResolverTest.java @@ -0,0 +1,160 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.engine.messageinterpolation; + +import static org.testng.Assert.assertEquals; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import javax.validation.MessageInterpolator; +import javax.validation.metadata.ConstraintDescriptor; + +import org.hibernate.validator.internal.engine.messageinterpolation.ParameterTermResolver; +import org.hibernate.validator.messageinterpolation.HibernateMessageInterpolatorContext; +import org.hibernate.validator.testutil.TestForIssue; + +import org.easymock.EasyMock; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * Test for {@link org.hibernate.validator.internal.engine.messageinterpolation.ParameterTermResolver} + * + * @author Alexander Gatsenko + */ +public class ParameterTermResolverTest { + + private final ParameterTermResolver resolver = new ParameterTermResolver(); + + @DataProvider(name = "interpolateByNotArrayValueArgs") + public static Object[][] interpolateByNotArrayValueArgs() { + // lines of (String variableName, Object variableValue, String expectedResolvedExpression) + return new Object[][] { + { "value", null, "{value}" }, + { "value", true, "true" }, + { "value", false, "false" }, + { "value", 'a', "a" }, + { "value", (byte) 10, "10" }, + { "value", (short) 10, "10" }, + { "value", 10, "10" }, + { "value", 10L, "10" }, + { "value", 10.1, "10.1" }, + { "value", 10.1f, "10.1" }, + { "value", "string value", "string value" }, + }; + } + + @DataProvider(name = "interpolateByArrayValueArgs") + public static Object[][] interpolateByArrayValueArgs() { + // lines of (String variableName, variableValueArray, String expectedResolvedExpression) + return new Object[][] { + { "value", new boolean[] { true, false }, Arrays.toString( new boolean[] { true, false } ) }, + { "value", new char[] { 'a', 'b' }, Arrays.toString( new char[] { 'a', 'b' } ) }, + { "value", new byte[] { 1, 2 }, Arrays.toString( new byte[] { 1, 2 } ) }, + { "value", new short[] { 1, 2 }, Arrays.toString( new short[] { 1, 2 } ) }, + { "value", new int[] { 1, 2 }, Arrays.toString( new int[] { 1, 2 } ) }, + { "value", new long[] { 1, 2 }, Arrays.toString( new long[] { 1, 2 } ) }, + { "value", new double[] { 1.2, 3.4 }, Arrays.toString( new double[] { 1.2, 3.4 } ) }, + { "value", new float[] { 1.2F, 3.4F }, Arrays.toString( new float[] { 1.2F, 3.4F } ) }, + { "value", new String[] { "one", "two" }, Arrays.toString( new String[] { "one", "two" } ) }, + }; + } + + @Test(dataProvider = "interpolateByNotArrayValueArgs") + public void testInterpolateShouldResolveExpressionByNotArrayValue( + String variableName, + Object variableValue, + String expectedResolvedExpression) { + final MessageInterpolator.Context context = createHibernateContextWithConstraintDescriptorAttr( + variableName, + variableValue + ); + final String srcExpression = createVariableExpression( variableName ); + + final String actualResolvedExpression = resolver.interpolate( context, srcExpression ); + assertEquals( actualResolvedExpression, expectedResolvedExpression ); + } + + @Test(dataProvider = "interpolateByArrayValueArgs") + @TestForIssue(jiraKey = "HV-1761") + public void testInterpolateShouldResolveExpressionByArrayValue( + String variableName, + Object variableValueArray, + String expectedResolvedExpression) { + final MessageInterpolator.Context context = createHibernateContextWithConstraintDescriptorAttr( + variableName, + variableValueArray + ); + final String srcExpression = createVariableExpression( variableName ); + + final String actualResolvedExpression = resolver.interpolate( context, srcExpression ); + assertEquals( actualResolvedExpression, expectedResolvedExpression ); + } + + @Test(dataProvider = "interpolateByNotArrayValueArgs") + public void testInterpolateShouldAllowUseNotHibernateContext( + String variableName, + Object variableValue, + String expectedResolvedExpression) { + final MessageInterpolator.Context context = createNotHibernateContextWithConstraintDescriptorAttr( + variableName, + variableValue + ); + final String srcExpression = createVariableExpression( variableName ); + + final String actualResolvedExpression = resolver.interpolate( context, srcExpression ); + assertEquals( actualResolvedExpression, expectedResolvedExpression ); + } + + private static String createVariableExpression(String variableName) { + return String.format( "{%s}", variableName ); + } + + private static Map createConstraintDescriptorAttr(String attrName, Object attrValue) { + Map map = new HashMap<>( 1 ); + map.put( attrName, attrValue ); + return map; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private static MessageInterpolator.Context createNotHibernateContextWithConstraintDescriptorAttr( + String attrName, + Object attrValue) { + final Map attrs = createConstraintDescriptorAttr( attrName, attrValue ); + + final MessageInterpolator.Context context = EasyMock.mock( MessageInterpolator.Context.class ); + final ConstraintDescriptor constraintDescriptor = EasyMock.mock( ConstraintDescriptor.class ); + + EasyMock.expect( context.getConstraintDescriptor() ).andStubReturn( constraintDescriptor ); + EasyMock.expect( constraintDescriptor.getAttributes() ).andStubReturn( attrs ); + + EasyMock.replay( context ); + EasyMock.replay( constraintDescriptor ); + + return context; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private static MessageInterpolator.Context createHibernateContextWithConstraintDescriptorAttr( + String attrName, + Object attrValue) { + final Map attrs = createConstraintDescriptorAttr( attrName, attrValue ); + + final HibernateMessageInterpolatorContext context = EasyMock.mock( HibernateMessageInterpolatorContext.class ); + final ConstraintDescriptor constraintDescriptor = EasyMock.mock( ConstraintDescriptor.class ); + + EasyMock.expect( context.getMessageParameters() ).andStubReturn( attrs ); + EasyMock.expect( context.getConstraintDescriptor() ).andStubReturn( constraintDescriptor ); + EasyMock.expect( constraintDescriptor.getAttributes() ).andStubReturn( attrs ); + + EasyMock.replay( context ); + EasyMock.replay( constraintDescriptor ); + + return context; + } +} From cd0e9a5be72dc8fffdecbf9800c27a60e0098f85 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 23 Jul 2020 12:49:42 +0200 Subject: [PATCH 346/393] HV-1795 Remove link to JavaMoney javadoc --- distribution/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/distribution/pom.xml b/distribution/pom.xml index c128d1f5aa..c86b52a46e 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -119,7 +119,7 @@ ${java.api-docs.base-url} ${javaee.api-docs.base-url} ${bv.api-docs.base-url} - ${javamoney.api-docs.base-url} + From 69b1ce3991b21e02452610df14bc6b38936ecf34 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 28 Sep 2020 11:52:08 +0200 Subject: [PATCH 347/393] HV-1802 Update ByteBuddy test dependency to 1.10.16 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3a0272475b..5f58180378 100644 --- a/pom.xml +++ b/pom.xml @@ -176,7 +176,7 @@ 1.0.0.Final 2.10.3 2.10.3 - 1.10.2 + 1.10.16 4.2.0 From caf79c1ac17bb468ec6042e255e0cc9baa243064 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 28 Sep 2020 16:14:14 +0200 Subject: [PATCH 348/393] HV-1803 Move the tests to log4j2 --- cdi/pom.xml | 4 +- distribution/pom.xml | 4 +- distribution/src/main/assembly/dist.xml | 2 +- engine/pom.xml | 10 +++- .../ParameterMessageInterpolatorTest.java | 34 ++++++++----- engine/src/test/resources/log4j.properties | 26 ---------- engine/src/test/resources/log4j2.properties | 22 +++++++++ integration/pom.xml | 5 -- ...mValidationProviderInDeploymentUnitIT.java | 6 --- .../JndiLookupOfValidatorFactoryIT.java | 4 -- ...omValidatorFactoryInPersistenceUnitIT.java | 10 ---- osgi/integrationtest/pom.xml | 4 +- pom.xml | 20 +++++--- test-utils/pom.xml | 4 +- .../MessageLoggedAssertionLogger.java | 49 ------------------- 15 files changed, 75 insertions(+), 129 deletions(-) delete mode 100644 engine/src/test/resources/log4j.properties create mode 100644 engine/src/test/resources/log4j2.properties delete mode 100644 test-utils/src/main/java/org/hibernate/validator/testutil/MessageLoggedAssertionLogger.java diff --git a/cdi/pom.xml b/cdi/pom.xml index 01e47da1a0..517267a17e 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -67,8 +67,8 @@ test - log4j - log4j + org.apache.logging.log4j + log4j-core test diff --git a/distribution/pom.xml b/distribution/pom.xml index c86b52a46e..18b104ea65 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -50,8 +50,8 @@ - log4j - log4j + org.apache.logging.log4j + log4j-core jakarta.persistence diff --git a/distribution/src/main/assembly/dist.xml b/distribution/src/main/assembly/dist.xml index 08abb1d44f..b31d964158 100644 --- a/distribution/src/main/assembly/dist.xml +++ b/distribution/src/main/assembly/dist.xml @@ -42,7 +42,7 @@ dist/lib/optional - log4j:log4j + org.apache.logging.log4j:log4j-core joda-time:joda-time jakarta.persistence:jakarta.persistence-api org.jsoup:jsoup diff --git a/engine/pom.xml b/engine/pom.xml index 381f87910e..0a06195fc2 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -119,10 +119,16 @@ test - log4j - log4j + org.apache.logging.log4j + log4j-core test + + org.apache.logging.log4j + log4j-core + test + test-jar + org.easymock easymock diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ParameterMessageInterpolatorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ParameterMessageInterpolatorTest.java index 210fe9867b..9557f87236 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ParameterMessageInterpolatorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ParameterMessageInterpolatorTest.java @@ -9,6 +9,7 @@ import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; import static org.hibernate.validator.testutils.ValidatorUtil.getConfiguration; +import static org.testng.Assert.assertTrue; import java.util.Set; @@ -16,11 +17,13 @@ import javax.validation.Validator; import javax.validation.constraints.Size; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.Logger; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.test.appender.ListAppender; import org.hibernate.validator.messageinterpolation.ParameterMessageInterpolator; -import org.hibernate.validator.testutil.MessageLoggedAssertionLogger; import org.hibernate.validator.testutil.TestForIssue; - -import org.apache.log4j.Logger; +import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; @@ -34,14 +37,26 @@ public class ParameterMessageInterpolatorTest { Validator validator; + ListAppender listAppender; + @BeforeTest public void setUp() { + LoggerContext context = LoggerContext.getContext( false ); + Logger logger = context.getLogger( ParameterMessageInterpolator.class.getName() ); + listAppender = (ListAppender) logger.getAppenders().get( "List" ); + listAppender.clear(); + validator = getConfiguration() .messageInterpolator( new ParameterMessageInterpolator() ) .buildValidatorFactory() .getValidator(); } + @AfterTest + public void tearDown() { + listAppender.clear(); + } + @Test public void testParameterMessageInterpolatorInterpolatesParameters() { Foo foo = new Foo(); @@ -55,20 +70,17 @@ public void testParameterMessageInterpolatorInterpolatesParameters() { @Test public void testParameterMessageInterpolatorIgnoresELExpressions() { - Logger log4jRootLogger = Logger.getRootLogger(); - MessageLoggedAssertionLogger assertingLogger = new MessageLoggedAssertionLogger( "HV000185" ); - log4jRootLogger.addAppender( assertingLogger ); - Foo foo = new Foo(); Set> constraintViolations = validator.validateProperty( foo, "bar" ); assertThat( constraintViolations ).containsOnlyViolations( violationOf( Size.class ) .withProperty( "bar" ) - .withMessage( "${validatedValue}" ) - ); + .withMessage( "${validatedValue}" ) ); - assertingLogger.assertMessageLogged(); - log4jRootLogger.removeAppender( assertingLogger ); + assertTrue( listAppender.getEvents().stream() + .filter( event -> event.getLevel().equals( Level.WARN ) ) + .map( event -> event.getMessage().getFormattedMessage() ) + .anyMatch( m -> m.startsWith( "HV000185" ) ) ); } public static class Foo { diff --git a/engine/src/test/resources/log4j.properties b/engine/src/test/resources/log4j.properties deleted file mode 100644 index 78c71c612a..0000000000 --- a/engine/src/test/resources/log4j.properties +++ /dev/null @@ -1,26 +0,0 @@ -### direct log messages to stdout ### -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.Target=System.out -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n - -### direct messages to file hibernate.log ### -log4j.appender.file=org.apache.log4j.FileAppender -log4j.appender.file.File=hibernate.log -log4j.appender.file.layout=org.apache.log4j.PatternLayout -log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n - -### direct messages to socket - chainsaw ### -log4j.appender.socket=org.apache.log4j.net.SocketAppender -log4j.appender.socket.remoteHost=localhost -log4j.appender.socket.port=4560 -log4j.appender.socket.locationInfo=true - - -### set log levels - for more verbose logging change 'info' to 'debug' ### -log4j.rootLogger=info, stdout - -#log4j.logger.org.hibernate.validator.internal.engine.ValidatorImpl=trace -#log4j.logger.org.hibernate.validator.internal.engine.resolver.JPATraversableResolver=trace -#log4j.logger.org.hibernate.validatorengine.ConstraintTree=trace -#log4j.logger.org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator=info diff --git a/engine/src/test/resources/log4j2.properties b/engine/src/test/resources/log4j2.properties new file mode 100644 index 0000000000..3a80eeb2c1 --- /dev/null +++ b/engine/src/test/resources/log4j2.properties @@ -0,0 +1,22 @@ +# License: Apache License, Version 2.0 +# See the LICENSE file in the root directory or . + +status = error + +# Direct log messages to stdout +appender.console.type = Console +appender.console.name = console +appender.console.layout.type = PatternLayout +appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n + +appender.list.type = List +appender.list.name = List + +# Root logger option +rootLogger.level = info +rootLogger.appenderRef.console.ref = console + +# Specific loggers options +logger.parametermessageinterpolator.name = org.hibernate.validator.messageinterpolation.ParameterMessageInterpolator +logger.parametermessageinterpolator.level = info +logger.parametermessageinterpolator.appenderRef.list.ref = List \ No newline at end of file diff --git a/integration/pom.xml b/integration/pom.xml index a419e11300..e24b935250 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -47,11 +47,6 @@ rest-assured test - - log4j - log4j - test - ${project.groupId} hibernate-validator-test-utils diff --git a/integration/src/test/java/org/hibernate/validator/integration/wildfly/CustomValidationProviderInDeploymentUnitIT.java b/integration/src/test/java/org/hibernate/validator/integration/wildfly/CustomValidationProviderInDeploymentUnitIT.java index d71ed060d5..833d2021a0 100644 --- a/integration/src/test/java/org/hibernate/validator/integration/wildfly/CustomValidationProviderInDeploymentUnitIT.java +++ b/integration/src/test/java/org/hibernate/validator/integration/wildfly/CustomValidationProviderInDeploymentUnitIT.java @@ -12,7 +12,6 @@ import javax.validation.Validator; import javax.validation.ValidatorFactory; -import org.apache.log4j.Logger; import org.hibernate.validator.integration.AbstractArquillianIT; import org.hibernate.validator.integration.util.IntegrationTestUtil; import org.hibernate.validator.integration.util.MyValidator; @@ -31,7 +30,6 @@ public class CustomValidationProviderInDeploymentUnitIT extends AbstractArquillianIT { private static final String WAR_FILE_NAME = CustomValidationProviderInDeploymentUnitIT.class.getSimpleName() + ".war"; - private static final Logger log = Logger.getLogger( CustomValidationProviderInDeploymentUnitIT.class ); @Deployment public static Archive createTestArchive() { @@ -49,8 +47,6 @@ public static Archive createTestArchive() { @Test public void testValidatorFactoryFromCustomValidationProvider() throws Exception { - log.debug( "Running testValidatorFactoryFromCustomValidationProvider..." ); - Validator validator = validatorFactory.getValidator(); // Asserting the validator type as the VF is the wrapper type used within WildFly (LazyValidatorFactory) @@ -58,7 +54,5 @@ public void testValidatorFactoryFromCustomValidationProvider() throws Exception .as( "The custom validator implementation as retrieved from the default provider configured in META-INF/validation.xml should be used but actually " + validator + " is used" ) .isInstanceOf( MyValidator.class ); - - log.debug( "testValidatorFactoryFromCustomValidationProvider completed" ); } } diff --git a/integration/src/test/java/org/hibernate/validator/integration/wildfly/JndiLookupOfValidatorFactoryIT.java b/integration/src/test/java/org/hibernate/validator/integration/wildfly/JndiLookupOfValidatorFactoryIT.java index 785bc28747..d0881e6af4 100644 --- a/integration/src/test/java/org/hibernate/validator/integration/wildfly/JndiLookupOfValidatorFactoryIT.java +++ b/integration/src/test/java/org/hibernate/validator/integration/wildfly/JndiLookupOfValidatorFactoryIT.java @@ -14,7 +14,6 @@ import javax.naming.NamingException; import javax.validation.ValidatorFactory; -import org.apache.log4j.Logger; import org.hibernate.validator.integration.AbstractArquillianIT; import org.hibernate.validator.internal.engine.ValidatorImpl; import org.jboss.arquillian.container.test.api.Deployment; @@ -28,7 +27,6 @@ */ public class JndiLookupOfValidatorFactoryIT extends AbstractArquillianIT { private static final String WAR_FILE_NAME = JndiLookupOfValidatorFactoryIT.class.getSimpleName() + ".war"; - private static final Logger log = Logger.getLogger( JndiLookupOfValidatorFactoryIT.class ); private static final String DEFAULT_JNDI_NAME_OF_VALIDATOR_FACTORY = "java:comp/ValidatorFactory"; @Deployment @@ -38,7 +36,6 @@ public static Archive createTestArchive() { @Test public void testDefaultValidatorFactoryLookup() throws Exception { - log.debug( "Running testDefaultValidatorFactoryLookup..." ); try { Context ctx = new InitialContext(); Object obj = ctx.lookup( DEFAULT_JNDI_NAME_OF_VALIDATOR_FACTORY ); @@ -51,6 +48,5 @@ public void testDefaultValidatorFactoryLookup() throws Exception { catch (NamingException e) { fail( "The default validator factory should be bound" ); } - log.debug( "testDefaultValidatorFactoryLookup completed" ); } } diff --git a/integration/src/test/java/org/hibernate/validator/integration/wildfly/jpa/CustomValidatorFactoryInPersistenceUnitIT.java b/integration/src/test/java/org/hibernate/validator/integration/wildfly/jpa/CustomValidatorFactoryInPersistenceUnitIT.java index 7d28896f77..151d421ed6 100644 --- a/integration/src/test/java/org/hibernate/validator/integration/wildfly/jpa/CustomValidatorFactoryInPersistenceUnitIT.java +++ b/integration/src/test/java/org/hibernate/validator/integration/wildfly/jpa/CustomValidatorFactoryInPersistenceUnitIT.java @@ -12,7 +12,6 @@ import javax.inject.Inject; import javax.validation.ConstraintViolationException; -import org.apache.log4j.Logger; import org.hibernate.validator.integration.AbstractArquillianIT; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.shrinkwrap.api.Archive; @@ -32,7 +31,6 @@ public class CustomValidatorFactoryInPersistenceUnitIT extends AbstractArquillianIT { private static final String WAR_FILE_NAME = CustomValidatorFactoryInPersistenceUnitIT.class.getSimpleName() + ".war"; - private static final Logger log = Logger.getLogger( CustomValidatorFactoryInPersistenceUnitIT.class ); @Deployment public static Archive createTestArchive() { @@ -64,8 +62,6 @@ private static Asset persistenceXml() { @Test public void testValidatorFactoryPassedToPersistenceUnitIsCorrectlyConfigured() throws Exception { - log.debug( "Running testValidatorFactoryPassedToPersistenceUnitIsCorrectlyConfigured..." ); - try { magicianService.storeMagician(); fail( "Expected exception wasn't raised" ); @@ -79,8 +75,6 @@ public void testValidatorFactoryPassedToPersistenceUnitIsCorrectlyConfigured() t assertThat( constraintViolationException.getConstraintViolations().iterator().next().getMessage() ) .isEqualTo( "Invalid magician name" ); } - - log.debug( "testValidatorFactoryPassedToPersistenceUnitIsCorrectlyConfigured completed" ); } /** @@ -90,8 +84,6 @@ public void testValidatorFactoryPassedToPersistenceUnitIsCorrectlyConfigured() t // TODO How to make that work reliably also after a HV upgrade within WF? @Test public void testValidatorFactoryPassedToPersistenceUnitIsContributedFromPortableExtensionOfCurrentModuleZip() throws Exception { - log.debug( "Running testValidatorFactoryPassedToPersistenceUnitIsContributedFromPortableExtensionOfCurrentModuleZip..." ); - try { magicianService.storeWand(); fail( "Expected exception wasn't raised" ); @@ -105,8 +97,6 @@ public void testValidatorFactoryPassedToPersistenceUnitIsContributedFromPortable assertThat( constraintViolationException.getConstraintViolations().iterator().next().getMessage() ) .isEqualTo( "size must be between 5 and 2147483647" ); } - - log.debug( "testValidatorFactoryPassedToPersistenceUnitIsContributedFromPortableExtensionOfCurrentModuleZip completed" ); } private Throwable getRootException(Throwable throwable) { diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 0e8a32c067..f33b6978d6 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -149,8 +149,8 @@ test - org.slf4j - slf4j-log4j12 + org.apache.logging.log4j + log4j-slf4j-impl test diff --git a/pom.xml b/pom.xml index 5f58180378..9d0cc24b04 100644 --- a/pom.xml +++ b/pom.xml @@ -136,7 +136,7 @@ 1.8.3 2.9.7 1.7.22 - 1.2.17 + 2.13.3 2.2.3 + + idea.maven.embedder.version + + + + + + + maven-compiler-plugin + ${version.compiler.plugin} + + + -Aorg.jboss.logging.tools.addGeneratedAnnotation=false + + -parameters + + + + + + + From 1f02245434e785e7d6216f9d3037ac44f165c433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Fri, 2 Oct 2020 14:18:12 +0200 Subject: [PATCH 356/393] HV-1811 Upgrade to Bean Validation TCK 2.0.6 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9d4340ad97..775289021c 100644 --- a/pom.xml +++ b/pom.xml @@ -114,7 +114,7 @@ 2.0.2 - 2.0.5 + 2.0.6 2.8 3.0.3 From 9137187fc2ed153b319ee914a1f88a51183df82f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Wed, 30 Sep 2020 16:41:50 +0200 Subject: [PATCH 357/393] HV-1809 Upgrade to TestNG 6.14.3 Necessary to upgrade to Arquillian 1.6+, which depends on some methods that weren't defined in TestNG 6.8. Note we have to change AbstractMethodValidationTest to avoid calling assertEquals(someObject, aProxyForThisObject), because TestNG 6.14.3 actually calls someObject.equals(aProxyForThisObject) under the hood, and this obviously doesn't work unless equals is overridden. --- .../AbstractMethodValidationTest.java | 90 ++++++++++--------- .../AnnotationBasedMethodValidationTest.java | 4 +- pom.xml | 2 +- 3 files changed, 49 insertions(+), 47 deletions(-) diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/AbstractMethodValidationTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/AbstractMethodValidationTest.java index b0b5a21750..5ab2de4dd5 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/AbstractMethodValidationTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/AbstractMethodValidationTest.java @@ -52,7 +52,8 @@ */ @Test public abstract class AbstractMethodValidationTest { - protected CustomerRepository customerRepository; + protected CustomerRepository customerRepositoryOriginalBean; + protected CustomerRepository customerRepositoryValidatingProxy; protected RepositoryBase repositoryBase; protected Validator validator; @@ -61,16 +62,17 @@ public abstract class AbstractMethodValidationTest { protected abstract String messagePrefix(); protected void createProxy(Class... groups) { - customerRepository = getValidatingProxy( - new CustomerRepositoryImpl(), validator, groups + customerRepositoryOriginalBean = new CustomerRepositoryImpl(); + customerRepositoryValidatingProxy = getValidatingProxy( + customerRepositoryOriginalBean, validator, groups ); - repositoryBase = customerRepository; + repositoryBase = customerRepositoryValidatingProxy; } @Test public void methodValidationYieldsConstraintViolation() { try { - customerRepository.findCustomerByName( null ); + customerRepositoryValidatingProxy.findCustomerByName( null ); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -92,13 +94,13 @@ public void methodValidationYieldsConstraintViolation() { assertMethod( constraintViolation, "findCustomerByName", String.class ); assertParameterIndex( constraintViolation, 0 ); assertMethodValidationType( constraintViolation, ElementKind.PARAMETER ); - assertEquals( constraintViolation.getRootBean(), customerRepository ); + assertEquals( constraintViolation.getRootBean(), customerRepositoryOriginalBean ); assertEquals( constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class ); assertEquals( constraintViolation.getPropertyPath().toString(), "findCustomerByName.name" ); - assertEquals( constraintViolation.getLeafBean(), customerRepository ); + assertEquals( constraintViolation.getLeafBean(), customerRepositoryOriginalBean ); assertEquals( constraintViolation.getInvalidValue(), null ); assertEquals( constraintViolation.getExecutableParameters(), new Object[] { null } ); assertEquals( constraintViolation.getExecutableReturnValue(), null ); @@ -108,7 +110,7 @@ public void methodValidationYieldsConstraintViolation() { @Test public void validationOfMethodWithMultipleParameters() { try { - customerRepository.findCustomerByAgeAndName( 30, null ); + customerRepositoryValidatingProxy.findCustomerByAgeAndName( 30, null ); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -141,7 +143,7 @@ public void validationOfMethodWithMultipleParameters() { @Test public void constraintViolationsAtMultipleParameters() { try { - customerRepository.findCustomerByAgeAndName( 1, null ); + customerRepositoryValidatingProxy.findCustomerByAgeAndName( 1, null ); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -170,7 +172,7 @@ public void constraintViolationsAtMultipleParameters() { public void methodValidationWithCascadingParameter() { Customer customer = new Customer( null, null ); try { - customerRepository.persistCustomer( customer ); + customerRepositoryValidatingProxy.persistCustomer( customer ); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -195,7 +197,7 @@ public void methodValidationWithCascadingParameter() { constraintViolation.getPropertyPath().toString(), "persistCustomer.customer.name" ); assertEquals( constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class ); - assertEquals( constraintViolation.getRootBean(), customerRepository ); + assertEquals( constraintViolation.getRootBean(), customerRepositoryOriginalBean ); assertEquals( constraintViolation.getLeafBean(), customer ); assertEquals( constraintViolation.getInvalidValue(), null ); assertEquals( constraintViolation.getExecutableParameters(), new Object[] { customer } ); @@ -209,7 +211,7 @@ public void methodValidationWithCascadingParameterAndCascadingConstraint() { Customer customer = new Customer( "Bob", address ); try { - customerRepository.persistCustomer( customer ); + customerRepositoryValidatingProxy.persistCustomer( customer ); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -236,7 +238,7 @@ public void methodValidationWithCascadingParameterAndCascadingConstraint() { "persistCustomer.customer.address.city" ); assertEquals( constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class ); - assertEquals( constraintViolation.getRootBean(), customerRepository ); + assertEquals( constraintViolation.getRootBean(), customerRepositoryOriginalBean ); assertEquals( constraintViolation.getLeafBean(), address ); assertEquals( constraintViolation.getInvalidValue(), null ); assertEquals( constraintViolation.getExecutableParameters(), new Object[] { customer } ); @@ -251,7 +253,7 @@ public void cascadingMapParameter() { customers.put( "Bob", bob ); try { - customerRepository.cascadingMapParameter( customers ); + customerRepositoryValidatingProxy.cascadingMapParameter( customers ); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -277,7 +279,7 @@ public void cascadingMapParameter() { "cascadingMapParameter.customer[Bob].name" ); assertEquals( constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class ); - assertEquals( constraintViolation.getRootBean(), customerRepository ); + assertEquals( constraintViolation.getRootBean(), customerRepositoryOriginalBean ); assertEquals( constraintViolation.getLeafBean(), bob ); assertEquals( constraintViolation.getInvalidValue(), null ); assertEquals( constraintViolation.getExecutableParameters(), new Object[] { customers } ); @@ -291,7 +293,7 @@ public void cascadingIterableParameter() { List customers = Arrays.asList( null, customer ); try { - customerRepository.cascadingIterableParameter( customers ); + customerRepositoryValidatingProxy.cascadingIterableParameter( customers ); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -317,7 +319,7 @@ public void cascadingIterableParameter() { "cascadingIterableParameter.customer[1].name" ); assertEquals( constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class ); - assertEquals( constraintViolation.getRootBean(), customerRepository ); + assertEquals( constraintViolation.getRootBean(), customerRepositoryOriginalBean ); assertEquals( constraintViolation.getLeafBean(), customer ); assertEquals( constraintViolation.getInvalidValue(), null ); assertEquals( constraintViolation.getExecutableParameters(), new Object[] { customers } ); @@ -331,7 +333,7 @@ public void cascadingArrayParameter() { Customer customer = new Customer( null ); try { - customerRepository.cascadingArrayParameter( null, customer ); + customerRepositoryValidatingProxy.cascadingArrayParameter( null, customer ); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -357,7 +359,7 @@ public void cascadingArrayParameter() { "cascadingArrayParameter.customer[1].name" ); assertEquals( constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class ); - assertEquals( constraintViolation.getRootBean(), customerRepository ); + assertEquals( constraintViolation.getRootBean(), customerRepositoryOriginalBean ); assertEquals( constraintViolation.getLeafBean(), customer ); assertEquals( constraintViolation.getInvalidValue(), null ); assertEquals( @@ -371,7 +373,7 @@ public void cascadingArrayParameter() { @Test public void constraintsAtMethodFromBaseClassAreEvaluated() { try { - customerRepository.findById( null ); + customerRepositoryValidatingProxy.findById( null ); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -398,7 +400,7 @@ public void constraintsAtMethodFromBaseClassAreEvaluated() { @Test public void constraintsAtOverriddenMethodAreEvaluated() { try { - customerRepository.foo( null ); + customerRepositoryValidatingProxy.foo( null ); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -425,7 +427,7 @@ public void constraintsAtOverriddenMethodAreEvaluated() { @Test public void validFromOverriddenMethodIsEvaluated() { try { - customerRepository.bar( new Customer( null, null ) ); + customerRepositoryValidatingProxy.bar( new Customer( null, null ) ); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -453,13 +455,13 @@ public void validFromOverriddenMethodIsEvaluated() { @Test public void parameterValidationOfParameterlessMethod() { - customerRepository.boz(); + customerRepositoryValidatingProxy.boz(); } @Test public void returnValueValidationYieldsConstraintViolation() { try { - customerRepository.baz(); + customerRepositoryValidatingProxy.baz(); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -478,10 +480,10 @@ public void returnValueValidationYieldsConstraintViolation() { assertEquals( constraintViolation.getMessage(), messagePrefix() + "must be greater than or equal to 10" ); assertMethod( constraintViolation, "baz" ); assertMethodValidationType( constraintViolation, ElementKind.RETURN_VALUE ); - assertEquals( constraintViolation.getRootBean(), customerRepository ); + assertEquals( constraintViolation.getRootBean(), customerRepositoryOriginalBean ); assertEquals( constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class ); assertEquals( constraintViolation.getPropertyPath().toString(), "baz." ); - assertEquals( constraintViolation.getLeafBean(), customerRepository ); + assertEquals( constraintViolation.getLeafBean(), customerRepositoryOriginalBean ); assertEquals( constraintViolation.getInvalidValue(), 9 ); assertEquals( constraintViolation.getExecutableParameters(), null ); assertEquals( constraintViolation.getExecutableReturnValue(), 9 ); @@ -491,7 +493,7 @@ public void returnValueValidationYieldsConstraintViolation() { @Test public void cascadingReturnValue() { try { - customerRepository.cascadingReturnValue(); + customerRepositoryValidatingProxy.cascadingReturnValue(); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -510,7 +512,7 @@ public void cascadingReturnValue() { assertEquals( constraintViolation.getMessage(), messagePrefix() + "must not be null" ); assertMethod( constraintViolation, "cascadingReturnValue" ); assertMethodValidationType( constraintViolation, ElementKind.RETURN_VALUE ); - assertEquals( constraintViolation.getRootBean(), customerRepository ); + assertEquals( constraintViolation.getRootBean(), customerRepositoryOriginalBean ); assertEquals( constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class ); assertEquals( constraintViolation.getPropertyPath().toString(), @@ -526,7 +528,7 @@ public void cascadingReturnValue() { @Test public void cascadingReturnValueFromSuperType() { try { - customerRepository.overriddenMethodWithCascadingReturnValue(); + customerRepositoryValidatingProxy.overriddenMethodWithCascadingReturnValue(); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -546,7 +548,7 @@ public void cascadingReturnValueFromSuperType() { assertMethod( constraintViolation, "overriddenMethodWithCascadingReturnValue" ); assertMethodValidationType( constraintViolation, ElementKind.RETURN_VALUE ); - assertEquals( constraintViolation.getRootBean(), customerRepository ); + assertEquals( constraintViolation.getRootBean(), customerRepositoryOriginalBean ); assertEquals( constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class ); assertEquals( constraintViolation.getPropertyPath().toString(), @@ -562,7 +564,7 @@ public void cascadingReturnValueFromSuperType() { @Test public void cascadingIterableReturnValue() { try { - customerRepository.cascadingIterableReturnValue(); + customerRepositoryValidatingProxy.cascadingIterableReturnValue(); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -587,7 +589,7 @@ public void cascadingIterableReturnValue() { "cascadingIterableReturnValue.[1].name" ); assertEquals( constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class ); - assertEquals( constraintViolation.getRootBean(), customerRepository ); + assertEquals( constraintViolation.getRootBean(), customerRepositoryOriginalBean ); assertEquals( constraintViolation.getLeafBean(), new Customer( null ) ); assertEquals( constraintViolation.getInvalidValue(), null ); assertEquals( constraintViolation.getExecutableParameters(), null ); @@ -598,7 +600,7 @@ public void cascadingIterableReturnValue() { @Test public void cascadingMapReturnValue() { try { - customerRepository.cascadingMapReturnValue(); + customerRepositoryValidatingProxy.cascadingMapReturnValue(); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -627,7 +629,7 @@ public void cascadingMapReturnValue() { "cascadingMapReturnValue.[Bob].name" ); assertEquals( constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class ); - assertEquals( constraintViolation.getRootBean(), customerRepository ); + assertEquals( constraintViolation.getRootBean(), customerRepositoryOriginalBean ); assertEquals( constraintViolation.getLeafBean(), customer ); assertEquals( constraintViolation.getInvalidValue(), null ); assertEquals( constraintViolation.getExecutableParameters(), null ); @@ -638,7 +640,7 @@ public void cascadingMapReturnValue() { @Test public void cascadingArrayReturnValue() { try { - customerRepository.cascadingArrayReturnValue(); + customerRepositoryValidatingProxy.cascadingArrayReturnValue(); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -663,7 +665,7 @@ public void cascadingArrayReturnValue() { "cascadingArrayReturnValue.[1].name" ); assertEquals( constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class ); - assertEquals( constraintViolation.getRootBean(), customerRepository ); + assertEquals( constraintViolation.getRootBean(), customerRepositoryOriginalBean ); assertEquals( constraintViolation.getLeafBean(), new Customer( null ) ); assertEquals( constraintViolation.getInvalidValue(), null ); assertEquals( constraintViolation.getExecutableParameters(), null ); @@ -674,7 +676,7 @@ public void cascadingArrayReturnValue() { @Test public void overridingMethodStrengthensReturnValueConstraint() { try { - customerRepository.overriddenMethodWithReturnValueConstraint(); + customerRepositoryValidatingProxy.overriddenMethodWithReturnValueConstraint(); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -729,13 +731,13 @@ public void runtimeTypeDefinesConstraintsToApply() { @Test public void methodValidationSucceedsAsNoConstraintOfValidatedGroupAreViolated() { - customerRepository.parameterConstraintInGroup( null ); + customerRepositoryValidatingProxy.parameterConstraintInGroup( null ); } @Test(expectedExceptions = ConstraintViolationException.class) public void methodValidationFailsAsConstraintOfValidatedGroupIsViolated() { createProxy( CustomerRepository.ValidationGroup.class ); - customerRepository.parameterConstraintInGroup( null ); + customerRepositoryValidatingProxy.parameterConstraintInGroup( null ); } @Test(expectedExceptions = ConstraintDeclarationException.class, expectedExceptionsMessageRegExp = "HV000132.*") @@ -750,7 +752,7 @@ public void voidMethodWithReturnValueConstraintCausesConstraintDeclarationExcept @TestForIssue(jiraKey = "HV-601") @Test(expectedExceptions = ConstraintViolationException.class) public void shouldValidateGetterLikeNamedMethodWithParameter() { - customerRepository.getFoo( "" ); + customerRepositoryValidatingProxy.getFoo( "" ); } @Test @@ -761,7 +763,7 @@ public void validationOfCrossParameterConstraint() { try { //when - customerRepository.methodWithCrossParameterConstraint( startDate, endDate ); + customerRepositoryValidatingProxy.methodWithCrossParameterConstraint( startDate, endDate ); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -778,8 +780,8 @@ public void validationOfCrossParameterConstraint() { ConstraintViolation constraintViolation = e.getConstraintViolations().iterator().next(); assertEquals( constraintViolation.getConstraintDescriptor().getAnnotation().annotationType(), ConsistentDateParameters.class ); assertEquals( constraintViolation.getInvalidValue(), new Object[] { startDate, endDate } ); - assertEquals( constraintViolation.getLeafBean(), customerRepository ); - assertEquals( constraintViolation.getRootBean(), customerRepository ); + assertEquals( constraintViolation.getLeafBean(), customerRepositoryOriginalBean ); + assertEquals( constraintViolation.getRootBean(), customerRepositoryOriginalBean ); assertEquals( constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class ); assertEquals( constraintViolation.getExecutableParameters(), new Object[] { startDate, endDate } ); assertEquals( constraintViolation.getExecutableReturnValue(), null ); @@ -795,7 +797,7 @@ public void validationOfCrossParameterConstraint() { @Test public void methodValidationSucceeds() { - customerRepository.findCustomerByName( "Bob" ); + customerRepositoryValidatingProxy.findCustomerByName( "Bob" ); } protected void assertMethod(ConstraintViolation constraintViolation, String methodName, Class... parameterTypes) { diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/AnnotationBasedMethodValidationTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/AnnotationBasedMethodValidationTest.java index 4e4575e3d1..a700db52d6 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/AnnotationBasedMethodValidationTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/AnnotationBasedMethodValidationTest.java @@ -46,7 +46,7 @@ public void iterableParameterWithCascadingTypeParameter() { List customers = Arrays.asList( null, customer ); try { - customerRepository.iterableParameterWithCascadingTypeParameter( customers ); + customerRepositoryValidatingProxy.iterableParameterWithCascadingTypeParameter( customers ); fail( "Expected ConstraintViolationException wasn't thrown." ); } catch (ConstraintViolationException e) { @@ -62,7 +62,7 @@ public void iterableParameterWithCascadingTypeParameter() { "iterableParameterWithCascadingTypeParameter.customer[1].name" ); assertEquals( constraintViolation.getRootBeanClass(), CustomerRepositoryImpl.class ); - assertEquals( constraintViolation.getRootBean(), customerRepository ); + assertEquals( constraintViolation.getRootBean(), customerRepositoryOriginalBean ); assertEquals( constraintViolation.getLeafBean(), customer ); assertEquals( constraintViolation.getInvalidValue(), null ); assertEquals( constraintViolation.getExecutableParameters(), new Object[] { customers } ); diff --git a/pom.xml b/pom.xml index 775289021c..b115aa16e3 100644 --- a/pom.xml +++ b/pom.xml @@ -164,7 +164,7 @@ 1.1.11.Final - 6.8 + 6.14.3 3.8.0 4.12 From bef4601643235041905eb6404fe2a744d7affda3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Thu, 1 Oct 2020 09:42:46 +0200 Subject: [PATCH 358/393] HV-1809 Fix the Security Manager policy following the TestNG upgrade --- tck-runner/src/test/resources/test.policy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tck-runner/src/test/resources/test.policy b/tck-runner/src/test/resources/test.policy index aae5f1c2d1..5f9136f89d 100644 --- a/tck-runner/src/test/resources/test.policy +++ b/tck-runner/src/test/resources/test.policy @@ -80,11 +80,13 @@ grant codeBase "file:${localRepository}/org/hibernate/beanvalidation/tck/-" { // Ideally, this domain should have no permissions at all; Only specifically enabling some API calls done by the BV TCK // tests (which do not use privileged actions for these) +// and by TestNG (which does not use privileged actions either). grant codeBase "file:${project.build.directory}/classes" { permission java.util.PropertyPermission "validation.provider", "read"; permission java.io.FilePermission "${localRepository}/org/hibernate/beanvalidation/tck/beanvalidation-tck-tests/${version.org.hibernate.beanvalidation.tck}/beanvalidation-tck-tests-${version.org.hibernate.beanvalidation.tck}.jar", "read"; permission java.util.PropertyPermission "user.language", "write"; permission org.hibernate.validator.HibernateValidatorPermission "accessPrivateMembers"; + permission "java.lang.reflect.ReflectPermission" "suppressAccessChecks"; }; grant codeBase "file:${project.build.directory}/test-classes" { From 0e878cdf3240ebd4fd0aa8aba1a9cfc27ffa84ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Thu, 1 Oct 2020 09:44:31 +0200 Subject: [PATCH 359/393] HV-1809 Disable parallel test execution in the tck-runner following the TestNG upgrade There seem to be problems with running tests in parallel with TestNG 6.14: we end up with archive content being mixed between threads, which leads to really cryptic errors in the SecurityManager (because we try to load a resource when we shouldn't have... ?). Anyway, the tests don't take that long to execute, so let's avoid this source of errors? --- tck-runner/pom.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index d27f85b21b..a72ad252de 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -156,8 +156,6 @@ ${validation.provider} - methods - 4 From d8185504fa66e27b675b011afe9b93e9ded4664f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Wed, 30 Sep 2020 16:41:50 +0200 Subject: [PATCH 360/393] HV-1810 Upgrade to Arquillian 1.6.0.Final To upgrade Shrinkwrap, which apparently doesn't work well with non-default local Maven repos in older versions. --- pom.xml | 2 +- .../LocalSecurityManagerTestingExecutionEvent.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b115aa16e3..ee84f5488a 100644 --- a/pom.xml +++ b/pom.xml @@ -163,7 +163,7 @@ 11.0.2 - 1.1.11.Final + 1.6.0.Final 6.14.3 3.8.0 diff --git a/tck-runner/src/test/java/org/hibernate/validator/tckrunner/securitymanager/arquillian/LocalSecurityManagerTestingExecutionEvent.java b/tck-runner/src/test/java/org/hibernate/validator/tckrunner/securitymanager/arquillian/LocalSecurityManagerTestingExecutionEvent.java index 85c408df9d..13fb09a2fc 100644 --- a/tck-runner/src/test/java/org/hibernate/validator/tckrunner/securitymanager/arquillian/LocalSecurityManagerTestingExecutionEvent.java +++ b/tck-runner/src/test/java/org/hibernate/validator/tckrunner/securitymanager/arquillian/LocalSecurityManagerTestingExecutionEvent.java @@ -39,6 +39,11 @@ public DelegatingTestMethodExecutor(TestMethodExecutor delegate) { this.delegate = new DelegatingExecutor( new ArquillianExecutor( delegate ) ); } + @Override + public String getMethodName() { + return method.getName(); + } + @Override public Method getMethod() { return method; From 11696b8f484e58f2c064149994bc6fc35f88a62c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Thu, 1 Oct 2020 09:40:40 +0200 Subject: [PATCH 361/393] HV-1810 Upgrade to payara-arquillian 2.3.1 The upgrade is necessary to upgrade to Arquillian 1.6. --- osgi/felixtest/pom.xml | 2 +- pom.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 4dcf57b60b..0241c45e99 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -75,7 +75,7 @@ fish.payara.arquillian - arquillian-payara-server-4-managed + arquillian-payara-server-managed ${version.fish.payara.arquillian} test diff --git a/pom.xml b/pom.xml index ee84f5488a..abcb3b66a4 100644 --- a/pom.xml +++ b/pom.xml @@ -183,8 +183,8 @@ 4.12.0 2.5.2 6.0.0 - 5.181 - 1.0.Beta3 + 5.2020.2 + 2.3.1 4.2.0 4.12.0 - 2.5.2 + 2.5.4 6.0.0 5.2020.2 2.3.1 From d23bdaf4297ec59855db111d49f51d4210cfa98a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 29 Sep 2020 13:02:00 +0200 Subject: [PATCH 364/393] HV-1806 Make sure Karaf-based tests use the same local Maven repository as the Maven build Otherwise, when the Maven local repository of the Maven build isn't the default one, Pax-Exam ends up not finding OSGi artifacts we just built. --- osgi/integrationtest/pom.xml | 1 + .../KarafFeaturesAreInstallableTest.java | 21 +++++++++++++++++++ .../integrationtest/OsgiIntegrationTest.java | 21 +++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 6879324f83..68ecd4ef18 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -181,6 +181,7 @@ false + ${settings.localRepository} ${mavencentral.repo.url} diff --git a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/KarafFeaturesAreInstallableTest.java b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/KarafFeaturesAreInstallableTest.java index 235b2cd904..4931ca3fca 100644 --- a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/KarafFeaturesAreInstallableTest.java +++ b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/KarafFeaturesAreInstallableTest.java @@ -67,6 +67,7 @@ public Option[] config() { .type( "xml" ) .versionAsInProject(); + String mavenLocalRepository = System.getProperty( "maven.settings.localRepository" ); String mavenCentralRepository = System.getProperty( "maven.mavencentral.repo.url" ); return options( @@ -94,6 +95,26 @@ public Option[] config() { "featuresBoot", "system" ), + /* + * Use the same local Maven repository as the build job. + * This allows to retrieve the just-installed artifacts in case + * the local repo was overridden from the command line. + * + * See https://ops4j1.jira.com/wiki/spaces/paxurl/pages/3833866/Mvn+Protocol for more information + * on the configuration below. + */ + editConfigurationFilePut( + "etc/org.ops4j.pax.url.mvn.cfg", + "org.ops4j.pax.url.mvn.defaultRepositories", + "file://" + mavenLocalRepository + + "@snapshots" + + "@id=local-repo-from-maven-settings" + ), + editConfigurationFilePut( + "etc/org.ops4j.pax.url.mvn.cfg", + "org.ops4j.pax.url.mvn.localRepository", + mavenLocalRepository + ), editConfigurationFilePut( // Erase the defaults: Maven Central uses HTTP by default... "etc/org.ops4j.pax.url.mvn.cfg", "org.ops4j.pax.url.mvn.repositories", diff --git a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java index f599e54c11..e65b1f3b3d 100644 --- a/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java +++ b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/OsgiIntegrationTest.java @@ -90,6 +90,7 @@ public Option[] config() { .type( "xml" ) .versionAsInProject(); + String mavenLocalRepository = System.getProperty( "maven.settings.localRepository" ); String mavenCentralRepository = System.getProperty( "maven.mavencentral.repo.url" ); return options( @@ -117,6 +118,26 @@ public Option[] config() { "featuresBoot", "system" ), + /* + * Use the same local Maven repository as the build job. + * This allows to retrieve the just-installed artifacts in case + * the local repo was overridden from the command line. + * + * See https://ops4j1.jira.com/wiki/spaces/paxurl/pages/3833866/Mvn+Protocol for more information + * on the configuration below. + */ + editConfigurationFilePut( + "etc/org.ops4j.pax.url.mvn.cfg", + "org.ops4j.pax.url.mvn.defaultRepositories", + "file://" + mavenLocalRepository + + "@snapshots" + + "@id=local-repo-from-maven-settings" + ), + editConfigurationFilePut( + "etc/org.ops4j.pax.url.mvn.cfg", + "org.ops4j.pax.url.mvn.localRepository", + mavenLocalRepository + ), editConfigurationFilePut( // Erase the defaults: Maven Central uses HTTP by default... "etc/org.ops4j.pax.url.mvn.cfg", "org.ops4j.pax.url.mvn.repositories", From 66966c7342eb501b1329ee5890d120f767d7ae0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 29 Sep 2020 17:50:21 +0200 Subject: [PATCH 365/393] HV-1806 Make sure that Shrinkwrap-based tests use the same local Maven repository as the Maven build Otherwise, when the Maven local repository of the Maven build isn't the default one, Shrinkwrap may end up not finding artifacts we already downloaded. --- pom.xml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index b42f4d0260..1f0719861e 100644 --- a/pom.xml +++ b/pom.xml @@ -279,8 +279,16 @@ - ${surefire.jvm.args.additional} ${surefire.jvm.args.add-opens} ${surefire.jvm.args.illegal-access} - ${surefire.jvm.args.additional} ${surefire.jvm.args.add-opens} ${surefire.jvm.args.illegal-access} + + + -Dmaven.repo.local=${settings.localRepository} + + ${surefire.jvm.args.additional} ${surefire.jvm.args.add-opens} ${surefire.jvm.args.illegal-access} ${surefire.jvm.args.shrinkwrap} + ${surefire.jvm.args.additional} ${surefire.jvm.args.add-opens} ${surefire.jvm.args.illegal-access} ${surefire.jvm.args.shrinkwrap} From cd42a5a8ca8049582bf6db539b599453b3851f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Thu, 1 Oct 2020 11:26:14 +0200 Subject: [PATCH 366/393] HV-1805 Add suffixes to test reports to more easily distinguish between multiple executions of the same test in the same Jenkins job --- pom.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pom.xml b/pom.xml index 1f0719861e..d9885ad777 100644 --- a/pom.xml +++ b/pom.xml @@ -290,6 +290,13 @@ ${surefire.jvm.args.additional} ${surefire.jvm.args.add-opens} ${surefire.jvm.args.illegal-access} ${surefire.jvm.args.shrinkwrap} ${surefire.jvm.args.additional} ${surefire.jvm.args.add-opens} ${surefire.jvm.args.illegal-access} ${surefire.jvm.args.shrinkwrap} + + default + ${arquillian.wildfly.jvm.args.add-opens} ${arquillian.wildfly.jvm.args.add-modules} @@ -794,6 +801,7 @@ **/*Test.java ${surefire.jvm.args} + ${surefire.environment} @@ -818,6 +826,7 @@ ${version.failsafe.plugin} ${failsafe.jvm.args} + ${surefire.environment} From 70687f3da83bc20f0852d7480ac8bbbb1371a5af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Mon, 28 Sep 2020 14:39:30 +0200 Subject: [PATCH 367/393] HV-1805 Copy and adapt Jenkinsfile from Hibernate Search --- Jenkinsfile | 542 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 542 insertions(+) create mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000000..d24690360d --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,542 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ + +import groovy.transform.Field + +/* + * See https://github.com/hibernate/hibernate-jenkins-pipeline-helpers + */ +@Library('hibernate-jenkins-pipeline-helpers@1.3') +import org.hibernate.jenkins.pipeline.helpers.job.JobHelper +import org.hibernate.jenkins.pipeline.helpers.alternative.AlternativeMultiMap +import org.hibernate.jenkins.pipeline.helpers.version.Version + +/* + * WARNING: DO NOT IMPORT LOCAL LIBRARIES HERE. + * + * By local, I mean libraries whose files are in the same Git repository. + * + * The Jenkinsfile is protected and will not be executed if modified in pull requests from external users, + * but other local library files are not protected. + * A user could potentially craft a malicious PR by modifying a local library. + * + * See https://blog.grdryn.me/blog/jenkins-pipeline-trust.html for a full explanation, + * and a potential solution if we really need local libraries. + * Alternatively we might be able to host libraries in a separate GitHub repo and configure + * them in the GUI: see https://ci.hibernate.org/job/hibernate-validator/configure, "Pipeline Libraries". + */ + +/* + * See https://github.com/hibernate/hibernate-jenkins-pipeline-helpers for the documentation + * of the helpers library used in this Jenkinsfile, + * and for help writing Jenkinsfiles. + * + * ### Jenkins configuration + * + * #### Jenkins plugins + * + * This file requires the following plugins in particular: + * + * - everything required by the helpers library (see the org.hibernate.(...) imports for a link to its documentation) + * - https://plugins.jenkins.io/pipeline-github for the trigger on pull request comments + * + * #### Script approval + * + * If not already done, you will need to allow the following calls in /scriptApproval/: + * + * - everything required by the helpers library (see the org.hibernate.(...) imports for a link to its documentation) + * + * ### Integrations + * + * #### Nexus deployment + * + * This job includes two deployment modes: + * + * - A deployment of snapshot artifacts for every non-PR build on "primary" branches (master and maintenance branches). + * - A full release when starting the job with specific parameters. + * + * In the first case, the name of a Maven settings file must be provided in the job configuration file + * (see below). + * + * #### Gitter (optional) + * + * You need to enable the Jenkins integration in your Gitter room first: + * see https://gitlab.com/gitlab-org/gitter/webapp/blob/master/docs/integrations.md + * + * Then you will also need to configure *global* secret text credentials containing the Gitter webhook URL, + * and list the ID of these credentials in the job configuration file + * (see https://github.com/hibernate/hibernate-jenkins-pipeline-helpers#job-configuration-file). + * + * ### Job configuration + * + * This Jenkinsfile gets its configuration from four sources: + * branch name, environment variables, a configuration file, and credentials. + * All configuration is optional for the default build (and it should stay that way), + * but some features require some configuration. + * + * #### Branch name + * + * See the org.hibernate.(...) imports for a link to the helpers library documentation, + * which explains the basics. + * + * #### Environment variables + * + * No particular environment variables is necessary. + * + * #### Job configuration file + * + * See the org.hibernate.(...) imports for a link to the helpers library documentation, + * which explains the basic structure of this file and how to set it up. + * + * Below is the additional structure specific to this Jenkinsfile: + * + * deployment: + * maven: + * # String containing the ID of a Maven settings file registered using the config-file-provider Jenkins plugin. + * # The settings must provide credentials to the servers with ID + * # 'jboss-releases-repository' and 'jboss-snapshots-repository'. + * settingsId: ... + */ + +@Field final String MAVEN_TOOL = 'Apache Maven 3.6' + +// Default node pattern, to be used for resource-intensive stages. +// Should not include the master node. +@Field final String NODE_PATTERN_BASE = 'Slave' +// Quick-use node pattern, to be used for very light, quick, and environment-independent stages, +// such as sending a notification. May include the master node in particular. +@Field final String QUICK_USE_NODE_PATTERN = 'Master||Slave' + +@Field AlternativeMultiMap environments +@Field JobHelper helper + +@Field boolean enableDefaultBuild = false +@Field boolean enableDefaultBuildIT = false +@Field boolean performRelease = false +@Field boolean deploySnapshot = false + +@Field Version releaseVersion +@Field Version afterReleaseDevelopmentVersion + +this.helper = new JobHelper(this) + +helper.runWithNotification { + +stage('Configure') { + this.environments = AlternativeMultiMap.create([ + jdk: [ + // This should not include every JDK; in particular let's not care too much about EOL'd JDKs like version 9 + // See http://www.oracle.com/technetwork/java/javase/eol-135779.html + new JdkBuildEnvironment(version: '8', buildJdkTool: 'OracleJDK8 Latest', + condition: TestCondition.BEFORE_MERGE, + isDefault: true), + new JdkBuildEnvironment(version: '11', buildJdkTool: 'OpenJDK 11 Latest', + condition: TestCondition.AFTER_MERGE), + new JdkBuildEnvironment(version: '14', buildJdkTool: 'OpenJDK 14 Latest', + condition: TestCondition.AFTER_MERGE), + new JdkBuildEnvironment(version: '15', buildJdkTool: 'OpenJDK 15 Latest', + condition: TestCondition.AFTER_MERGE), + new JdkBuildEnvironment(version: '16', buildJdkTool: 'OpenJDK 16 Latest', + condition: TestCondition.AFTER_MERGE) + ] + ]) + + helper.configure { + configurationNodePattern QUICK_USE_NODE_PATTERN + file 'job-configuration.yaml' + jdk { + defaultTool environments.content.jdk.default.buildJdkTool + } + maven { + defaultTool MAVEN_TOOL + producedArtifactPattern "org/hibernate/validator/*" + // Relocation artifacts + producedArtifactPattern "org/hibernate/hibernate-validator*" + } + } + + properties([ + buildDiscarder( + logRotator(daysToKeepStr: '90') + ), + pipelineTriggers( + // HSEARCH-3417: do not add snapshotDependencies() here, this was known to cause problems. + [ + issueCommentTrigger('.*test this please.*') + ] + + helper.generateUpstreamTriggers() + ), + helper.generateNotificationProperty(), + parameters([ + choice( + name: 'ENVIRONMENT_SET', + choices: """AUTOMATIC +DEFAULT +SUPPORTED +ALL""", + description: """A set of environments that must be checked. +'AUTOMATIC' picks a different set of environments based on the branch name and whether a release is being performed. +'DEFAULT' means a single build with the default environment expected by the Maven configuration, +while other options will trigger multiple Maven executions in different environments.""" + ), + string( + name: 'ENVIRONMENT_FILTER', + defaultValue: '', + trim: true, + description: """A regex filter to apply to the environments that must be checked. +If this parameter is non-empty, ENVIRONMENT_SET will be ignored and environments whose tag matches the given regex will be checked. +Some useful filters: 'default', 'jdk', 'jdk-10', 'eclipse'. +""" + ), + string( + name: 'RELEASE_VERSION', + defaultValue: '', + description: 'The version to be released, e.g. 5.10.0.Final. Setting this triggers a release.', + trim: true + ), + string( + name: 'RELEASE_DEVELOPMENT_VERSION', + defaultValue: '', + description: 'The next version to be used after the release, e.g. 5.10.0-SNAPSHOT.', + trim: true + ), + booleanParam( + name: 'RELEASE_DRY_RUN', + defaultValue: false, + description: 'If true, just simulate the release, without pushing any commits or tags, and without uploading any artifacts or documentation.' + ) + ]) + ]) + + performRelease = (params.RELEASE_VERSION ? true : false) + + if (!performRelease && helper.scmSource.branch.primary && !helper.scmSource.pullRequest) { + if (helper.configuration.file?.deployment?.maven?.settingsId) { + deploySnapshot = true + } + else { + echo "Missing deployment configuration in job configuration file - snapshot deployment will be skipped." + } + } + + if (params.ENVIRONMENT_FILTER) { + keepOnlyEnvironmentsMatchingFilter(params.ENVIRONMENT_FILTER) + } + else { + keepOnlyEnvironmentsFromSet(params.ENVIRONMENT_SET) + } + + // Determine whether ITs need to be run in the default build + enableDefaultBuildIT = environments.content.any { key, envSet -> + return envSet.enabled.contains(envSet.default) + } + // No need to re-test default environments separately, they will be tested as part of the default build if needed + environments.content.each { key, envSet -> + envSet.enabled.remove(envSet.default) + } + + if ( enableDefaultBuildIT && params.LEGACY_IT ) { + echo "Enabling legacy integration tests in default environment due to explicit request" + enableDefaultBuildLegacyIT = true + } + + enableDefaultBuild = + enableDefaultBuildIT || + environments.content.any { key, envSet -> envSet.enabled.any { buildEnv -> buildEnv.requiresDefaultBuildArtifacts() } } || + deploySnapshot + + echo """Branch: ${helper.scmSource.branch.name} +PR: ${helper.scmSource.pullRequest?.id} +params.ENVIRONMENT_SET: ${params.ENVIRONMENT_SET} +params.ENVIRONMENT_FILTER: ${params.ENVIRONMENT_FILTER} + +Resulting execution plan: + enableDefaultBuild=$enableDefaultBuild + enableDefaultBuildIT=$enableDefaultBuildIT + environments=${environments.enabledAsString} + performRelease=$performRelease + deploySnapshot=$deploySnapshot +""" + + if (performRelease) { + releaseVersion = Version.parseReleaseVersion(params.RELEASE_VERSION) + echo "Inferred version family for the release to '$releaseVersion.family'" + + // Check that all the necessary parameters are set + if (!params.RELEASE_DEVELOPMENT_VERSION) { + throw new IllegalArgumentException( + "Missing value for parameter RELEASE_DEVELOPMENT_VERSION." + + " This parameter must be set when RELEASE_VERSION is set." + ) + } + if (!params.RELEASE_DRY_RUN && !helper.configuration.file?.deployment?.maven?.settingsId) { + throw new IllegalArgumentException( + "Missing deployment configuration in job configuration file." + + " Cannot deploy artifacts during the release." + ) + } + } + + if (params.RELEASE_DEVELOPMENT_VERSION) { + afterReleaseDevelopmentVersion = Version.parseDevelopmentVersion(params.RELEASE_DEVELOPMENT_VERSION) + } +} + +stage('Default build') { + if (!enableDefaultBuild) { + echo 'Skipping default build and integration tests in the default environment' + helper.markStageSkipped() + return + } + runBuildOnNode { + helper.withMavenWorkspace(mavenSettingsConfig: deploySnapshot ? helper.configuration.file.deployment.maven.settingsId : null) { + sh """ \ + mvn clean \ + --fail-at-end \ + ${deploySnapshot ? "\ + deploy \ + " : "\ + install \ + "} \ + -Pdist \ + ${enableDefaultBuildIT ? '' : '-DskipITs'} \ + ${toTestJdkArg(environments.content.jdk.default)} \ + """ + + dir(helper.configuration.maven.localRepositoryPath) { + stash name:'default-build-result', includes:"org/hibernate/validator/**" + } + } + } +} + +stage('Non-default environments') { + Map executions = [:] + + // Test with multiple JDKs + environments.content.jdk.enabled.each { JdkBuildEnvironment buildEnv -> + executions.put(buildEnv.tag, { + runBuildOnNode { + helper.withMavenWorkspace(jdk: buildEnv.buildJdkTool) { + mavenNonDefaultBuild buildEnv, """ \ + clean install \ + """ + } + } + }) + } + + if (executions.isEmpty()) { + echo 'Skipping builds in non-default environments' + helper.markStageSkipped() + } + else { + parallel(executions) + } +} + +stage('Deploy') { + if (deploySnapshot) { + // TODO delay the release to this stage? This would require to use staging repositories for snapshots, not sure it's possible. + echo "Already deployed snapshot as part of the 'Default build' stage." + } + else if (performRelease) { + echo "Performing full release for version ${releaseVersion.toString()}" + runBuildOnNode { + helper.withMavenWorkspace(mavenSettingsConfig: params.RELEASE_DRY_RUN ? null : helper.configuration.file.deployment.maven.settingsId) { + sh "git clone https://github.com/hibernate/hibernate-noorm-release-scripts.git" + sh "bash -xe hibernate-noorm-release-scripts/prepare-release.sh validator ${releaseVersion.toString()}" + + String deployCommand = "bash -xe hibernate-noorm-release-scripts/deploy.sh validator" + if (!params.RELEASE_DRY_RUN) { + sh deployCommand + } else { + echo "WARNING: Not deploying. Would have executed:" + echo deployCommand + } + + String uploadDistributionCommand = "bash -xe hibernate-noorm-release-scripts/upload-distribution.sh validator ${releaseVersion.toString()}" + String uploadDocumentationCommand = "bash -xe hibernate-noorm-release-scripts/upload-documentation.sh validator ${releaseVersion.toString()} ${releaseVersion.family}" + if (!params.RELEASE_DRY_RUN) { + sh uploadDistributionCommand + sh uploadDocumentationCommand + } + else { + echo "WARNING: Not uploading anything. Would have executed:" + echo uploadDistributionCommand + echo uploadDocumentationCommand + } + + sh "bash -xe hibernate-noorm-release-scripts/update-version.sh validator ${afterReleaseDevelopmentVersion.toString()}" + sh "bash -xe hibernate-noorm-release-scripts/push-upstream.sh validator ${releaseVersion.toString()} ${helper.scmSource.branch.name} ${!params.RELEASE_DRY_RUN}" + } + } + } + else { + echo "Skipping deployment" + helper.markStageSkipped() + return + } +} + +} // End of helper.runWithNotification + +// Job-specific helpers + +enum TestCondition { + // For environments that are expected to work correctly + // before merging into master or maintenance branches. + // Tested on master and maintenance branches, on feature branches, and for PRs. + BEFORE_MERGE, + // For environments that are expected to work correctly, + // but are considered too resource-intensive to test them on pull requests. + // Tested on master and maintenance branches only. + // Not tested on feature branches or PRs. + AFTER_MERGE, + // For environments that may not work correctly. + // Only tested when explicitly requested through job parameters. + ON_DEMAND; + + // Work around JENKINS-33023 + // See https://issues.jenkins-ci.org/browse/JENKINS-33023?focusedCommentId=325738&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-325738 + public TestCondition() {} +} + +abstract class BuildEnvironment { + boolean isDefault = false + TestCondition condition + String toString() { getTag() } + abstract String getTag() + boolean isDefault() { isDefault } + boolean requiresDefaultBuildArtifacts() { true } +} + +class JdkBuildEnvironment extends BuildEnvironment { + String version + String buildJdkTool + String testJdkTool + @Override + String getTag() { "jdk-$version" } + @Override + boolean requiresDefaultBuildArtifacts() { false } +} + +void keepOnlyEnvironmentsMatchingFilter(String regex) { + def pattern = /$regex/ + + boolean enableDefault = ('default' =~ pattern) + + environments.content.each { key, envSet -> + envSet.enabled.removeAll { buildEnv -> + !(buildEnv.tag =~ pattern) && !(envSet.default == buildEnv && enableDefault) + } + } +} + +void keepOnlyEnvironmentsFromSet(String environmentSetName) { + boolean enableDefaultEnv = false + boolean enableBeforeMergeEnvs = false + boolean enableAfterMergeEnvs = false + boolean enableOnDemandEnvs = false + switch (environmentSetName) { + case 'DEFAULT': + enableDefaultEnv = true + break + case 'SUPPORTED': + enableDefaultEnv = true + enableBeforeMergeEnvs = true + enableAfterMergeEnvs = true + break + case 'ALL': + enableDefaultEnv = true + enableBeforeMergeEnvs = true + enableAfterMergeEnvs = true + enableOptional = true + break + case 'AUTOMATIC': + if (params.RELEASE_VERSION) { + echo "Releasing version '$params.RELEASE_VERSION'." + } else if (helper.scmSource.pullRequest) { + echo "Building pull request '$helper.scmSource.pullRequest.id'" + enableDefaultEnv = true + enableBeforeMergeEnvs = true + } else if (helper.scmSource.branch.primary) { + echo "Building primary branch '$helper.scmSource.branch.name'" + enableDefaultEnv = true + enableBeforeMergeEnvs = true + enableAfterMergeEnvs = true + echo "Legacy integration tests are enabled for the default build environment." + enableDefaultBuildLegacyIT = true + } else { + echo "Building feature branch '$helper.scmSource.branch.name'" + enableDefaultEnv = true + enableBeforeMergeEnvs = true + } + break + default: + throw new IllegalArgumentException( + "Unknown value for param 'ENVIRONMENT_SET': '$environmentSetName'." + ) + } + + // Filter environments + + environments.content.each { key, envSet -> + envSet.enabled.removeAll { buildEnv -> ! ( + enableDefaultEnv && buildEnv.isDefault || + enableBeforeMergeEnvs && buildEnv.condition == TestCondition.BEFORE_MERGE || + enableAfterMergeEnvs && buildEnv.condition == TestCondition.AFTER_MERGE || + enableOnDemandEnvs && buildEnv.condition == TestCondition.ON_DEMAND ) } + } +} + +void runBuildOnNode(Closure body) { + runBuildOnNode( NODE_PATTERN_BASE, body ) +} + +void runBuildOnNode(String label, Closure body) { + node( label ) { + timeout( [time: 1, unit: 'HOURS'], body ) + } +} + +void mavenNonDefaultBuild(BuildEnvironment buildEnv, String args, String projectPath = '.') { + if ( buildEnv.requiresDefaultBuildArtifacts() ) { + dir(helper.configuration.maven.localRepositoryPath) { + unstash name:'default-build-result' + } + } + + // Add a suffix to tests to distinguish between different executions + // of the same test in different environments in reports + def testSuffix = buildEnv.tag.replaceAll('[^a-zA-Z0-9_\\-+]+', '_') + + dir(projectPath) { + sh """ \ + mvn -Dsurefire.environment=$testSuffix \ + ${toTestJdkArg(buildEnv)} \ + --fail-at-end \ + $args \ + """ + } +} + +String toTestJdkArg(BuildEnvironment buildEnv) { + String args = '' + + if ( ! (buildEnv instanceof JdkBuildEnvironment) ) { + return args; + } + + String testJdkTool = buildEnv.testJdkTool + if ( testJdkTool ) { + def testJdkToolPath = tool(name: testJdkTool, type: 'jdk') + args += " -Dsurefire.jvm.java_executable=$testJdkToolPath/bin/java" + } + + return args +} From f57403a7b6a3f7f5675a687ee14612128d00cdb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 29 Sep 2020 16:42:51 +0200 Subject: [PATCH 368/393] HV-1805 Disable fail-fast in Jenkinsfile --- Jenkinsfile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index d24690360d..5ee176d914 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -315,11 +315,11 @@ stage('Default build') { } stage('Non-default environments') { - Map executions = [:] + Map parameters = [:] // Test with multiple JDKs environments.content.jdk.enabled.each { JdkBuildEnvironment buildEnv -> - executions.put(buildEnv.tag, { + parameters.put(buildEnv.tag, { runBuildOnNode { helper.withMavenWorkspace(jdk: buildEnv.buildJdkTool) { mavenNonDefaultBuild buildEnv, """ \ @@ -330,12 +330,13 @@ stage('Non-default environments') { }) } - if (executions.isEmpty()) { + if (parameters.isEmpty()) { echo 'Skipping builds in non-default environments' helper.markStageSkipped() } else { - parallel(executions) + parameters.put('failFast', false) + parallel(parameters) } } From e504de2d715d7ed2ac9452c6e8f4e968feb0440d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Wed, 30 Sep 2020 18:32:19 +0200 Subject: [PATCH 369/393] HV-1805 Run the TCK with WildFly in the Jenkinsfile --- Jenkinsfile | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index 5ee176d914..e3f08758d8 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -142,6 +142,12 @@ stage('Configure') { condition: TestCondition.AFTER_MERGE), new JdkBuildEnvironment(version: '16', buildJdkTool: 'OpenJDK 16 Latest', condition: TestCondition.AFTER_MERGE) + ], + wildflyTck: [ + new WildFlyTckBuildEnvironment(javaVersion: '8', buildJdkTool: 'OracleJDK8 Latest', + condition: TestCondition.AFTER_MERGE), + new WildFlyTckBuildEnvironment(javaVersion: '11', buildJdkTool: 'OpenJDK 11 Latest', + condition: TestCondition.AFTER_MERGE) ] ]) @@ -330,6 +336,21 @@ stage('Non-default environments') { }) } + // Run the TCK with WildFly in multiple environments + environments.content.wildflyTck.enabled.each { WildFlyTckBuildEnvironment buildEnv -> + parameters.put(buildEnv.tag, { + runBuildOnNode { + helper.withMavenWorkspace(jdk: buildEnv.buildJdkTool) { + mavenNonDefaultBuild buildEnv, """ \ + clean install \ + -pl tck-runner \ + -Dincontainer \ + """ + } + } + }) + } + if (parameters.isEmpty()) { echo 'Skipping builds in non-default environments' helper.markStageSkipped() @@ -426,6 +447,15 @@ class JdkBuildEnvironment extends BuildEnvironment { boolean requiresDefaultBuildArtifacts() { false } } +class WildFlyTckBuildEnvironment extends BuildEnvironment { + String javaVersion + String buildJdkTool + @Override + String getTag() { "wildfly-tck-jdk$javaVersion" } + @Override + boolean requiresDefaultBuildArtifacts() { true } +} + void keepOnlyEnvironmentsMatchingFilter(String regex) { def pattern = /$regex/ From 863d611205f6f434c5fed563735b759da4e7f5b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Thu, 1 Oct 2020 10:54:59 +0200 Subject: [PATCH 370/393] HV-1805 Pass -DdeployAtEnd=true when deploying snapshots in the Jenkinsfile --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index e3f08758d8..188d808dd1 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -304,7 +304,7 @@ stage('Default build') { mvn clean \ --fail-at-end \ ${deploySnapshot ? "\ - deploy \ + deploy -DdeployAtEnd=true \ " : "\ install \ "} \ From 4b6762bfbb1517a28361241b0202d8cc4deca0d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 6 Oct 2020 16:47:00 +0200 Subject: [PATCH 371/393] HV-1805 Run sigtests and JQAssistant as part of the default Jenkinsfile build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Yoann Rodière --- Jenkinsfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index 188d808dd1..071000af71 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -309,6 +309,8 @@ stage('Default build') { install \ "} \ -Pdist \ + -Psigtest \ + -Pjqassistant \ ${enableDefaultBuildIT ? '' : '-DskipITs'} \ ${toTestJdkArg(environments.content.jdk.default)} \ """ From d4d82392c71f44897ae9d1fa56b0f33fea232237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Thu, 8 Oct 2020 09:01:17 +0200 Subject: [PATCH 372/393] HV-1805 Disable JDK15/JDK16 builds in Jenkinsfile because of JDK-8253566 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Yoann Rodière --- Jenkinsfile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 071000af71..d7905d3ffd 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -138,10 +138,12 @@ stage('Configure') { condition: TestCondition.AFTER_MERGE), new JdkBuildEnvironment(version: '14', buildJdkTool: 'OpenJDK 14 Latest', condition: TestCondition.AFTER_MERGE), + // Disabled because of https://bugs.openjdk.java.net/browse/JDK-8253566 new JdkBuildEnvironment(version: '15', buildJdkTool: 'OpenJDK 15 Latest', - condition: TestCondition.AFTER_MERGE), + condition: TestCondition.ON_DEMAND), + // Disabled because of https://bugs.openjdk.java.net/browse/JDK-8253566 new JdkBuildEnvironment(version: '16', buildJdkTool: 'OpenJDK 16 Latest', - condition: TestCondition.AFTER_MERGE) + condition: TestCondition.ON_DEMAND) ], wildflyTck: [ new WildFlyTckBuildEnvironment(javaVersion: '8', buildJdkTool: 'OracleJDK8 Latest', From 6c579c74ba7348751188abe732d2da26dbc67e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 20 Oct 2020 10:49:06 +0200 Subject: [PATCH 373/393] Re-enable JDK16 testing in Jenkinsfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Yoann Rodière --- Jenkinsfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index d7905d3ffd..8b9993ca3c 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -141,9 +141,8 @@ stage('Configure') { // Disabled because of https://bugs.openjdk.java.net/browse/JDK-8253566 new JdkBuildEnvironment(version: '15', buildJdkTool: 'OpenJDK 15 Latest', condition: TestCondition.ON_DEMAND), - // Disabled because of https://bugs.openjdk.java.net/browse/JDK-8253566 new JdkBuildEnvironment(version: '16', buildJdkTool: 'OpenJDK 16 Latest', - condition: TestCondition.ON_DEMAND) + condition: TestCondition.AFTER_MERGE) ], wildflyTck: [ new WildFlyTckBuildEnvironment(javaVersion: '8', buildJdkTool: 'OracleJDK8 Latest', From 864843180412cd8173d176108b7ccd6d8c49a010 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Oct 2020 22:57:43 +0000 Subject: [PATCH 374/393] HV-1814 Bump JUnit from 4.12 to 4.13.1 Bumps [junit](https://github.com/junit-team/junit4) from 4.12 to 4.13.1. - [Release notes](https://github.com/junit-team/junit4/releases) - [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.12.md) - [Commits](https://github.com/junit-team/junit4/compare/r4.12...r4.13.1) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d9885ad777..b948f2ea1e 100644 --- a/pom.xml +++ b/pom.xml @@ -167,7 +167,7 @@ 6.14.3 3.8.0 - 4.12 + 4.13.1 3.4 4.1.2 2.4.12 From 3aed882fa3fac22bf8afcc5922fe43523385e3e5 Mon Sep 17 00:00:00 2001 From: roger-jm Date: Sat, 31 Oct 2020 22:30:09 +0800 Subject: [PATCH 375/393] HV-1815 Fix DecimalMax and DecimalMin in zh_CN translation --- .../hibernate/validator/ValidationMessages_zh_CN.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh_CN.properties b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh_CN.properties index b2a75318fe..41e92497de 100644 --- a/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh_CN.properties +++ b/engine/src/main/resources/org/hibernate/validator/ValidationMessages_zh_CN.properties @@ -1,7 +1,7 @@ javax.validation.constraints.AssertFalse.message = \u53ea\u80fd\u4e3afalse javax.validation.constraints.AssertTrue.message = \u53ea\u80fd\u4e3atrue -javax.validation.constraints.DecimalMax.message = \u5fc5\u987b\u5c0f\u4e8e\u6216\u7b49\u4e8e{value} -javax.validation.constraints.DecimalMin.message = \u5fc5\u987b\u5927\u4e8e\u6216\u7b49\u4e8e{value} +javax.validation.constraints.DecimalMax.message = \u5FC5\u987B\u5C0F\u4E8E${inclusive == true ? '\u6216\u7B49\u4E8E' : ''}{value} +javax.validation.constraints.DecimalMin.message = \u5FC5\u987B\u5927\u4E8E${inclusive == true ? '\u6216\u7B49\u4E8E' : ''}{value} javax.validation.constraints.Digits.message = \u6570\u5b57\u7684\u503c\u8d85\u51fa\u4e86\u5141\u8bb8\u8303\u56f4(\u53ea\u5141\u8bb8\u5728{integer}\u4f4d\u6574\u6570\u548c{fraction}\u4f4d\u5c0f\u6570\u8303\u56f4\u5185) javax.validation.constraints.Email.message = \u4e0d\u662f\u4e00\u4e2a\u5408\u6cd5\u7684\u7535\u5b50\u90ae\u4ef6\u5730\u5740 javax.validation.constraints.Future.message = \u9700\u8981\u662f\u4e00\u4e2a\u5c06\u6765\u7684\u65f6\u95f4 From 5cb52c1565abf90d0f8bbee28f3ecb1cbda9eecc Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 4 Dec 2020 11:31:29 +0100 Subject: [PATCH 376/393] Set version to 6.2.0-SNAPSHOT --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index aba2ee27c3..febd4b8a6d 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index cf729254b1..de0652b818 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index b77667cecb..dc673dbc4e 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index 7abb58cb11..6138d3bfaa 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index fbadad5713..0412b53add 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index 2c0c5f42d1..04d9510d31 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 469a36e7af..e9525e8b9a 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index 04632e1174..5ec803106d 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 63a6e70b2d..a33e397ca6 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 68ecd4ef18..225deabc4e 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index cc7885efbb..e05aef916e 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index ac4bbd15a9..cf19966dd9 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index 3b8a65887a..83f5b1dabd 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index b948f2ea1e..a3aa029b52 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 48392fd31d..c42ad9fc2f 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index 20e34fd939..48ab6fef1a 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index 4fd7e2c57a..9d6ae2cae4 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index f93e782bcd..0f29f9e585 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index f3b5f6f460..b94ef0bf09 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index a72ad252de..23d8161891 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 08c0ebf283..9f506bae26 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.7-SNAPSHOT + 6.2.0-SNAPSHOT hibernate-validator-test-utils From 1403c1f896eb6ba506b40f3c20f8b96725bfdeef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 1 Dec 2020 11:46:16 +0100 Subject: [PATCH 377/393] HV-1817 Fix style issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Yoann Rodière --- .../hv/ScriptAssertValidatorTest.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/ScriptAssertValidatorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/ScriptAssertValidatorTest.java index 20d698abc8..95efc32d4c 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/ScriptAssertValidatorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/ScriptAssertValidatorTest.java @@ -43,14 +43,16 @@ public class ScriptAssertValidatorTest extends AbstractConstrainedTest { @Test public void scriptEvaluatesToTrue() throws Exception { - @ScriptAssert(lang = "groovy", script = "true") class TmpType { } + @ScriptAssert(lang = "groovy", script = "true") class TmpType { + } assertNoViolations( validator.validate( new TmpType() ) ); } @Test public void scriptEvaluatesToFalse() throws Exception { - @ScriptAssert(lang = "groovy", script = "false") class TmpType { } + @ScriptAssert(lang = "groovy", script = "false") class TmpType { + } assertThat( validator.validate( new TmpType() ) ).containsOnlyViolations( violationOf( ScriptAssert.class ) ); @@ -107,28 +109,32 @@ public void emptyAliasRaisesException() throws Exception { @Test(expectedExceptions = ConstraintDeclarationException.class) public void unknownLanguageNameRaisesException() throws Exception { - @ScriptAssert(lang = "foo", script = "script") class TmpType { } + @ScriptAssert(lang = "foo", script = "script") class TmpType { + } assertNoViolations( validator.validate( new TmpType() ) ); } @Test(expectedExceptions = ConstraintDeclarationException.class) public void illegalScriptExpressionRaisesException() throws Exception { - @ScriptAssert(lang = "groovy", script = "foo") class TmpType { } + @ScriptAssert(lang = "groovy", script = "foo") class TmpType { + } assertNoViolations( validator.validate( new TmpType() ) ); } @Test(expectedExceptions = ConstraintDeclarationException.class) public void scriptExpressionReturningNullRaisesException() throws Exception { - @ScriptAssert(lang = "groovy", script = "null") class TmpType { } + @ScriptAssert(lang = "groovy", script = "null") class TmpType { + } assertNoViolations( validator.validate( new TmpType() ) ); } @Test(expectedExceptions = ConstraintDeclarationException.class) public void scriptExpressionReturningNoBooleanRaisesException() throws Exception { - @ScriptAssert(lang = "groovy", script = "new java.util.Date()") class TmpType { } + @ScriptAssert(lang = "groovy", script = "new java.util.Date()") class TmpType { + } assertNoViolations( validator.validate( new TmpType() ) ); } From 56d443dbb5f4e81f2900d2563c42e68f475051e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 1 Dec 2020 11:45:06 +0100 Subject: [PATCH 378/393] HV-1817 Upgrade to checkstyle 8.38 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Yoann Rodière --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a3aa029b52..0b8d73fc6e 100644 --- a/pom.xml +++ b/pom.xml @@ -191,7 +191,7 @@ overridden by a CI job of the Checkstyle project so that they can check for regressions. Which is obviously good for us, too. --> - 8.18 + 8.38 @@ -208,7 +208,7 @@ 3.1.0 3.0.0 3.5.0 - 3.0.0 + 3.1.1 3.0.0 3.8.1 0.0.6 From e076293b0ee1bfa97b6e67d05ad9eee1ad77e893 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 25 Nov 2020 17:28:24 +0100 Subject: [PATCH 379/393] HV-1816 Disable Expression Language by default for custom constraint violations --- documentation/src/main/asciidoc/ch06.asciidoc | 31 ++---------- documentation/src/main/asciidoc/ch12.asciidoc | 37 +++++++++++++- .../chapter06/elinjection/SafeValidator.java | 1 + .../elinjection/UnsafeValidator.java | 9 +++- .../HibernateConstraintValidatorContext.java | 3 ++ .../HibernateConstraintViolationBuilder.java | 27 +++++++++++ .../engine/MessageInterpolatorContext.java | 11 ++++- .../ConstraintValidatorContextImpl.java | 48 ++++++++++++++----- .../ConstraintViolationCreationContext.java | 20 +++++--- ...rameterConstraintValidatorContextImpl.java | 3 +- .../AbstractValidationContext.java | 5 +- .../validator/internal/util/logging/Log.java | 4 ++ .../AbstractMessageInterpolator.java | 15 ++++-- .../HibernateMessageInterpolatorContext.java | 7 +++ ...bernateConstraintValidatorContextTest.java | 36 +++++++++++++- ...ssionLanguageMessageInterpolationTest.java | 16 ++++--- .../MessageInterpolatorContextTest.java | 15 ++++-- ...ResourceBundleMessageInterpolatorTest.java | 3 +- 18 files changed, 220 insertions(+), 71 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/constraintvalidation/HibernateConstraintViolationBuilder.java diff --git a/documentation/src/main/asciidoc/ch06.asciidoc b/documentation/src/main/asciidoc/ch06.asciidoc index 23adc09e16..6746906a37 100644 --- a/documentation/src/main/asciidoc/ch06.asciidoc +++ b/documentation/src/main/asciidoc/ch06.asciidoc @@ -173,35 +173,12 @@ It is important to add each configured constraint violation by calling `addConst Only after that the new constraint violation will be created. ==== -[[el-injection-caution]] -[CAUTION] -==== -**Be aware that the custom message template is passed directly to the Expression Language engine.** - -Thus, you should be very careful when integrating user input in a custom message template as it will be interpreted -by the Expression Language engine, which is usually not the behavior you want and **could allow malicious users to leak -sensitive data or even execute arbitrary code**. - -If you need to integrate user input in your message, you must <> -by unwrapping the context to `HibernateConstraintValidatorContext`. - -The following validator is very unsafe as it includes user input in the violation message. -If the validated `value` contains EL expressions, they will be executed by the EL engine. - -[source, JAVA, indent=0] ----- -include::{sourcedir}/org/hibernate/validator/referenceguide/chapter06/elinjection/UnsafeValidator.java[tags=include] ----- - -The following pattern must be used instead: +By default, Expression Language is not enabled for custom violations created in the `ConstraintValidatorContext`. -[source] ----- -include::{sourcedir}/org/hibernate/validator/referenceguide/chapter06/elinjection/SafeValidator.java[tags=include] ----- +However, for some advanced requirements, using Expression Language might be necessary. -By using expression variables, Hibernate Validator properly handles escaping and EL expressions won't be executed. -==== +In this case, you need to unwrap the `HibernateConstraintValidatorContext` and enable Expression Language explicitly. +See <> for more information. Refer to <> to learn how to use the `ConstraintValidatorContext` API to control the property path of constraint violations for class-level constraints. diff --git a/documentation/src/main/asciidoc/ch12.asciidoc b/documentation/src/main/asciidoc/ch12.asciidoc index 6abbddc995..c02971ec73 100644 --- a/documentation/src/main/asciidoc/ch12.asciidoc +++ b/documentation/src/main/asciidoc/ch12.asciidoc @@ -510,6 +510,7 @@ custom extensions for both of these interfaces. [[section-custom-constraint-validator-context]] `HibernateConstraintValidatorContext` is a subtype of `ConstraintValidatorContext` which allows you to: +* enable Expression Language interpolation for a particular custom violation - see below * set arbitrary parameters for interpolation via the Expression Language message interpolation facility using `HibernateConstraintValidatorContext#addExpressionVariable(String, Object)` or `HibernateConstraintValidatorContext#addMessageParameter(String, Object)`. @@ -535,8 +536,8 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/context/My [NOTE] ==== Apart from the syntax, the main difference between message parameters and expression variables is that message parameters -are simply interpolated whereas expression variables are interpreted using the expression language engine. -In practice, it should not change anything. +are simply interpolated whereas expression variables are interpreted using the Expression Language engine. +In practice, use message parameters if you do not need the advanced features of an Expression Language. ==== + [NOTE] @@ -550,6 +551,38 @@ You can, however, update the parameters between invocations of ==== * set an arbitrary dynamic payload - see <> +By default, Expression Language interpolation is **disabled** for custom violations, +this to avoid arbitrary code execution or sensitive data leak if user input is not properly escaped. + +It is possible to enable Expression Language for a given custom violation by using `enableExpressionLanguage()` as shown in the example below: + +[source] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter06/elinjection/SafeValidator.java[tags=include] +---- + +In this case, the message template will be interpolated by the Expression Language engine. + +[CAUTION] +==== +Using `addExpressionVariable()` is the only safe way to inject a variable into an expression. + +If you inject user input by simply concatenating the user input in the message, +you will allow potential arbitrary code execution and sensitive data leak: +if the user input contains valid expressions, they will be executed by the Expression Language engine. + +Here is an example of something you should **ABSOLUTELY NOT** do: + +[source, JAVA, indent=0] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter06/elinjection/UnsafeValidator.java[tags=include] +---- + +In the example above, if `value`, which might be user input, contains a valid expression, +it will be interpolated by the Expression Language engine, +potentially leading to unsafe behaviors. +==== + ==== `HibernateMessageInterpolatorContext` Hibernate Validator also offers a custom extension of `MessageInterpolatorContext`, namely diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter06/elinjection/SafeValidator.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter06/elinjection/SafeValidator.java index 182ab328da..71b6080e98 100644 --- a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter06/elinjection/SafeValidator.java +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter06/elinjection/SafeValidator.java @@ -23,6 +23,7 @@ public boolean isValid(String value, ConstraintValidatorContext context) { hibernateContext .addExpressionVariable( "validatedValue", value ) .buildConstraintViolationWithTemplate( "${validatedValue} is not a valid ZIP code" ) + .enableExpressionLanguage() .addConstraintViolation(); return false; diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter06/elinjection/UnsafeValidator.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter06/elinjection/UnsafeValidator.java index 6adf4632a1..70f3fe0e8f 100644 --- a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter06/elinjection/UnsafeValidator.java +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter06/elinjection/UnsafeValidator.java @@ -1,5 +1,6 @@ package org.hibernate.validator.referenceguide.chapter06.elinjection; +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorContext; import org.hibernate.validator.referenceguide.chapter06.constraintvalidatorpayload.ZipCode; import javax.validation.ConstraintValidator; @@ -16,9 +17,15 @@ public boolean isValid(String value, ConstraintValidatorContext context) { context.disableDefaultConstraintViolation(); + HibernateConstraintValidatorContext hibernateContext = context.unwrap( + HibernateConstraintValidatorContext.class ); + hibernateContext.disableDefaultConstraintViolation(); + if ( isInvalid( value ) ) { - context + hibernateContext + // THIS IS UNSAFE, DO NOT COPY THIS EXAMPLE .buildConstraintViolationWithTemplate( value + " is not a valid ZIP code" ) + .enableExpressionLanguage() .addConstraintViolation(); return false; diff --git a/engine/src/main/java/org/hibernate/validator/constraintvalidation/HibernateConstraintValidatorContext.java b/engine/src/main/java/org/hibernate/validator/constraintvalidation/HibernateConstraintValidatorContext.java index ddb049e2d0..7512652548 100644 --- a/engine/src/main/java/org/hibernate/validator/constraintvalidation/HibernateConstraintValidatorContext.java +++ b/engine/src/main/java/org/hibernate/validator/constraintvalidation/HibernateConstraintValidatorContext.java @@ -21,6 +21,9 @@ */ public interface HibernateConstraintValidatorContext extends ConstraintValidatorContext { + @Override + HibernateConstraintViolationBuilder buildConstraintViolationWithTemplate(String messageTemplate); + /** * Allows to set an additional named parameter which can be interpolated in the constraint violation message. The * variable will be available for interpolation for all constraint violations generated for this constraint. diff --git a/engine/src/main/java/org/hibernate/validator/constraintvalidation/HibernateConstraintViolationBuilder.java b/engine/src/main/java/org/hibernate/validator/constraintvalidation/HibernateConstraintViolationBuilder.java new file mode 100644 index 0000000000..413561dbbb --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/constraintvalidation/HibernateConstraintViolationBuilder.java @@ -0,0 +1,27 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ + +package org.hibernate.validator.constraintvalidation; + +import javax.validation.ConstraintValidatorContext.ConstraintViolationBuilder; + +import org.hibernate.validator.Incubating; + +public interface HibernateConstraintViolationBuilder extends ConstraintViolationBuilder { + + /** + * Enable Expression Language for the constraint violation created by this builder if the chosen + * {@code MessageInterpolator} supports it. + *

    + * If enabling this, you need to make sure your message template does not contain any unescaped user input (such as + * the validated value): use {@code addExpressionVariable()} to inject properly escaped variables into the template. + * + * @since 6.2 + */ + @Incubating + HibernateConstraintViolationBuilder enableExpressionLanguage(); +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/MessageInterpolatorContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/MessageInterpolatorContext.java index df9f9c4b79..eabaf5bd90 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/MessageInterpolatorContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/MessageInterpolatorContext.java @@ -39,19 +39,22 @@ public class MessageInterpolatorContext implements HibernateMessageInterpolatorC private final Map messageParameters; @Immutable private final Map expressionVariables; + private final boolean expressionLanguageEnabled; public MessageInterpolatorContext(ConstraintDescriptor constraintDescriptor, Object validatedValue, Class rootBeanType, Path propertyPath, Map messageParameters, - Map expressionVariables) { + Map expressionVariables, + boolean expressionLanguageEnabled) { this.constraintDescriptor = constraintDescriptor; this.validatedValue = validatedValue; this.rootBeanType = rootBeanType; this.propertyPath = propertyPath; this.messageParameters = toImmutableMap( messageParameters ); this.expressionVariables = toImmutableMap( expressionVariables ); + this.expressionLanguageEnabled = expressionLanguageEnabled; } @Override @@ -74,6 +77,11 @@ public Map getMessageParameters() { return messageParameters; } + @Override + public boolean isExpressionLanguageEnabled() { + return expressionLanguageEnabled; + } + @Override public Map getExpressionVariables() { return expressionVariables; @@ -135,6 +143,7 @@ public String toString() { sb.append( ", propertyPath=" ).append( propertyPath ); sb.append( ", messageParameters=" ).append( messageParameters ); sb.append( ", expressionVariables=" ).append( expressionVariables ); + sb.append( ", expressionLanguageEnabled=" ).append( expressionLanguageEnabled ); sb.append( '}' ); return sb.toString(); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java index 8af5369371..5535043205 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java @@ -6,6 +6,7 @@ */ package org.hibernate.validator.internal.engine.constraintvalidation; +import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.Collections; @@ -28,6 +29,7 @@ import javax.validation.metadata.ConstraintDescriptor; import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorContext; +import org.hibernate.validator.constraintvalidation.HibernateConstraintViolationBuilder; import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.util.CollectionHelper; import org.hibernate.validator.internal.util.Contracts; @@ -75,7 +77,7 @@ public final String getDefaultConstraintMessageTemplate() { } @Override - public ConstraintViolationBuilder buildConstraintViolationWithTemplate(String messageTemplate) { + public HibernateConstraintViolationBuilder buildConstraintViolationWithTemplate(String messageTemplate) { return new ConstraintViolationBuilderImpl( messageTemplate, getCopyOfBasePath() @@ -168,6 +170,7 @@ protected final PathImpl getCopyOfBasePath() { private ConstraintViolationCreationContext getDefaultConstraintViolationCreationContext() { return new ConstraintViolationCreationContext( getDefaultConstraintMessageTemplate(), + true, // EL is enabled for the default constraint violation basePath, messageParameters != null ? new HashMap<>( messageParameters ) : Collections.emptyMap(), expressionVariables != null ? new HashMap<>( expressionVariables ) : Collections.emptyMap(), @@ -178,6 +181,7 @@ private ConstraintViolationCreationContext getDefaultConstraintViolationCreation private abstract class NodeBuilderBase { protected final String messageTemplate; + protected boolean expressionLanguageEnabled; protected PathImpl propertyPath; protected NodeBuilderBase(String template, PathImpl path) { @@ -189,9 +193,14 @@ public ConstraintValidatorContext addConstraintViolation() { if ( constraintViolationCreationContexts == null ) { constraintViolationCreationContexts = CollectionHelper.newArrayList( 3 ); } + if ( !(expressionVariables == null || expressionVariables.isEmpty()) && !expressionLanguageEnabled ) { + LOG.expressionVariablesDefinedWithExpressionLanguageNotEnabled( + constraintDescriptor.getAnnotation() != null ? constraintDescriptor.getAnnotation().annotationType() : Annotation.class ); + } constraintViolationCreationContexts.add( new ConstraintViolationCreationContext( messageTemplate, + expressionLanguageEnabled, propertyPath, messageParameters != null ? new HashMap<>( messageParameters ) : Collections.emptyMap(), expressionVariables != null ? new HashMap<>( expressionVariables ) : Collections.emptyMap(), @@ -202,12 +211,18 @@ public ConstraintValidatorContext addConstraintViolation() { } } - protected class ConstraintViolationBuilderImpl extends NodeBuilderBase implements ConstraintViolationBuilder { + protected class ConstraintViolationBuilderImpl extends NodeBuilderBase implements HibernateConstraintViolationBuilder { protected ConstraintViolationBuilderImpl(String template, PathImpl path) { super( template, path ); } + @Override + public HibernateConstraintViolationBuilder enableExpressionLanguage() { + expressionLanguageEnabled = true; + return this; + } + @Override @Deprecated public NodeBuilderDefinedContext addNode(String name) { @@ -221,12 +236,12 @@ public NodeBuilderDefinedContext addNode(String name) { public NodeBuilderCustomizableContext addPropertyNode(String name) { dropLeafNodeIfRequired(); - return new DeferredNodeBuilder( messageTemplate, propertyPath, name, ElementKind.PROPERTY ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, name, ElementKind.PROPERTY ); } @Override public LeafNodeBuilderCustomizableContext addBeanNode() { - return new DeferredNodeBuilder( messageTemplate, propertyPath, null, ElementKind.BEAN ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, null, ElementKind.BEAN ); } @Override @@ -238,7 +253,7 @@ public NodeBuilderDefinedContext addParameterNode(int index) { public ContainerElementNodeBuilderCustomizableContext addContainerElementNode(String name, Class containerType, Integer typeArgumentIndex) { dropLeafNodeIfRequired(); - return new DeferredNodeBuilder( messageTemplate, propertyPath, name, containerType, typeArgumentIndex ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, name, containerType, typeArgumentIndex ); } /** @@ -267,17 +282,17 @@ public ConstraintViolationBuilder.NodeBuilderCustomizableContext addNode(String @Override public NodeBuilderCustomizableContext addPropertyNode(String name) { - return new DeferredNodeBuilder( messageTemplate, propertyPath, name, ElementKind.PROPERTY ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, name, ElementKind.PROPERTY ); } @Override public LeafNodeBuilderCustomizableContext addBeanNode() { - return new DeferredNodeBuilder( messageTemplate, propertyPath, null, ElementKind.BEAN ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, null, ElementKind.BEAN ); } @Override public ContainerElementNodeBuilderCustomizableContext addContainerElementNode(String name, Class containerType, Integer typeArgumentIndex) { - return new DeferredNodeBuilder( messageTemplate, propertyPath, name, containerType, typeArgumentIndex ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, name, containerType, typeArgumentIndex ); } } @@ -293,16 +308,23 @@ private class DeferredNodeBuilder extends NodeBuilderBase private final Integer leafNodeTypeArgumentIndex; - private DeferredNodeBuilder(String template, PathImpl path, String nodeName, ElementKind leafNodeKind) { + private DeferredNodeBuilder(String template, boolean expressionLanguageEnabled, PathImpl path, String nodeName, ElementKind leafNodeKind) { super( template, path ); + this.expressionLanguageEnabled = expressionLanguageEnabled; this.leafNodeName = nodeName; this.leafNodeKind = leafNodeKind; this.leafNodeContainerType = null; this.leafNodeTypeArgumentIndex = null; } - private DeferredNodeBuilder(String template, PathImpl path, String nodeName, Class leafNodeContainerType, Integer leafNodeTypeArgumentIndex) { + private DeferredNodeBuilder(String template, + boolean expressionLanguageEnabled, + PathImpl path, + String nodeName, + Class leafNodeContainerType, + Integer leafNodeTypeArgumentIndex) { super( template, path ); + this.expressionLanguageEnabled = expressionLanguageEnabled; this.leafNodeName = nodeName; this.leafNodeKind = ElementKind.CONTAINER_ELEMENT; this.leafNodeContainerType = leafNodeContainerType; @@ -344,19 +366,19 @@ public NodeBuilderCustomizableContext addNode(String name) { @Override public NodeBuilderCustomizableContext addPropertyNode(String name) { addLeafNode(); - return new DeferredNodeBuilder( messageTemplate, propertyPath, name, ElementKind.PROPERTY ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, name, ElementKind.PROPERTY ); } @Override public ContainerElementNodeBuilderCustomizableContext addContainerElementNode(String name, Class containerType, Integer typeArgumentIndex) { addLeafNode(); - return new DeferredNodeBuilder( messageTemplate, propertyPath, name, containerType, typeArgumentIndex ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, name, containerType, typeArgumentIndex ); } @Override public LeafNodeBuilderCustomizableContext addBeanNode() { addLeafNode(); - return new DeferredNodeBuilder( messageTemplate, propertyPath, null, ElementKind.BEAN ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, null, ElementKind.BEAN ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintViolationCreationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintViolationCreationContext.java index ce0396a78a..be009a3569 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintViolationCreationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintViolationCreationContext.java @@ -8,7 +8,6 @@ import static org.hibernate.validator.internal.util.CollectionHelper.toImmutableMap; -import java.util.Collections; import java.util.Map; import org.hibernate.validator.internal.engine.path.PathImpl; @@ -18,9 +17,12 @@ * Container class for the information needed to create a constraint violation. * * @author Hardy Ferentschik + * @author Guillaume Smet */ public class ConstraintViolationCreationContext { + private final String message; + private final boolean expressionLanguageEnabled; private final PathImpl propertyPath; @Immutable private final Map messageParameters; @@ -28,13 +30,14 @@ public class ConstraintViolationCreationContext { private final Map expressionVariables; private final Object dynamicPayload; - public ConstraintViolationCreationContext(String message, PathImpl property) { - this( message, property, Collections.emptyMap(), Collections.emptyMap(), null ); - } - - public ConstraintViolationCreationContext(String message, PathImpl property, Map messageParameters, Map expressionVariables, + public ConstraintViolationCreationContext(String message, + boolean expressionLanguageEnabled, + PathImpl property, + Map messageParameters, + Map expressionVariables, Object dynamicPayload) { this.message = message; + this.expressionLanguageEnabled = expressionLanguageEnabled; this.propertyPath = property; this.messageParameters = toImmutableMap( messageParameters ); this.expressionVariables = toImmutableMap( expressionVariables ); @@ -45,6 +48,10 @@ public final String getMessage() { return message; } + public boolean isExpressionLanguageEnabled() { + return expressionLanguageEnabled; + } + public final PathImpl getPath() { return propertyPath; } @@ -65,6 +72,7 @@ public Object getDynamicPayload() { public String toString() { final StringBuilder sb = new StringBuilder( "ConstraintViolationCreationContext{" ); sb.append( "message='" ).append( message ).append( '\'' ); + sb.append( ", expressionLanguageEnabled=" ).append( expressionLanguageEnabled ); sb.append( ", propertyPath=" ).append( propertyPath ); sb.append( ", messageParameters=" ).append( messageParameters ); sb.append( ", expressionVariables=" ).append( expressionVariables ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/CrossParameterConstraintValidatorContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/CrossParameterConstraintValidatorContextImpl.java index 2ac491a84d..0aaea340cf 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/CrossParameterConstraintValidatorContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/CrossParameterConstraintValidatorContextImpl.java @@ -12,6 +12,7 @@ import javax.validation.ElementKind; import javax.validation.metadata.ConstraintDescriptor; +import org.hibernate.validator.constraintvalidation.HibernateConstraintViolationBuilder; import org.hibernate.validator.constraintvalidation.HibernateCrossParameterConstraintValidatorContext; import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.util.Contracts; @@ -30,7 +31,7 @@ public CrossParameterConstraintValidatorContextImpl(List methodParameter } @Override - public final ConstraintViolationBuilder buildConstraintViolationWithTemplate(String messageTemplate) { + public final HibernateConstraintViolationBuilder buildConstraintViolationWithTemplate(String messageTemplate) { return new CrossParameterConstraintViolationBuilderImpl( methodParameterNames, messageTemplate, diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java index 870f0b2ad7..3c99e31613 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java @@ -229,6 +229,7 @@ public void addConstraintFailure( String messageTemplate = constraintViolationCreationContext.getMessage(); String interpolatedMessage = interpolate( messageTemplate, + constraintViolationCreationContext.isExpressionLanguageEnabled(), valueContext.getCurrentValidatedValue(), descriptor, constraintViolationCreationContext.getPath(), @@ -295,6 +296,7 @@ public ConstraintValidatorContextImpl createConstraintValidatorContextFor(Constr private String interpolate( String messageTemplate, + boolean expressionLanguageEnabled, Object validatedValue, ConstraintDescriptor descriptor, Path path, @@ -306,7 +308,8 @@ private String interpolate( getRootBeanClass(), path, messageParameters, - expressionVariables + expressionVariables, + expressionLanguageEnabled ); try { diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index cfe3761558..2f33852238 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -908,4 +908,8 @@ ConstraintDefinitionException getConstraintValidatorDefinitionConstraintMismatch @Message(id = 256, value = "Unable to instantiate locale resolver class %s.") ValidationException getUnableToInstantiateLocaleResolverClassException(String localeResolverClassName, @Cause Exception e); + + @LogMessage(level = WARN) + @Message(id = 257, value = "Expression variables have been defined for constraint %1$s while Expression Language is not enabled.") + void expressionVariablesDefinedWithExpressionLanguageNotEnabled(Class constraintAnnotation); } diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java index bbb7f8bd65..34054ff2a4 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java @@ -412,11 +412,16 @@ private String interpolateMessage(String message, Context context, Locale locale ); // resolve EL expressions (step 3) - resolvedMessage = interpolateExpression( - new TokenIterator( getParameterTokens( resolvedMessage, tokenizedELMessages, InterpolationTermType.EL ) ), - context, - locale - ); + // in the standard Hibernate Validator execution flow, the context is always an instance of + // HibernateMessageInterpolatorContext + // but it can be a spec Context in the Jakarta Bean Validation TCK. + if ( !( context instanceof HibernateMessageInterpolatorContext ) + || ( (HibernateMessageInterpolatorContext) context ).isExpressionLanguageEnabled() ) { + resolvedMessage = interpolateExpression( + new TokenIterator( getParameterTokens( resolvedMessage, tokenizedELMessages, InterpolationTermType.EL ) ), + context, + locale ); + } } // last but not least we have to take care of escaped literals diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/HibernateMessageInterpolatorContext.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/HibernateMessageInterpolatorContext.java index c1640cc24c..e398aa4fd9 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/HibernateMessageInterpolatorContext.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/HibernateMessageInterpolatorContext.java @@ -48,4 +48,11 @@ public interface HibernateMessageInterpolatorContext extends MessageInterpolator * @since 6.1 */ Path getPropertyPath(); + + /** + * @return if Expression Language should be enabled if supported by the {@code MessageInterpolator}. + * + * @return 6.1.7 + */ + boolean isExpressionLanguageEnabled(); } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/constraintvalidation/HibernateConstraintValidatorContextTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/constraintvalidation/HibernateConstraintValidatorContextTest.java index fa9c670e7e..3501d164c6 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/constraintvalidation/HibernateConstraintValidatorContextTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/constraintvalidation/HibernateConstraintValidatorContextTest.java @@ -45,6 +45,7 @@ public class HibernateConstraintValidatorContextTest { private static final String QUESTION_2 = "What is 1+1 and what is the answer to life?"; private static final String QUESTION_3 = "This is a trick question"; private static final String QUESTION_4 = "What keywords are not allowed?"; + private static final String QUESTION_5 = "What is 1+1 and what is the answer to life? But I won't get the right answer as Expression Language is disabled"; private static final List INVALID_KEYWORDS = Lists.newArrayList( "foo", "bar", "baz" ); @@ -130,7 +131,7 @@ public void testSettingInvalidCustomExpressionVariable() { @Test @TestForIssue(jiraKey = "HV-701") - public void testCreatingMultipleConstraintViolationWithExpressionVariables() { + public void testCreatingMultipleConstraintViolationWithExpressionVariablesWithExpressionLanguageEnabled() { Validator validator = getValidator(); Set> constraintViolations = validator.validate( new ExpressionVariableFoo( QUESTION_2 ) ); @@ -223,6 +224,18 @@ public void testNullIsReturnedIfPayloadIsNull() { Assert.assertNull( hibernateConstraintViolation.getDynamicPayload( Object.class ) ); } + @Test + @TestForIssue(jiraKey = "HV-1816") + public void testCreatingMultipleConstraintViolationWithExpressionVariables() { + Validator validator = getValidator(); + Set> constraintViolations = validator.validate( new ExpressionVariableFoo( QUESTION_5 ) ); + + assertThat( constraintViolations ).containsOnlyViolations( + violationOf( ExpressionVariableOracleConstraint.class ).withMessage( "answer 1: ${answer}" ), + violationOf( ExpressionVariableOracleConstraint.class ).withMessage( "answer 2: ${answer}" ) + ); + } + public class MessageParameterFoo { @MessageParameterOracleConstraint private final String question; @@ -323,7 +336,7 @@ public boolean isValid(String question, ConstraintValidatorContext context) { createSingleConstraintViolation( hibernateContext ); } else if ( question.equals( QUESTION_2 ) ) { - createMultipleConstraintViolationsUpdatingExpressionVariableValues( hibernateContext ); + createMultipleConstraintViolationsUpdatingExpressionVariableValuesWithExpressionLanguageEnabled( hibernateContext ); } else if ( question.equals( QUESTION_3 ) ) { hibernateContext.addExpressionVariable( "answer", "${foo}" ); @@ -331,6 +344,9 @@ else if ( question.equals( QUESTION_3 ) ) { else if ( question.equals( QUESTION_4 ) ) { hibernateContext.withDynamicPayload( INVALID_KEYWORDS ); } + else if ( question.equals( QUESTION_5 ) ) { + createMultipleConstraintViolationsUpdatingExpressionVariableValues( hibernateContext ); + } else { tryingToIllegallyUseNullExpressionVariableName( hibernateContext ); } @@ -343,6 +359,22 @@ private void tryingToIllegallyUseNullExpressionVariableName(HibernateConstraintV hibernateContext.addMessageParameter( null, "foo" ); } + private void createMultipleConstraintViolationsUpdatingExpressionVariableValuesWithExpressionLanguageEnabled( + HibernateConstraintValidatorContext hibernateContext) { + hibernateContext.disableDefaultConstraintViolation(); + + hibernateContext.addExpressionVariable( "answer", 2 ); + hibernateContext.buildConstraintViolationWithTemplate( "answer 1: ${answer}" ) + .enableExpressionLanguage() + .addConstraintViolation(); + + // resetting the expression variables + hibernateContext.addExpressionVariable( "answer", 42 ); + hibernateContext.buildConstraintViolationWithTemplate( "answer 2: ${answer}" ) + .enableExpressionLanguage() + .addConstraintViolation(); + } + private void createMultipleConstraintViolationsUpdatingExpressionVariableValues(HibernateConstraintValidatorContext hibernateContext) { hibernateContext.disableDefaultConstraintViolation(); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java index 4f4b986847..be94c108d3 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java @@ -22,7 +22,6 @@ import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; import org.hibernate.validator.testutil.TestForIssue; - import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; @@ -69,7 +68,8 @@ public void testExpressionLanguageGraphNavigation() { null, null, Collections.emptyMap(), - Collections.emptyMap() ); + Collections.emptyMap(), + true ); String expected = "18"; String actual = interpolatorUnderTest.interpolate( "${validatedValue.age}", context ); @@ -84,7 +84,8 @@ public void testUnknownPropertyInExpressionLanguageGraphNavigation() { null, null, Collections.emptyMap(), - Collections.emptyMap() ); + Collections.emptyMap(), + true ); String expected = "${validatedValue.foo}"; String actual = interpolatorUnderTest.interpolate( "${validatedValue.foo}", context ); @@ -174,7 +175,8 @@ public void testLocaleBasedFormatting() { null, null, Collections.emptyMap(), - Collections.emptyMap() ); + Collections.emptyMap(), + true ); // german locale String expected = "42,00"; @@ -234,7 +236,8 @@ public void testCallingWrongFormatterMethod() { null, null, Collections.emptyMap(), - Collections.emptyMap() ); + Collections.emptyMap(), + true ); String expected = "${formatter.foo('%1$.2f', validatedValue)}"; String actual = interpolatorUnderTest.interpolate( @@ -310,6 +313,7 @@ private MessageInterpolatorContext createMessageInterpolatorContext(ConstraintDe null, null, Collections.emptyMap(), - Collections.emptyMap() ); + Collections.emptyMap(), + true ); } } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/MessageInterpolatorContextTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/MessageInterpolatorContextTest.java index c989b6b3ad..9481471f36 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/MessageInterpolatorContextTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/MessageInterpolatorContextTest.java @@ -92,7 +92,8 @@ public void testContextWithRightDescriptorAndValueAndRootBeanClassIsPassedToMess TestBean.class, null, Collections.emptyMap(), - Collections.emptyMap() ) + Collections.emptyMap(), + true ) ) ) .andReturn( "invalid" ); @@ -109,13 +110,15 @@ public void testContextWithRightDescriptorAndValueAndRootBeanClassIsPassedToMess @Test(expectedExceptions = ValidationException.class) public void testUnwrapToImplementationCausesValidationException() { - Context context = new MessageInterpolatorContext( null, null, null, null, Collections.emptyMap(), Collections.emptyMap() ); + Context context = new MessageInterpolatorContext( null, null, null, null, Collections.emptyMap(), + Collections.emptyMap(), true ); context.unwrap( MessageInterpolatorContext.class ); } @Test public void testUnwrapToInterfaceTypesSucceeds() { - Context context = new MessageInterpolatorContext( null, null, null, null, Collections.emptyMap(), Collections.emptyMap() ); + Context context = new MessageInterpolatorContext( null, null, null, null, Collections.emptyMap(), + Collections.emptyMap(), true ); MessageInterpolator.Context asMessageInterpolatorContext = context.unwrap( MessageInterpolator.Context.class ); assertSame( asMessageInterpolatorContext, context ); @@ -138,7 +141,8 @@ public void testGetRootBeanType() { rootBeanType, null, Collections.emptyMap(), - Collections.emptyMap() ); + Collections.emptyMap(), + true ); assertSame( context.unwrap( HibernateMessageInterpolatorContext.class ).getRootBeanType(), rootBeanType ); } @@ -153,7 +157,8 @@ public void testGetPropertyPath() { null, pathMock, Collections.emptyMap(), - Collections.emptyMap() ); + Collections.emptyMap(), + true ); assertSame( context.unwrap( HibernateMessageInterpolatorContext.class ).getPropertyPath(), pathMock ); } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java index 09bbbd198b..1c6f0810c9 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java @@ -281,7 +281,8 @@ private MessageInterpolatorContext createMessageInterpolatorContext(ConstraintDe null, null, Collections.emptyMap(), - Collections.emptyMap() ); + Collections.emptyMap(), + true ); } private void runInterpolation(boolean cachingEnabled) { From d2db40b9e7d22c7a0b44d7665242dfc7b4d14d78 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 25 Nov 2020 20:12:56 +0100 Subject: [PATCH 380/393] HV-1816 Limit the EL features exposed by default --- documentation/src/main/asciidoc/ch04.asciidoc | 13 + documentation/src/main/asciidoc/ch12.asciidoc | 67 ++- .../chapter12/el/ElFeaturesTest.java | 33 ++ .../BaseHibernateValidatorConfiguration.java | 53 +++ .../HibernateConstraintViolationBuilder.java | 20 +- .../engine/AbstractConfigurationImpl.java | 32 ++ .../engine/MessageInterpolatorContext.java | 21 +- .../PredefinedScopeValidatorFactoryImpl.java | 6 +- .../ValidatorFactoryConfigurationHelper.java | 45 ++ .../internal/engine/ValidatorFactoryImpl.java | 6 +- .../engine/ValidatorFactoryScopedContext.java | 48 ++- .../ConstraintValidatorContextImpl.java | 53 ++- .../ConstraintViolationCreationContext.java | 21 +- ...rameterConstraintValidatorContextImpl.java | 12 +- .../messageinterpolation/ElTermResolver.java | 41 +- ...Context.java => BeanMethodsELContext.java} | 4 +- .../el/BeanPropertiesELResolver.java | 25 ++ .../el/BeanPropertiesElContext.java | 53 +++ .../el/DisabledFeatureELException.java | 16 + .../el/NoOpElResolver.java | 55 +++ .../el/VariablesELContext.java | 57 +++ .../AbstractValidationContext.java | 14 +- .../ParameterExecutableValidationContext.java | 8 +- .../ValidatorScopedContext.java | 21 + .../validator/internal/util/logging/Log.java | 26 ++ .../AbstractMessageInterpolator.java | 4 +- .../ExpressionLanguageFeatureLevel.java | 90 ++++ .../HibernateMessageInterpolatorContext.java | 6 +- .../ParameterMessageInterpolator.java | 2 +- .../ResourceBundleMessageInterpolator.java | 2 +- .../ConstraintValidatorContextImplTest.java | 4 +- ...intExpressionLanguageFeatureLevelTest.java | 257 ++++++++++++ ...ionExpressionLanguageFeatureLevelTest.java | 388 ++++++++++++++++++ ...ssionLanguageMessageInterpolationTest.java | 111 ++++- .../MessageInterpolatorContextTest.java | 14 +- ...ResourceBundleMessageInterpolatorTest.java | 4 +- .../validator/testutils/ValidatorUtil.java | 4 +- engine/src/test/resources/log4j2.properties | 6 +- .../validation-constraints-bean-methods.xml | 16 + .../el/validation-constraints-default.xml | 16 + ...idation-custom-violations-bean-methods.xml | 16 + .../validation-custom-violations-default.xml | 16 + 42 files changed, 1613 insertions(+), 93 deletions(-) create mode 100644 documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/el/ElFeaturesTest.java rename engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/{SimpleELContext.java => BeanMethodsELContext.java} (92%) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/BeanPropertiesELResolver.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/BeanPropertiesElContext.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/DisabledFeatureELException.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/NoOpElResolver.java create mode 100644 engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/VariablesELContext.java create mode 100644 engine/src/main/java/org/hibernate/validator/messageinterpolation/ExpressionLanguageFeatureLevel.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/el/ConstraintExpressionLanguageFeatureLevelTest.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/el/CustomViolationExpressionLanguageFeatureLevelTest.java create mode 100644 engine/src/test/resources/org/hibernate/validator/test/el/validation-constraints-bean-methods.xml create mode 100644 engine/src/test/resources/org/hibernate/validator/test/el/validation-constraints-default.xml create mode 100644 engine/src/test/resources/org/hibernate/validator/test/el/validation-custom-violations-bean-methods.xml create mode 100644 engine/src/test/resources/org/hibernate/validator/test/el/validation-custom-violations-default.xml diff --git a/documentation/src/main/asciidoc/ch04.asciidoc b/documentation/src/main/asciidoc/ch04.asciidoc index 7ab337396f..68bf448ec9 100644 --- a/documentation/src/main/asciidoc/ch04.asciidoc +++ b/documentation/src/main/asciidoc/ch04.asciidoc @@ -91,6 +91,19 @@ context: `format(String format, Object... args)` which behaves like `java.util.Formatter.format(String format, Object... args)`. +Expression Language is very flexible and Hibernate Validator offers several feature levels +that you can use to enable Expression Language features through the `ExpressionLanguageFeatureLevel` enum: + +* `NONE`: Expression Language interpolation is fully disabled. +* `VARIABLES`: Allow interpolation of the variables injected via `addExpressionVariable()`, resources bundles and usage of the `formatter` object. +* `BEAN_PROPERTIES`: Allow everything `VARIABLES` allows plus the interpolation of bean properties. +* `BEAN_METHODS`: Also allow execution of bean methods. Can be considered safe for hardcoded constraint messages but not for <> + where extra care is required. + +The default feature level for constraint messages is `BEAN_PROPERTIES`. + +You can define the Expression Language feature level when <>. + The following section provides several examples for using EL expressions in error messages. ==== Examples diff --git a/documentation/src/main/asciidoc/ch12.asciidoc b/documentation/src/main/asciidoc/ch12.asciidoc index c02971ec73..0421e753b2 100644 --- a/documentation/src/main/asciidoc/ch12.asciidoc +++ b/documentation/src/main/asciidoc/ch12.asciidoc @@ -419,6 +419,55 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/dynamicpay ---- ==== +[[el-features]] +=== Enabling Expression Language features + +Hibernate Validator restricts the Expression Language features exposed by default. + +For this purpose, we define several feature levels in `ExpressionLanguageFeatureLevel`: + +* `NONE`: Expression Language interpolation is fully disabled. +* `VARIABLES`: Allow interpolation of the variables injected via `addExpressionVariable()`, resources bundles and usage of the `formatter` object. +* `BEAN_PROPERTIES`: Allow everything `VARIABLES` allows plus the interpolation of bean properties. +* `BEAN_METHODS`: Also allow execution of bean methods. This can lead to serious security issues, including arbitrary code execution if not carefully handled. + +Depending on the context, the features we expose are different: + +* For constraints, the default level is `BEAN_PROPERTIES`. + For all the built-in constraint messages to be correctly interpolated, you need at least the `VARIABLES` level. +* For custom violations, created via the `ConstraintValidatorContext`, Expression Language is disabled by default. + You can enable it for specific custom violations and, when enabled, it will default to `VARIABLES`. + +Hibernate Validator provides ways to override these defaults when boostrapping the `ValidatorFactory`. + +To change the Expression Language feature level for constraints, use the following: + +[source, JAVA, indent=0] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/el/ElFeaturesTest.java[tags=constraints] +---- + +To change the Expression Language feature level for custom violations, use the following: + +[source, JAVA, indent=0] +---- +include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/el/ElFeaturesTest.java[tags=customViolations] +---- + +[CAUTION] +==== +Doing this will automatically enable Expression Language for all the custom violations in your application. + +It should only be used for compatibility and to ease the migration from older Hibernate Validator versions. +==== + +These levels can also be defined using the following properties: + +* `hibernate.validator.constraint_expression_language_feature_level` +* `hibernate.validator.custom_violation_expression_language_feature_level` + +Accepted values for these properties are: `none`, `variables`, `bean-properties` and `bean-methods`. + [[non-el-message-interpolator]] === `ParameterMessageInterpolator` @@ -552,7 +601,7 @@ You can, however, update the parameters between invocations of * set an arbitrary dynamic payload - see <> By default, Expression Language interpolation is **disabled** for custom violations, -this to avoid arbitrary code execution or sensitive data leak if user input is not properly escaped. +this to avoid arbitrary code execution or sensitive data leak if message templates are built from improperly escaped user input. It is possible to enable Expression Language for a given custom violation by using `enableExpressionLanguage()` as shown in the example below: @@ -563,9 +612,21 @@ include::{sourcedir}/org/hibernate/validator/referenceguide/chapter06/elinjectio In this case, the message template will be interpolated by the Expression Language engine. +By default, only variables interpolation is enabled when enabling Expression Language. + +You can enable more features by using `HibernateConstraintViolationBuilder#enableExpressionLanguage(ExpressionLanguageFeatureLevel level)`. + +We define several levels of features for Expression Language interpolation: + +* `NONE`: Expression Language interpolation is fully disabled - this is the default for custom violations. +* `VARIABLES`: Allow interpolation of the variables injected via `addExpressionVariable()`, resources bundles and usage of the `formatter` object. +* `BEAN_PROPERTIES`: Allow everything `VARIABLES` allows plus the interpolation of bean properties. +* `BEAN_METHODS`: Also allow execution of bean methods. This can lead to serious security issues, including arbitrary code execution if not carefully handled. + [CAUTION] ==== -Using `addExpressionVariable()` is the only safe way to inject a variable into an expression. +Using `addExpressionVariable()` is the only safe way to inject a variable into an expression +and it's especially important if you use the `BEAN_PROPERTIES` or `BEAN_METHODS` feature levels. If you inject user input by simply concatenating the user input in the message, you will allow potential arbitrary code execution and sensitive data leak: @@ -596,7 +657,7 @@ bundle. If you have any other use cases, let us know. ==== [source, JAVA, indent=0] ---- -include::{engine-sourcedir}/org/hibernate/validator/messageinterpolation/HibernateMessageInterpolatorContext.java[lines=18..26] +include::{engine-sourcedir}/org/hibernate/validator/messageinterpolation/HibernateMessageInterpolatorContext.java[lines=22..58] ---- ==== diff --git a/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/el/ElFeaturesTest.java b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/el/ElFeaturesTest.java new file mode 100644 index 0000000000..a3071fca47 --- /dev/null +++ b/documentation/src/test/java/org/hibernate/validator/referenceguide/chapter12/el/ElFeaturesTest.java @@ -0,0 +1,33 @@ +package org.hibernate.validator.referenceguide.chapter12.el; + +import javax.validation.Validation; +import javax.validation.ValidatorFactory; + +import org.hibernate.validator.HibernateValidator; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; +import org.junit.Test; + +public class ElFeaturesTest { + + @SuppressWarnings("unused") + @Test + public void testConstraints() throws Exception { + //tag::constraints[] + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .constraintExpressionLanguageFeatureLevel( ExpressionLanguageFeatureLevel.VARIABLES ) + .buildValidatorFactory(); + //end::constraints[] + } + + @SuppressWarnings("unused") + @Test + public void testCustomViolations() throws Exception { + //tag::customViolations[] + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .customViolationExpressionLanguageFeatureLevel( ExpressionLanguageFeatureLevel.VARIABLES ) + .buildValidatorFactory(); + //end::customViolations[] + } +} diff --git a/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java index 44955071e5..7ce04ef270 100644 --- a/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/BaseHibernateValidatorConfiguration.java @@ -13,6 +13,7 @@ import java.util.Set; import javax.validation.Configuration; +import javax.validation.ConstraintValidatorContext; import javax.validation.ConstraintViolation; import javax.validation.TraversableResolver; import javax.validation.constraints.Future; @@ -24,6 +25,7 @@ import org.hibernate.validator.cfg.ConstraintMapping; import org.hibernate.validator.constraints.ParameterScriptAssert; import org.hibernate.validator.constraints.ScriptAssert; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; import org.hibernate.validator.spi.messageinterpolation.LocaleResolver; import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider; @@ -144,6 +146,28 @@ public interface BaseHibernateValidatorConfiguration + * This property only affects the EL feature level of "static" constraint violation messages. In particular, it + * doesn't affect the default EL feature level for custom violations. Refer to + * {@link #CUSTOM_VIOLATION_EXPRESSION_LANGUAGE_FEATURE_LEVEL} to configure that. + * + * @since 6.2 + */ + @Incubating + String CONSTRAINT_EXPRESSION_LANGUAGE_FEATURE_LEVEL = "hibernate.validator.constraint_expression_language_feature_level"; + + /** + * Property for configuring the Expression Language feature level for custom violations, allowing to define which + * Expression Language features are available for message interpolation. + * + * @since 6.2 + */ + @Incubating + String CUSTOM_VIOLATION_EXPRESSION_LANGUAGE_FEATURE_LEVEL = "hibernate.validator.custom_violation_expression_language_feature_level"; + /** *

    * Returns the {@link ResourceBundleLocator} used by the @@ -427,4 +451,33 @@ default S locales(Locale... locales) { @Incubating S beanMetaDataClassNormalizer(BeanMetaDataClassNormalizer beanMetaDataClassNormalizer); + + /** + * Allows setting the Expression Language feature level for message interpolation of constraint messages. + *

    + * This is the feature level used for messages hardcoded inside the constraint declaration. + *

    + * If you are creating custom constraint violations, Expression Language support needs to be explicitly enabled and + * use the safest feature level by default if enabled. + * + * @param expressionLanguageFeatureLevel the {@link ExpressionLanguageFeatureLevel} to be used + * @return {@code this} following the chaining method pattern + * + * @since 6.2 + */ + @Incubating + S constraintExpressionLanguageFeatureLevel(ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel); + + /** + * Allows setting the Expression Language feature level for message interpolation of custom violation messages. + *

    + * This is the feature level used for messages of custom violations created by the {@link ConstraintValidatorContext}. + * + * @param expressionLanguageFeatureLevel the {@link ExpressionLanguageFeatureLevel} to be used + * @return {@code this} following the chaining method pattern + * + * @since 6.2 + */ + @Incubating + S customViolationExpressionLanguageFeatureLevel(ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel); } diff --git a/engine/src/main/java/org/hibernate/validator/constraintvalidation/HibernateConstraintViolationBuilder.java b/engine/src/main/java/org/hibernate/validator/constraintvalidation/HibernateConstraintViolationBuilder.java index 413561dbbb..9150353fa2 100644 --- a/engine/src/main/java/org/hibernate/validator/constraintvalidation/HibernateConstraintViolationBuilder.java +++ b/engine/src/main/java/org/hibernate/validator/constraintvalidation/HibernateConstraintViolationBuilder.java @@ -10,18 +10,34 @@ import javax.validation.ConstraintValidatorContext.ConstraintViolationBuilder; import org.hibernate.validator.Incubating; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; public interface HibernateConstraintViolationBuilder extends ConstraintViolationBuilder { + /** + * Enable Expression Language with the default Expression Language feature level for the constraint violation + * created by this builder if the chosen {@code MessageInterpolator} supports it. + *

    + * If you enable this, you need to make sure your message template does not contain any unescaped user input (such as + * the validated value): use {@code addExpressionVariable()} to inject properly escaped variables into the template. + * + * @since 6.2 + */ + @Incubating + default HibernateConstraintViolationBuilder enableExpressionLanguage() { + return enableExpressionLanguage( ExpressionLanguageFeatureLevel.DEFAULT ); + }; + /** * Enable Expression Language for the constraint violation created by this builder if the chosen * {@code MessageInterpolator} supports it. *

    - * If enabling this, you need to make sure your message template does not contain any unescaped user input (such as + * If you enable this, you need to make sure your message template does not contain any unescaped user input (such as * the validated value): use {@code addExpressionVariable()} to inject properly escaped variables into the template. * + * @param level The Expression Language features level supported. * @since 6.2 */ @Incubating - HibernateConstraintViolationBuilder enableExpressionLanguage(); + HibernateConstraintViolationBuilder enableExpressionLanguage(ExpressionLanguageFeatureLevel level); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java index 04b093db81..f858c61d9e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/AbstractConfigurationImpl.java @@ -57,6 +57,7 @@ import org.hibernate.validator.internal.util.stereotypes.Lazy; import org.hibernate.validator.internal.xml.config.ValidationBootstrapParameters; import org.hibernate.validator.internal.xml.config.ValidationXmlParser; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; import org.hibernate.validator.resourceloading.PlatformResourceBundleLocator; @@ -129,6 +130,8 @@ public abstract class AbstractConfigurationImpl getProgrammaticMappings() { return programmaticMappings; diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/MessageInterpolatorContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/MessageInterpolatorContext.java index eabaf5bd90..4d398c80dc 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/MessageInterpolatorContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/MessageInterpolatorContext.java @@ -17,6 +17,7 @@ import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.util.stereotypes.Immutable; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; import org.hibernate.validator.messageinterpolation.HibernateMessageInterpolatorContext; /** @@ -39,7 +40,8 @@ public class MessageInterpolatorContext implements HibernateMessageInterpolatorC private final Map messageParameters; @Immutable private final Map expressionVariables; - private final boolean expressionLanguageEnabled; + private final ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel; + private final boolean customViolation; public MessageInterpolatorContext(ConstraintDescriptor constraintDescriptor, Object validatedValue, @@ -47,14 +49,16 @@ public MessageInterpolatorContext(ConstraintDescriptor constraintDescriptor, Path propertyPath, Map messageParameters, Map expressionVariables, - boolean expressionLanguageEnabled) { + ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel, + boolean customViolation) { this.constraintDescriptor = constraintDescriptor; this.validatedValue = validatedValue; this.rootBeanType = rootBeanType; this.propertyPath = propertyPath; this.messageParameters = toImmutableMap( messageParameters ); this.expressionVariables = toImmutableMap( expressionVariables ); - this.expressionLanguageEnabled = expressionLanguageEnabled; + this.expressionLanguageFeatureLevel = expressionLanguageFeatureLevel; + this.customViolation = customViolation; } @Override @@ -78,8 +82,12 @@ public Map getMessageParameters() { } @Override - public boolean isExpressionLanguageEnabled() { - return expressionLanguageEnabled; + public ExpressionLanguageFeatureLevel getExpressionLanguageFeatureLevel() { + return expressionLanguageFeatureLevel; + } + + public boolean isCustomViolation() { + return customViolation; } @Override @@ -143,7 +151,8 @@ public String toString() { sb.append( ", propertyPath=" ).append( propertyPath ); sb.append( ", messageParameters=" ).append( messageParameters ); sb.append( ", expressionVariables=" ).append( expressionVariables ); - sb.append( ", expressionLanguageEnabled=" ).append( expressionLanguageEnabled ); + sb.append( ", expressionLanguageFeatureLevel=" ).append( expressionLanguageFeatureLevel ); + sb.append( ", customViolation=" ).append( customViolation ); sb.append( '}' ); return sb.toString(); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java index 2eddf9153f..ca59ece651 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java @@ -9,6 +9,8 @@ import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowMultipleCascadedValidationOnReturnValues; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowOverridingMethodAlterParameterConstraint; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineAllowParallelMethodsDefineParameterConstraints; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineConstraintExpressionLanguageFeatureLevel; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineCustomViolationExpressionLanguageFeatureLevel; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineBeanMetaDataClassNormalizer; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineConstraintMappings; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineConstraintValidatorPayload; @@ -119,7 +121,9 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState determineScriptEvaluatorFactory( configurationState, properties, externalClassLoader ), determineFailFast( hibernateSpecificConfig, properties ), determineTraversableResolverResultCacheEnabled( hibernateSpecificConfig, properties ), - determineConstraintValidatorPayload( hibernateSpecificConfig ) + determineConstraintValidatorPayload( hibernateSpecificConfig ), + determineConstraintExpressionLanguageFeatureLevel( hibernateSpecificConfig, properties ), + determineCustomViolationExpressionLanguageFeatureLevel( hibernateSpecificConfig, properties ) ); this.constraintValidatorManager = new PredefinedScopeConstraintValidatorManagerImpl( diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java index a74f5a16fd..b8e814c3ca 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryConfigurationHelper.java @@ -38,6 +38,7 @@ import org.hibernate.validator.internal.util.privilegedactions.GetClassLoader; import org.hibernate.validator.internal.util.privilegedactions.LoadClass; import org.hibernate.validator.internal.util.privilegedactions.NewInstance; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; import org.hibernate.validator.metadata.BeanMetaDataClassNormalizer; import org.hibernate.validator.spi.cfg.ConstraintMappingContributor; import org.hibernate.validator.spi.messageinterpolation.LocaleResolver; @@ -259,6 +260,50 @@ static Object determineConstraintValidatorPayload(ConfigurationState configurati return null; } + static ExpressionLanguageFeatureLevel determineConstraintExpressionLanguageFeatureLevel(AbstractConfigurationImpl hibernateSpecificConfig, + Map properties) { + if ( hibernateSpecificConfig.getConstraintExpressionLanguageFeatureLevel() != null ) { + LOG.logConstraintExpressionLanguageFeatureLevel( hibernateSpecificConfig.getConstraintExpressionLanguageFeatureLevel() ); + return ExpressionLanguageFeatureLevel.interpretDefaultForConstraints( hibernateSpecificConfig.getConstraintExpressionLanguageFeatureLevel() ); + } + + String expressionLanguageFeatureLevelName = properties.get( HibernateValidatorConfiguration.CONSTRAINT_EXPRESSION_LANGUAGE_FEATURE_LEVEL ); + if ( expressionLanguageFeatureLevelName != null ) { + try { + ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel = ExpressionLanguageFeatureLevel.of( expressionLanguageFeatureLevelName ); + LOG.logConstraintExpressionLanguageFeatureLevel( expressionLanguageFeatureLevel ); + return ExpressionLanguageFeatureLevel.interpretDefaultForConstraints( expressionLanguageFeatureLevel ); + } + catch (IllegalArgumentException e) { + throw LOG.invalidExpressionLanguageFeatureLevelValue( expressionLanguageFeatureLevelName, e ); + } + } + + return ExpressionLanguageFeatureLevel.interpretDefaultForConstraints( ExpressionLanguageFeatureLevel.DEFAULT ); + } + + static ExpressionLanguageFeatureLevel determineCustomViolationExpressionLanguageFeatureLevel(AbstractConfigurationImpl hibernateSpecificConfig, + Map properties) { + if ( hibernateSpecificConfig.getCustomViolationExpressionLanguageFeatureLevel() != null ) { + LOG.logCustomViolationExpressionLanguageFeatureLevel( hibernateSpecificConfig.getCustomViolationExpressionLanguageFeatureLevel() ); + return ExpressionLanguageFeatureLevel.interpretDefaultForCustomViolations( hibernateSpecificConfig.getCustomViolationExpressionLanguageFeatureLevel() ); + } + + String expressionLanguageFeatureLevelName = properties.get( HibernateValidatorConfiguration.CUSTOM_VIOLATION_EXPRESSION_LANGUAGE_FEATURE_LEVEL ); + if ( expressionLanguageFeatureLevelName != null ) { + try { + ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel = ExpressionLanguageFeatureLevel.of( expressionLanguageFeatureLevelName ); + LOG.logCustomViolationExpressionLanguageFeatureLevel( expressionLanguageFeatureLevel ); + return ExpressionLanguageFeatureLevel.interpretDefaultForCustomViolations( expressionLanguageFeatureLevel ); + } + catch (IllegalArgumentException e) { + throw LOG.invalidExpressionLanguageFeatureLevelValue( expressionLanguageFeatureLevelName, e ); + } + } + + return ExpressionLanguageFeatureLevel.NONE; + } + static GetterPropertySelectionStrategy determineGetterPropertySelectionStrategy(AbstractConfigurationImpl hibernateSpecificConfig, Map properties, ClassLoader externalClassLoader) { if ( hibernateSpecificConfig.getGetterPropertySelectionStrategy() != null ) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java index 918177fd46..e7ae23617d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java @@ -12,6 +12,8 @@ import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineBeanMetaDataClassNormalizer; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineConstraintMappings; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineConstraintValidatorPayload; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineConstraintExpressionLanguageFeatureLevel; +import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineCustomViolationExpressionLanguageFeatureLevel; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineExternalClassLoader; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineFailFast; import static org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.determineScriptEvaluatorFactory; @@ -156,7 +158,9 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { determineScriptEvaluatorFactory( configurationState, properties, externalClassLoader ), determineFailFast( hibernateSpecificConfig, properties ), determineTraversableResolverResultCacheEnabled( hibernateSpecificConfig, properties ), - determineConstraintValidatorPayload( hibernateSpecificConfig ) + determineConstraintValidatorPayload( hibernateSpecificConfig ), + determineConstraintExpressionLanguageFeatureLevel( hibernateSpecificConfig, properties ), + determineCustomViolationExpressionLanguageFeatureLevel( hibernateSpecificConfig, properties ) ); ConstraintValidatorManager constraintValidatorManager = new ConstraintValidatorManagerImpl( diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryScopedContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryScopedContext.java index fa87eb016d..85b9599471 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryScopedContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryScopedContext.java @@ -17,6 +17,7 @@ import org.hibernate.validator.internal.engine.constraintvalidation.HibernateConstraintValidatorInitializationContextImpl; import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; public class ValidatorFactoryScopedContext { @@ -67,6 +68,16 @@ public class ValidatorFactoryScopedContext { */ private final Object constraintValidatorPayload; + /** + * The Expression Language feature level for constraints. + */ + private final ExpressionLanguageFeatureLevel constraintExpressionLanguageFeatureLevel; + + /** + * The Expression Language feature level for custom violations. + */ + private final ExpressionLanguageFeatureLevel customViolationExpressionLanguageFeatureLevel; + /** * The constraint validator initialization context. */ @@ -80,9 +91,12 @@ public class ValidatorFactoryScopedContext { ScriptEvaluatorFactory scriptEvaluatorFactory, boolean failFast, boolean traversableResolverResultCacheEnabled, - Object constraintValidatorPayload) { + Object constraintValidatorPayload, + ExpressionLanguageFeatureLevel constraintExpressionLanguageFeatureLevel, + ExpressionLanguageFeatureLevel customViolationExpressionLanguageFeatureLevel) { this( messageInterpolator, traversableResolver, parameterNameProvider, clockProvider, temporalValidationTolerance, scriptEvaluatorFactory, failFast, - traversableResolverResultCacheEnabled, constraintValidatorPayload, + traversableResolverResultCacheEnabled, constraintValidatorPayload, constraintExpressionLanguageFeatureLevel, + customViolationExpressionLanguageFeatureLevel, new HibernateConstraintValidatorInitializationContextImpl( scriptEvaluatorFactory, clockProvider, temporalValidationTolerance ) ); } @@ -96,6 +110,8 @@ private ValidatorFactoryScopedContext(MessageInterpolator messageInterpolator, boolean failFast, boolean traversableResolverResultCacheEnabled, Object constraintValidatorPayload, + ExpressionLanguageFeatureLevel constraintExpressionLanguageFeatureLevel, + ExpressionLanguageFeatureLevel customViolationExpressionLanguageFeatureLevel, HibernateConstraintValidatorInitializationContextImpl constraintValidatorInitializationContext) { this.messageInterpolator = messageInterpolator; this.traversableResolver = traversableResolver; @@ -106,6 +122,8 @@ private ValidatorFactoryScopedContext(MessageInterpolator messageInterpolator, this.failFast = failFast; this.traversableResolverResultCacheEnabled = traversableResolverResultCacheEnabled; this.constraintValidatorPayload = constraintValidatorPayload; + this.constraintExpressionLanguageFeatureLevel = constraintExpressionLanguageFeatureLevel; + this.customViolationExpressionLanguageFeatureLevel = customViolationExpressionLanguageFeatureLevel; this.constraintValidatorInitializationContext = constraintValidatorInitializationContext; } @@ -149,6 +167,14 @@ public HibernateConstraintValidatorInitializationContext getConstraintValidatorI return this.constraintValidatorInitializationContext; } + public ExpressionLanguageFeatureLevel getConstraintExpressionLanguageFeatureLevel() { + return this.constraintExpressionLanguageFeatureLevel; + } + + public ExpressionLanguageFeatureLevel getCustomViolationExpressionLanguageFeatureLevel() { + return this.customViolationExpressionLanguageFeatureLevel; + } + static class Builder { private final ValidatorFactoryScopedContext defaultContext; @@ -161,6 +187,8 @@ static class Builder { private boolean failFast; private boolean traversableResolverResultCacheEnabled; private Object constraintValidatorPayload; + private ExpressionLanguageFeatureLevel constraintExpressionLanguageFeatureLevel; + private ExpressionLanguageFeatureLevel customViolationExpressionLanguageFeatureLevel; private HibernateConstraintValidatorInitializationContextImpl constraintValidatorInitializationContext; Builder(ValidatorFactoryScopedContext defaultContext) { @@ -176,6 +204,8 @@ static class Builder { this.failFast = defaultContext.failFast; this.traversableResolverResultCacheEnabled = defaultContext.traversableResolverResultCacheEnabled; this.constraintValidatorPayload = defaultContext.constraintValidatorPayload; + this.constraintExpressionLanguageFeatureLevel = defaultContext.constraintExpressionLanguageFeatureLevel; + this.customViolationExpressionLanguageFeatureLevel = defaultContext.customViolationExpressionLanguageFeatureLevel; this.constraintValidatorInitializationContext = defaultContext.constraintValidatorInitializationContext; } @@ -250,6 +280,18 @@ public ValidatorFactoryScopedContext.Builder setConstraintValidatorPayload(Objec return this; } + public ValidatorFactoryScopedContext.Builder setConstraintExpressionLanguageFeatureLevel( + ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel) { + this.constraintExpressionLanguageFeatureLevel = expressionLanguageFeatureLevel; + return this; + } + + public ValidatorFactoryScopedContext.Builder setCustomViolationExpressionLanguageFeatureLevel( + ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel) { + this.customViolationExpressionLanguageFeatureLevel = expressionLanguageFeatureLevel; + return this; + } + public ValidatorFactoryScopedContext build() { return new ValidatorFactoryScopedContext( messageInterpolator, @@ -261,6 +303,8 @@ public ValidatorFactoryScopedContext build() { failFast, traversableResolverResultCacheEnabled, constraintValidatorPayload, + constraintExpressionLanguageFeatureLevel, + customViolationExpressionLanguageFeatureLevel, HibernateConstraintValidatorInitializationContextImpl.of( constraintValidatorInitializationContext, scriptEvaluatorFactory, diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java index 5535043205..aeb2ce2b33 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java @@ -35,6 +35,7 @@ import org.hibernate.validator.internal.util.Contracts; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; /** * @author Hardy Ferentschik @@ -48,6 +49,8 @@ public class ConstraintValidatorContextImpl implements HibernateConstraintValida private Map messageParameters; private Map expressionVariables; private final ClockProvider clockProvider; + private final ExpressionLanguageFeatureLevel defaultConstraintExpressionLanguageFeatureLevel; + private final ExpressionLanguageFeatureLevel defaultCustomViolationExpressionLanguageFeatureLevel; private final PathImpl basePath; private final ConstraintDescriptor constraintDescriptor; private List constraintViolationCreationContexts; @@ -59,8 +62,12 @@ public ConstraintValidatorContextImpl( ClockProvider clockProvider, PathImpl propertyPath, ConstraintDescriptor constraintDescriptor, - Object constraintValidatorPayload) { + Object constraintValidatorPayload, + ExpressionLanguageFeatureLevel defaultConstraintExpressionLanguageFeatureLevel, + ExpressionLanguageFeatureLevel defaultCustomViolationExpressionLanguageFeatureLevel) { this.clockProvider = clockProvider; + this.defaultConstraintExpressionLanguageFeatureLevel = defaultConstraintExpressionLanguageFeatureLevel; + this.defaultCustomViolationExpressionLanguageFeatureLevel = defaultCustomViolationExpressionLanguageFeatureLevel; this.basePath = propertyPath; this.constraintDescriptor = constraintDescriptor; this.constraintValidatorPayload = constraintValidatorPayload; @@ -170,7 +177,8 @@ protected final PathImpl getCopyOfBasePath() { private ConstraintViolationCreationContext getDefaultConstraintViolationCreationContext() { return new ConstraintViolationCreationContext( getDefaultConstraintMessageTemplate(), - true, // EL is enabled for the default constraint violation + defaultConstraintExpressionLanguageFeatureLevel, + false, basePath, messageParameters != null ? new HashMap<>( messageParameters ) : Collections.emptyMap(), expressionVariables != null ? new HashMap<>( expressionVariables ) : Collections.emptyMap(), @@ -181,7 +189,7 @@ private ConstraintViolationCreationContext getDefaultConstraintViolationCreation private abstract class NodeBuilderBase { protected final String messageTemplate; - protected boolean expressionLanguageEnabled; + protected ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel = defaultCustomViolationExpressionLanguageFeatureLevel; protected PathImpl propertyPath; protected NodeBuilderBase(String template, PathImpl path) { @@ -193,14 +201,15 @@ public ConstraintValidatorContext addConstraintViolation() { if ( constraintViolationCreationContexts == null ) { constraintViolationCreationContexts = CollectionHelper.newArrayList( 3 ); } - if ( !(expressionVariables == null || expressionVariables.isEmpty()) && !expressionLanguageEnabled ) { + if ( !( expressionVariables == null || expressionVariables.isEmpty() ) && expressionLanguageFeatureLevel == ExpressionLanguageFeatureLevel.NONE ) { LOG.expressionVariablesDefinedWithExpressionLanguageNotEnabled( constraintDescriptor.getAnnotation() != null ? constraintDescriptor.getAnnotation().annotationType() : Annotation.class ); } constraintViolationCreationContexts.add( new ConstraintViolationCreationContext( messageTemplate, - expressionLanguageEnabled, + expressionLanguageFeatureLevel, + true, propertyPath, messageParameters != null ? new HashMap<>( messageParameters ) : Collections.emptyMap(), expressionVariables != null ? new HashMap<>( expressionVariables ) : Collections.emptyMap(), @@ -218,8 +227,8 @@ protected ConstraintViolationBuilderImpl(String template, PathImpl path) { } @Override - public HibernateConstraintViolationBuilder enableExpressionLanguage() { - expressionLanguageEnabled = true; + public HibernateConstraintViolationBuilder enableExpressionLanguage(ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel) { + this.expressionLanguageFeatureLevel = ExpressionLanguageFeatureLevel.interpretDefaultForCustomViolations( expressionLanguageFeatureLevel ); return this; } @@ -236,12 +245,12 @@ public NodeBuilderDefinedContext addNode(String name) { public NodeBuilderCustomizableContext addPropertyNode(String name) { dropLeafNodeIfRequired(); - return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, name, ElementKind.PROPERTY ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageFeatureLevel, propertyPath, name, ElementKind.PROPERTY ); } @Override public LeafNodeBuilderCustomizableContext addBeanNode() { - return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, null, ElementKind.BEAN ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageFeatureLevel, propertyPath, null, ElementKind.BEAN ); } @Override @@ -253,7 +262,7 @@ public NodeBuilderDefinedContext addParameterNode(int index) { public ContainerElementNodeBuilderCustomizableContext addContainerElementNode(String name, Class containerType, Integer typeArgumentIndex) { dropLeafNodeIfRequired(); - return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, name, containerType, typeArgumentIndex ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageFeatureLevel, propertyPath, name, containerType, typeArgumentIndex ); } /** @@ -282,17 +291,17 @@ public ConstraintViolationBuilder.NodeBuilderCustomizableContext addNode(String @Override public NodeBuilderCustomizableContext addPropertyNode(String name) { - return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, name, ElementKind.PROPERTY ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageFeatureLevel, propertyPath, name, ElementKind.PROPERTY ); } @Override public LeafNodeBuilderCustomizableContext addBeanNode() { - return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, null, ElementKind.BEAN ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageFeatureLevel, propertyPath, null, ElementKind.BEAN ); } @Override public ContainerElementNodeBuilderCustomizableContext addContainerElementNode(String name, Class containerType, Integer typeArgumentIndex) { - return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, name, containerType, typeArgumentIndex ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageFeatureLevel, propertyPath, name, containerType, typeArgumentIndex ); } } @@ -308,9 +317,13 @@ private class DeferredNodeBuilder extends NodeBuilderBase private final Integer leafNodeTypeArgumentIndex; - private DeferredNodeBuilder(String template, boolean expressionLanguageEnabled, PathImpl path, String nodeName, ElementKind leafNodeKind) { + private DeferredNodeBuilder(String template, + ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel, + PathImpl path, + String nodeName, + ElementKind leafNodeKind) { super( template, path ); - this.expressionLanguageEnabled = expressionLanguageEnabled; + this.expressionLanguageFeatureLevel = expressionLanguageFeatureLevel; this.leafNodeName = nodeName; this.leafNodeKind = leafNodeKind; this.leafNodeContainerType = null; @@ -318,13 +331,13 @@ private DeferredNodeBuilder(String template, boolean expressionLanguageEnabled, } private DeferredNodeBuilder(String template, - boolean expressionLanguageEnabled, + ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel, PathImpl path, String nodeName, Class leafNodeContainerType, Integer leafNodeTypeArgumentIndex) { super( template, path ); - this.expressionLanguageEnabled = expressionLanguageEnabled; + this.expressionLanguageFeatureLevel = expressionLanguageFeatureLevel; this.leafNodeName = nodeName; this.leafNodeKind = ElementKind.CONTAINER_ELEMENT; this.leafNodeContainerType = leafNodeContainerType; @@ -366,19 +379,19 @@ public NodeBuilderCustomizableContext addNode(String name) { @Override public NodeBuilderCustomizableContext addPropertyNode(String name) { addLeafNode(); - return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, name, ElementKind.PROPERTY ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageFeatureLevel, propertyPath, name, ElementKind.PROPERTY ); } @Override public ContainerElementNodeBuilderCustomizableContext addContainerElementNode(String name, Class containerType, Integer typeArgumentIndex) { addLeafNode(); - return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, name, containerType, typeArgumentIndex ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageFeatureLevel, propertyPath, name, containerType, typeArgumentIndex ); } @Override public LeafNodeBuilderCustomizableContext addBeanNode() { addLeafNode(); - return new DeferredNodeBuilder( messageTemplate, expressionLanguageEnabled, propertyPath, null, ElementKind.BEAN ); + return new DeferredNodeBuilder( messageTemplate, expressionLanguageFeatureLevel, propertyPath, null, ElementKind.BEAN ); } @Override diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintViolationCreationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintViolationCreationContext.java index be009a3569..9118be015d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintViolationCreationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintViolationCreationContext.java @@ -12,6 +12,7 @@ import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.util.stereotypes.Immutable; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; /** * Container class for the information needed to create a constraint violation. @@ -22,7 +23,8 @@ public class ConstraintViolationCreationContext { private final String message; - private final boolean expressionLanguageEnabled; + private final ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel; + private final boolean customViolation; private final PathImpl propertyPath; @Immutable private final Map messageParameters; @@ -31,13 +33,15 @@ public class ConstraintViolationCreationContext { private final Object dynamicPayload; public ConstraintViolationCreationContext(String message, - boolean expressionLanguageEnabled, + ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel, + boolean customViolation, PathImpl property, Map messageParameters, Map expressionVariables, Object dynamicPayload) { this.message = message; - this.expressionLanguageEnabled = expressionLanguageEnabled; + this.expressionLanguageFeatureLevel = expressionLanguageFeatureLevel; + this.customViolation = customViolation; this.propertyPath = property; this.messageParameters = toImmutableMap( messageParameters ); this.expressionVariables = toImmutableMap( expressionVariables ); @@ -48,8 +52,12 @@ public final String getMessage() { return message; } - public boolean isExpressionLanguageEnabled() { - return expressionLanguageEnabled; + public ExpressionLanguageFeatureLevel getExpressionLanguageFeatureLevel() { + return expressionLanguageFeatureLevel; + } + + public boolean isCustomViolation() { + return customViolation; } public final PathImpl getPath() { @@ -72,7 +80,8 @@ public Object getDynamicPayload() { public String toString() { final StringBuilder sb = new StringBuilder( "ConstraintViolationCreationContext{" ); sb.append( "message='" ).append( message ).append( '\'' ); - sb.append( ", expressionLanguageEnabled=" ).append( expressionLanguageEnabled ); + sb.append( ", expressionLanguageFeatureLevel=" ).append( expressionLanguageFeatureLevel ); + sb.append( ", customViolation=" ).append( customViolation ); sb.append( ", propertyPath=" ).append( propertyPath ); sb.append( ", messageParameters=" ).append( messageParameters ); sb.append( ", expressionVariables=" ).append( expressionVariables ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/CrossParameterConstraintValidatorContextImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/CrossParameterConstraintValidatorContextImpl.java index 0aaea340cf..4bb97b70fa 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/CrossParameterConstraintValidatorContextImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/CrossParameterConstraintValidatorContextImpl.java @@ -16,6 +16,7 @@ import org.hibernate.validator.constraintvalidation.HibernateCrossParameterConstraintValidatorContext; import org.hibernate.validator.internal.engine.path.PathImpl; import org.hibernate.validator.internal.util.Contracts; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; /** * @author Marko Bekhta @@ -24,8 +25,15 @@ public class CrossParameterConstraintValidatorContextImpl extends ConstraintVali private final List methodParameterNames; - public CrossParameterConstraintValidatorContextImpl(List methodParameterNames, ClockProvider clockProvider, PathImpl propertyPath, ConstraintDescriptor constraintDescriptor, Object constraintValidatorPayload) { - super( clockProvider, propertyPath, constraintDescriptor, constraintValidatorPayload ); + public CrossParameterConstraintValidatorContextImpl(List methodParameterNames, + ClockProvider clockProvider, + PathImpl propertyPath, + ConstraintDescriptor constraintDescriptor, + Object constraintValidatorPayload, + ExpressionLanguageFeatureLevel constraintExpressionLanguageFeatureLevel, + ExpressionLanguageFeatureLevel customViolationExpressionLanguageFeatureLevel) { + super( clockProvider, propertyPath, constraintDescriptor, constraintValidatorPayload, constraintExpressionLanguageFeatureLevel, + customViolationExpressionLanguageFeatureLevel ); Contracts.assertTrue( propertyPath.getLeafNode().getKind() == ElementKind.CROSS_PARAMETER, "Context can only be used for corss parameter validation" ); this.methodParameterNames = methodParameterNames; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/ElTermResolver.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/ElTermResolver.java index e063390e80..5e7d21220a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/ElTermResolver.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/ElTermResolver.java @@ -10,14 +10,19 @@ import java.util.Locale; import java.util.Map; +import javax.el.ELContext; import javax.el.ELException; import javax.el.ExpressionFactory; +import javax.el.MethodNotFoundException; import javax.el.PropertyNotFoundException; import javax.el.ValueExpression; import javax.validation.MessageInterpolator; +import org.hibernate.validator.internal.engine.messageinterpolation.el.BeanMethodsELContext; +import org.hibernate.validator.internal.engine.messageinterpolation.el.BeanPropertiesElContext; +import org.hibernate.validator.internal.engine.messageinterpolation.el.DisabledFeatureELException; import org.hibernate.validator.internal.engine.messageinterpolation.el.RootResolver; -import org.hibernate.validator.internal.engine.messageinterpolation.el.SimpleELContext; +import org.hibernate.validator.internal.engine.messageinterpolation.el.VariablesELContext; import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.messageinterpolation.HibernateMessageInterpolatorContext; @@ -27,6 +32,7 @@ * * @author Hardy Ferentschik * @author Adam Stawicki + * @author Guillaume Smet */ public class ElTermResolver implements TermResolver { @@ -61,14 +67,22 @@ public ElTermResolver(Locale locale, ExpressionFactory expressionFactory) { @Override public String interpolate(MessageInterpolator.Context context, String expression) { String resolvedExpression = expression; - SimpleELContext elContext = new SimpleELContext( expressionFactory ); + + ELContext elContext = getElContext( context ); + try { ValueExpression valueExpression = bindContextValues( expression, context, elContext ); resolvedExpression = (String) valueExpression.getValue( elContext ); } + catch (DisabledFeatureELException dfee) { + LOG.disabledFeatureInExpressionLanguage( expression, dfee ); + } catch (PropertyNotFoundException pnfe) { LOG.unknownPropertyInExpressionLanguage( expression, pnfe ); } + catch (MethodNotFoundException mnfe) { + LOG.unknownMethodInExpressionLanguage( expression, mnfe ); + } catch (ELException e) { LOG.errorInExpressionLanguage( expression, e ); } @@ -79,7 +93,26 @@ public String interpolate(MessageInterpolator.Context context, String expression return resolvedExpression; } - private ValueExpression bindContextValues(String messageTemplate, MessageInterpolator.Context messageInterpolatorContext, SimpleELContext elContext) { + private ELContext getElContext(MessageInterpolator.Context context) { + if ( !( context instanceof HibernateMessageInterpolatorContext ) ) { + return new VariablesELContext( expressionFactory ); + } + + switch ( ( (HibernateMessageInterpolatorContext) context ).getExpressionLanguageFeatureLevel() ) { + case NONE: + throw LOG.expressionsNotResolvedWhenExpressionLanguageFeaturesDisabled(); + case VARIABLES: + return new VariablesELContext( expressionFactory ); + case BEAN_PROPERTIES: + return new BeanPropertiesElContext( expressionFactory ); + case BEAN_METHODS: + return new BeanMethodsELContext( expressionFactory ); + default: + throw LOG.expressionsLanguageFeatureLevelNotSupported(); + } + } + + private ValueExpression bindContextValues(String messageTemplate, MessageInterpolator.Context messageInterpolatorContext, ELContext elContext) { // bind the validated value ValueExpression valueExpression = expressionFactory.createValueExpression( messageInterpolatorContext.getValidatedValue(), @@ -104,7 +137,7 @@ private ValueExpression bindContextValues(String messageTemplate, MessageInterpo return expressionFactory.createValueExpression( elContext, messageTemplate, String.class ); } - private void addVariablesToElContext(SimpleELContext elContext, Map variables) { + private void addVariablesToElContext(ELContext elContext, Map variables) { for ( Map.Entry entry : variables.entrySet() ) { ValueExpression valueExpression = expressionFactory.createValueExpression( entry.getValue(), Object.class ); elContext.getVariableMapper().setVariable( entry.getKey(), valueExpression ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/SimpleELContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/BeanMethodsELContext.java similarity index 92% rename from engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/SimpleELContext.java rename to engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/BeanMethodsELContext.java index 8647e34837..bb5c9f6f23 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/SimpleELContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/BeanMethodsELContext.java @@ -20,7 +20,7 @@ * @author Hardy Ferentschik * @author Guillaume Smet */ -public class SimpleELContext extends StandardELContext { +public class BeanMethodsELContext extends StandardELContext { private static final ELResolver DEFAULT_RESOLVER = new CompositeELResolver() { { add( new RootResolver() ); @@ -32,7 +32,7 @@ public class SimpleELContext extends StandardELContext { } }; - public SimpleELContext(ExpressionFactory expressionFactory) { + public BeanMethodsELContext(ExpressionFactory expressionFactory) { super( expressionFactory ); // In javax.el.ELContext, the ExpressionFactory is extracted from the context map. If it is not found, it diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/BeanPropertiesELResolver.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/BeanPropertiesELResolver.java new file mode 100644 index 0000000000..d9e9be4d2c --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/BeanPropertiesELResolver.java @@ -0,0 +1,25 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.messageinterpolation.el; + +import javax.el.BeanELResolver; +import javax.el.ELContext; + +/** + * @author Guillaume Smet + */ +public class BeanPropertiesELResolver extends BeanELResolver { + + BeanPropertiesELResolver() { + super( false ); + } + + @Override + public Object invoke(ELContext context, Object base, Object methodName, Class[] paramTypes, Object[] params) { + throw new DisabledFeatureELException( "Method execution is not supported when only enabling Expression Language bean property resolution." ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/BeanPropertiesElContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/BeanPropertiesElContext.java new file mode 100644 index 0000000000..4969e03a99 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/BeanPropertiesElContext.java @@ -0,0 +1,53 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.messageinterpolation.el; + +import javax.el.ArrayELResolver; +import javax.el.CompositeELResolver; +import javax.el.ELResolver; +import javax.el.ExpressionFactory; +import javax.el.ListELResolver; +import javax.el.MapELResolver; +import javax.el.ResourceBundleELResolver; +import javax.el.StandardELContext; + +/** + * @author Guillaume Smet + */ +public class BeanPropertiesElContext extends StandardELContext { + private static final ELResolver DEFAULT_RESOLVER = new CompositeELResolver() { + { + add( new RootResolver() ); + add( new ArrayELResolver( true ) ); + add( new ListELResolver( true ) ); + add( new MapELResolver( true ) ); + add( new ResourceBundleELResolver() ); + add( new BeanPropertiesELResolver() ); + } + }; + + public BeanPropertiesElContext(ExpressionFactory expressionFactory) { + super( expressionFactory ); + + // In javax.el.ELContext, the ExpressionFactory is extracted from the context map. If it is not found, it + // defaults to ELUtil.getExpressionFactory() which, if we provided the ExpressionFactory to the + // ResourceBundleMessageInterpolator, might not be the same. Thus, we inject the ExpressionFactory in the + // context. + putContext( ExpressionFactory.class, expressionFactory ); + } + + @Override + public void addELResolver(ELResolver cELResolver) { + throw new UnsupportedOperationException( getClass().getSimpleName() + " does not support addELResolver." ); + } + + @Override + public ELResolver getELResolver() { + return DEFAULT_RESOLVER; + } + +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/DisabledFeatureELException.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/DisabledFeatureELException.java new file mode 100644 index 0000000000..6cfd2edf27 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/DisabledFeatureELException.java @@ -0,0 +1,16 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.messageinterpolation.el; + +import javax.el.ELException; + +public class DisabledFeatureELException extends ELException { + + DisabledFeatureELException(String message) { + super( message ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/NoOpElResolver.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/NoOpElResolver.java new file mode 100644 index 0000000000..9ea875ee8e --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/NoOpElResolver.java @@ -0,0 +1,55 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.messageinterpolation.el; + +import java.beans.FeatureDescriptor; +import java.util.Collections; +import java.util.Iterator; + +import javax.el.ELContext; +import javax.el.ELResolver; + +/** + * @author Guillaume Smet + */ +public class NoOpElResolver extends ELResolver { + + @Override + public Object invoke(ELContext context, Object base, Object method, Class[] paramTypes, Object[] params) { + throw new DisabledFeatureELException( "Method execution is not supported when only enabling Expression Language variables resolution." ); + } + + @Override + public Object getValue(ELContext context, Object base, Object property) { + throw new DisabledFeatureELException( "Accessing properties is not supported when only enabling Expression Language variables resolution" ); + } + + @Override + public Class getType(ELContext context, Object base, Object property) { + return null; + } + + @Override + public void setValue(ELContext context, Object base, Object property, Object value) { + throw new DisabledFeatureELException( "Accessing properties is not supported when only enabling Expression Language variables resolution" ); + } + + @Override + public boolean isReadOnly(ELContext context, Object base, Object property) { + return true; + } + + @Override + public Iterator getFeatureDescriptors(ELContext context, Object base) { + return Collections.emptyIterator(); + } + + @Override + public Class getCommonPropertyType(ELContext context, Object base) { + return null; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/VariablesELContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/VariablesELContext.java new file mode 100644 index 0000000000..2b942ddc1f --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/el/VariablesELContext.java @@ -0,0 +1,57 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.engine.messageinterpolation.el; + +import javax.el.ArrayELResolver; +import javax.el.CompositeELResolver; +import javax.el.ELResolver; +import javax.el.ExpressionFactory; +import javax.el.ListELResolver; +import javax.el.MapELResolver; +import javax.el.ResourceBundleELResolver; +import javax.el.StandardELContext; + +/** + * @author Guillaume Smet + */ +public class VariablesELContext extends StandardELContext { + + private static final ELResolver DEFAULT_RESOLVER = new CompositeELResolver() { + + { + add( new RootResolver() ); + add( new ArrayELResolver( true ) ); + add( new ListELResolver( true ) ); + add( new MapELResolver( true ) ); + add( new ResourceBundleELResolver() ); + // this one is required so that expressions containing method calls are returned as is + // if not there, the expression is replaced by an empty string + add( new NoOpElResolver() ); + } + }; + + public VariablesELContext(ExpressionFactory expressionFactory) { + super( expressionFactory ); + + // In javax.el.ELContext, the ExpressionFactory is extracted from the context map. If it is not found, it + // defaults to ELUtil.getExpressionFactory() which, if we provided the ExpressionFactory to the + // ResourceBundleMessageInterpolator, might not be the same. Thus, we inject the ExpressionFactory in the + // context. + putContext( ExpressionFactory.class, expressionFactory ); + } + + @Override + public void addELResolver(ELResolver cELResolver) { + throw new UnsupportedOperationException( getClass().getSimpleName() + " does not support addELResolver." ); + } + + @Override + public ELResolver getELResolver() { + return DEFAULT_RESOLVER; + } + +} diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java index 3c99e31613..361d2bf65f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/AbstractValidationContext.java @@ -35,6 +35,7 @@ import org.hibernate.validator.internal.util.logging.Log; import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.internal.util.stereotypes.Lazy; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; /** * Context object keeping track of all required data for a validation call. @@ -229,7 +230,8 @@ public void addConstraintFailure( String messageTemplate = constraintViolationCreationContext.getMessage(); String interpolatedMessage = interpolate( messageTemplate, - constraintViolationCreationContext.isExpressionLanguageEnabled(), + constraintViolationCreationContext.getExpressionLanguageFeatureLevel(), + constraintViolationCreationContext.isCustomViolation(), valueContext.getCurrentValidatedValue(), descriptor, constraintViolationCreationContext.getPath(), @@ -287,7 +289,9 @@ public ConstraintValidatorContextImpl createConstraintValidatorContextFor(Constr validatorScopedContext.getClockProvider(), path, constraintDescriptor, - validatorScopedContext.getConstraintValidatorPayload() + validatorScopedContext.getConstraintValidatorPayload(), + validatorScopedContext.getConstraintExpressionLanguageFeatureLevel(), + validatorScopedContext.getCustomViolationExpressionLanguageFeatureLevel() ); } @@ -296,7 +300,8 @@ public ConstraintValidatorContextImpl createConstraintValidatorContextFor(Constr private String interpolate( String messageTemplate, - boolean expressionLanguageEnabled, + ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel, + boolean customViolation, Object validatedValue, ConstraintDescriptor descriptor, Path path, @@ -309,7 +314,8 @@ private String interpolate( path, messageParameters, expressionVariables, - expressionLanguageEnabled + expressionLanguageFeatureLevel, + customViolation ); try { diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ParameterExecutableValidationContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ParameterExecutableValidationContext.java index e1fe98b70c..fc08e920b4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ParameterExecutableValidationContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ParameterExecutableValidationContext.java @@ -102,7 +102,9 @@ public ConstraintValidatorContextImpl createConstraintValidatorContextFor(Constr validatorScopedContext.getClockProvider(), path, constraintDescriptor, - validatorScopedContext.getConstraintValidatorPayload() + validatorScopedContext.getConstraintValidatorPayload(), + validatorScopedContext.getConstraintExpressionLanguageFeatureLevel(), + validatorScopedContext.getCustomViolationExpressionLanguageFeatureLevel() ); } @@ -110,7 +112,9 @@ public ConstraintValidatorContextImpl createConstraintValidatorContextFor(Constr validatorScopedContext.getClockProvider(), path, constraintDescriptor, - validatorScopedContext.getConstraintValidatorPayload() + validatorScopedContext.getConstraintValidatorPayload(), + validatorScopedContext.getConstraintExpressionLanguageFeatureLevel(), + validatorScopedContext.getCustomViolationExpressionLanguageFeatureLevel() ); } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidatorScopedContext.java b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidatorScopedContext.java index 04953bc7b7..0e78c05025 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidatorScopedContext.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/validationcontext/ValidatorScopedContext.java @@ -14,6 +14,7 @@ import org.hibernate.validator.internal.engine.ValidatorFactoryScopedContext; import org.hibernate.validator.internal.util.ExecutableParameterNameProvider; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; import org.hibernate.validator.spi.scripting.ScriptEvaluatorFactory; /** @@ -65,6 +66,16 @@ public class ValidatorScopedContext { */ private final Object constraintValidatorPayload; + /** + * Hibernate Validator specific flag to define Expression Language feature levels for constraints. + */ + private final ExpressionLanguageFeatureLevel constraintExpressionLanguageFeatureLevel; + + /** + * Hibernate Validator specific flag to define Expression Language feature levels for custom violations. + */ + private final ExpressionLanguageFeatureLevel customViolationExpressionLanguageFeatureLevel; + public ValidatorScopedContext(ValidatorFactoryScopedContext validatorFactoryScopedContext) { this.messageInterpolator = validatorFactoryScopedContext.getMessageInterpolator(); this.parameterNameProvider = validatorFactoryScopedContext.getParameterNameProvider(); @@ -74,6 +85,8 @@ public ValidatorScopedContext(ValidatorFactoryScopedContext validatorFactoryScop this.failFast = validatorFactoryScopedContext.isFailFast(); this.traversableResolverResultCacheEnabled = validatorFactoryScopedContext.isTraversableResolverResultCacheEnabled(); this.constraintValidatorPayload = validatorFactoryScopedContext.getConstraintValidatorPayload(); + this.constraintExpressionLanguageFeatureLevel = validatorFactoryScopedContext.getConstraintExpressionLanguageFeatureLevel(); + this.customViolationExpressionLanguageFeatureLevel = validatorFactoryScopedContext.getCustomViolationExpressionLanguageFeatureLevel(); } public MessageInterpolator getMessageInterpolator() { @@ -107,4 +120,12 @@ public boolean isTraversableResolverResultCacheEnabled() { public Object getConstraintValidatorPayload() { return this.constraintValidatorPayload; } + + public ExpressionLanguageFeatureLevel getConstraintExpressionLanguageFeatureLevel() { + return this.constraintExpressionLanguageFeatureLevel; + } + + public ExpressionLanguageFeatureLevel getCustomViolationExpressionLanguageFeatureLevel() { + return customViolationExpressionLanguageFeatureLevel; + } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java index 2f33852238..7b4bfce17a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java @@ -63,6 +63,7 @@ import org.hibernate.validator.internal.util.logging.formatter.ObjectArrayFormatter; import org.hibernate.validator.internal.util.logging.formatter.TypeFormatter; import org.hibernate.validator.internal.xml.mapping.ContainerElementTypePath; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; import org.hibernate.validator.spi.messageinterpolation.LocaleResolver; import org.hibernate.validator.spi.nodenameprovider.PropertyNodeNameProvider; import org.hibernate.validator.spi.properties.GetterPropertySelectionStrategy; @@ -912,4 +913,29 @@ ConstraintDefinitionException getConstraintValidatorDefinitionConstraintMismatch @LogMessage(level = WARN) @Message(id = 257, value = "Expression variables have been defined for constraint %1$s while Expression Language is not enabled.") void expressionVariablesDefinedWithExpressionLanguageNotEnabled(Class constraintAnnotation); + + @Message(id = 258, value = "Expressions should not be resolved when Expression Language features are disabled.") + IllegalStateException expressionsNotResolvedWhenExpressionLanguageFeaturesDisabled(); + + @Message(id = 259, value = "Provided Expression Language feature level is not supported.") + IllegalStateException expressionsLanguageFeatureLevelNotSupported(); + + @LogMessage(level = DEBUG) + @Message(id = 260, value = "Expression Language feature level for constraints set to %1$s.") + void logConstraintExpressionLanguageFeatureLevel(ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel); + + @LogMessage(level = DEBUG) + @Message(id = 261, value = "Expression Language feature level for custom violations set to %1$s.") + void logCustomViolationExpressionLanguageFeatureLevel(ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel); + + @Message(id = 262, value = "Unable to find an expression language feature level for value %s.") + ValidationException invalidExpressionLanguageFeatureLevelValue(String expressionLanguageFeatureLevelName, @Cause IllegalArgumentException e); + + @LogMessage(level = WARN) + @Message(id = 263, value = "EL expression '%s' references an unknown method.") + void unknownMethodInExpressionLanguage(String expression, @Cause Exception e); + + @LogMessage(level = ERROR) + @Message(id = 264, value = "Unable to interpolate EL expression '%s' as it uses a disabled feature.") + void disabledFeatureInExpressionLanguage(String expression, @Cause Exception e); } diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java index 34054ff2a4..d25992dba4 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java @@ -416,7 +416,7 @@ private String interpolateMessage(String message, Context context, Locale locale // HibernateMessageInterpolatorContext // but it can be a spec Context in the Jakarta Bean Validation TCK. if ( !( context instanceof HibernateMessageInterpolatorContext ) - || ( (HibernateMessageInterpolatorContext) context ).isExpressionLanguageEnabled() ) { + || ( (HibernateMessageInterpolatorContext) context ).getExpressionLanguageFeatureLevel() != ExpressionLanguageFeatureLevel.NONE ) { resolvedMessage = interpolateExpression( new TokenIterator( getParameterTokens( resolvedMessage, tokenizedELMessages, InterpolationTermType.EL ) ), context, @@ -527,7 +527,7 @@ private String interpolateExpression(TokenIterator tokenIterator, Context contex return tokenIterator.getInterpolatedMessage(); } - public abstract String interpolate(Context context, Locale locale, String term); + protected abstract String interpolate(Context context, Locale locale, String term); private String resolveParameter(String parameterName, ResourceBundle bundle, Locale locale, boolean recursive) throws MessageDescriptorFormatException { diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ExpressionLanguageFeatureLevel.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ExpressionLanguageFeatureLevel.java new file mode 100644 index 0000000000..bbb5ca9795 --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ExpressionLanguageFeatureLevel.java @@ -0,0 +1,90 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.messageinterpolation; + +import org.hibernate.validator.Incubating; +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorContext; + +/** + * Indicates the level of features enabled for the Expression Language engine. + * + * @since 6.2 + */ +@Incubating +public enum ExpressionLanguageFeatureLevel { + + /** + * The default Expression Language feature level. + *

    + * Depends on the context. + *

    + * For standard constraint messages, it is {@link ExpressionLanguageFeatureLevel#BEAN_PROPERTIES}. + *

    + * For custom violations, the default is {@link ExpressionLanguageFeatureLevel#NONE} and, if Expression Language is + * enabled for a given custom violation via the API, the default becomes + * {@link ExpressionLanguageFeatureLevel#VARIABLES} in the context of this given custom violation. + */ + DEFAULT("default"), + + /** + * Expression Language expressions are not interpolated. + */ + NONE("none"), + + /** + * Only allows access to the variables injected via + * {@link HibernateConstraintValidatorContext#addExpressionVariable(String, Object)}, the Jakarta Bean + * Validation-defined {@code formatter} and the {@code ResourceBundle}s. + */ + VARIABLES("variables"), + + /** + * Only allows to what is allowed with the {@code variables} level plus access to bean properties. + *

    + * This is the minimal level to have a specification-compliant implementation. + */ + BEAN_PROPERTIES("bean-properties"), + + /** + * This level allows what is allowed with the {@code bean-properties} level plus bean methods execution and can lead + * to serious security issues, including arbitrary code execution, if not very carefully handled. + *

    + * If using this level, you need to be sure you are not injecting user input in an expression without properly + * escaping it using {@link HibernateConstraintValidatorContext#addExpressionVariable(String, Object)}. + */ + BEAN_METHODS("bean-methods"); + + private final String externalRepresentation; + + ExpressionLanguageFeatureLevel(String externalRepresentation) { + this.externalRepresentation = externalRepresentation; + } + + public static ExpressionLanguageFeatureLevel of(String value) { + for ( ExpressionLanguageFeatureLevel level : values() ) { + if ( level.externalRepresentation.equals( value ) ) { + return level; + } + } + + return ExpressionLanguageFeatureLevel.valueOf( value ); + } + + public static ExpressionLanguageFeatureLevel interpretDefaultForConstraints(ExpressionLanguageFeatureLevel value) { + if ( value == DEFAULT ) { + return BEAN_PROPERTIES; + } + return value; + } + + public static ExpressionLanguageFeatureLevel interpretDefaultForCustomViolations(ExpressionLanguageFeatureLevel value) { + if ( value == DEFAULT ) { + return VARIABLES; + } + return value; + } +} diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/HibernateMessageInterpolatorContext.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/HibernateMessageInterpolatorContext.java index e398aa4fd9..a5644f5d19 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/HibernateMessageInterpolatorContext.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/HibernateMessageInterpolatorContext.java @@ -50,9 +50,9 @@ public interface HibernateMessageInterpolatorContext extends MessageInterpolator Path getPropertyPath(); /** - * @return if Expression Language should be enabled if supported by the {@code MessageInterpolator}. + * @return the level of features enabled for the Expression Language engine * - * @return 6.1.7 + * @since 6.2 */ - boolean isExpressionLanguageEnabled(); + ExpressionLanguageFeatureLevel getExpressionLanguageFeatureLevel(); } diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java index 41c24e9cd5..0cd1c7f573 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ParameterMessageInterpolator.java @@ -52,7 +52,7 @@ public ParameterMessageInterpolator(Set locales, Locale defaultLocale, L } @Override - public String interpolate(Context context, Locale locale, String term) { + protected String interpolate(Context context, Locale locale, String term) { if ( InterpolationTerm.isElExpression( term ) ) { LOG.warnElIsUnsupported( term ); return term; diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java index 9c8646539f..b92e2a25ec 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java @@ -154,7 +154,7 @@ public ResourceBundleMessageInterpolator(ResourceBundleLocator userResourceBundl } @Override - public String interpolate(Context context, Locale locale, String term) { + protected String interpolate(Context context, Locale locale, String term) { InterpolationTerm expression = new InterpolationTerm( term, locale, expressionFactory ); return expression.interpolate( context ); } diff --git a/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextImplTest.java b/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextImplTest.java index 436536db8f..24925974e8 100644 --- a/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextImplTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextImplTest.java @@ -21,6 +21,7 @@ import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintViolationCreationContext; import org.hibernate.validator.internal.engine.path.PathImpl; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; import org.hibernate.validator.testutil.ConstraintViolationAssert.PathExpectation; import org.testng.annotations.Test; @@ -226,7 +227,8 @@ private ConstraintValidatorContextImpl createEmptyConstraintValidatorContextImpl PathImpl path = PathImpl.createRootPath(); path.addBeanNode(); - ConstraintValidatorContextImpl context = new ConstraintValidatorContextImpl( null, path, null, null ); + ConstraintValidatorContextImpl context = new ConstraintValidatorContextImpl( null, path, null, null, ExpressionLanguageFeatureLevel.BEAN_PROPERTIES, + ExpressionLanguageFeatureLevel.NONE ); context.disableDefaultConstraintViolation(); return context; } diff --git a/engine/src/test/java/org/hibernate/validator/test/el/ConstraintExpressionLanguageFeatureLevelTest.java b/engine/src/test/java/org/hibernate/validator/test/el/ConstraintExpressionLanguageFeatureLevelTest.java new file mode 100644 index 0000000000..6370b842d8 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/el/ConstraintExpressionLanguageFeatureLevelTest.java @@ -0,0 +1,257 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.el; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import javax.validation.Payload; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; + +import org.hibernate.validator.HibernateValidator; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; +import org.hibernate.validator.testutil.TestForIssue; +import org.hibernate.validator.testutil.ValidationXmlTestHelper; +import org.hibernate.validator.testutils.ValidatorUtil; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * @author Guillaume Smet + */ +@TestForIssue(jiraKey = "HV-1816") +public class ConstraintExpressionLanguageFeatureLevelTest { + + private static ValidationXmlTestHelper validationXmlTestHelper; + + @BeforeClass + public static void setupValidationXmlTestHelper() { + validationXmlTestHelper = new ValidationXmlTestHelper( ConstraintExpressionLanguageFeatureLevelTest.class ); + } + + @Test + public void default_expression_language_feature_level() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .buildValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + + assertThat( validator.validate( new VariablesBean( "value" ) ) ) + .containsOnlyViolations( violationOf( VariablesConstraint.class ).withMessage( "Variable: value" ) ); + assertThat( validator.validate( new BeanPropertiesBean( "value" ) ) ) + .containsOnlyViolations( violationOf( BeanPropertiesConstraint.class ).withMessage( "Bean property: 118" ) ); + assertThat( validator.validate( new BeanMethodsBean() ) ) + .containsOnlyViolations( violationOf( BeanMethodsConstraint.class ).withMessage( "Method execution: ${'aaaa'.substring(0, 1)}" ) ); + } + + @Test + public void none_expression_language_feature_level() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .constraintExpressionLanguageFeatureLevel( ExpressionLanguageFeatureLevel.NONE ) + .buildValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + + assertThat( validator.validate( new VariablesBean( "value" ) ) ) + .containsOnlyViolations( violationOf( VariablesConstraint.class ).withMessage( "Variable: ${validatedValue}" ) ); + assertThat( validator.validate( new BeanPropertiesBean( "value" ) ) ) + .containsOnlyViolations( violationOf( BeanPropertiesConstraint.class ).withMessage( "Bean property: ${validatedValue.bytes[0]}" ) ); + assertThat( validator.validate( new BeanMethodsBean() ) ) + .containsOnlyViolations( violationOf( BeanMethodsConstraint.class ).withMessage( "Method execution: ${'aaaa'.substring(0, 1)}" ) ); + } + + @Test + public void variables_expression_language_feature_level() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .constraintExpressionLanguageFeatureLevel( ExpressionLanguageFeatureLevel.VARIABLES ) + .buildValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + + assertThat( validator.validate( new VariablesBean( "value" ) ) ) + .containsOnlyViolations( violationOf( VariablesConstraint.class ).withMessage( "Variable: value" ) ); + assertThat( validator.validate( new BeanPropertiesBean( "value" ) ) ) + .containsOnlyViolations( violationOf( BeanPropertiesConstraint.class ).withMessage( "Bean property: ${validatedValue.bytes[0]}" ) ); + assertThat( validator.validate( new BeanMethodsBean() ) ) + .containsOnlyViolations( violationOf( BeanMethodsConstraint.class ).withMessage( "Method execution: ${'aaaa'.substring(0, 1)}" ) ); + } + + @Test + public void bean_properties_expression_language_feature_level() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .constraintExpressionLanguageFeatureLevel( ExpressionLanguageFeatureLevel.BEAN_PROPERTIES ) + .buildValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + + assertThat( validator.validate( new VariablesBean( "value" ) ) ) + .containsOnlyViolations( violationOf( VariablesConstraint.class ).withMessage( "Variable: value" ) ); + assertThat( validator.validate( new BeanPropertiesBean( "value" ) ) ) + .containsOnlyViolations( violationOf( BeanPropertiesConstraint.class ).withMessage( "Bean property: 118" ) ); + assertThat( validator.validate( new BeanMethodsBean() ) ) + .containsOnlyViolations( violationOf( BeanMethodsConstraint.class ).withMessage( "Method execution: ${'aaaa'.substring(0, 1)}" ) ); + } + + @Test + public void bean_methods_expression_language_feature_level() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .constraintExpressionLanguageFeatureLevel( ExpressionLanguageFeatureLevel.BEAN_METHODS ) + .buildValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + + assertThat( validator.validate( new VariablesBean( "value" ) ) ) + .containsOnlyViolations( violationOf( VariablesConstraint.class ).withMessage( "Variable: value" ) ); + assertThat( validator.validate( new BeanPropertiesBean( "value" ) ) ) + .containsOnlyViolations( violationOf( BeanPropertiesConstraint.class ).withMessage( "Bean property: 118" ) ); + assertThat( validator.validate( new BeanMethodsBean() ) ) + .containsOnlyViolations( violationOf( BeanMethodsConstraint.class ).withMessage( "Method execution: a" ) ); + } + + @Test + public void property_default_value() { + validationXmlTestHelper.runWithCustomValidationXml( + "validation-constraints-default.xml", new Runnable() { + + @Override + public void run() { + Validator validator = ValidatorUtil.getValidator(); + + assertThat( validator.validate( new VariablesBean( "value" ) ) ) + .containsOnlyViolations( violationOf( VariablesConstraint.class ).withMessage( "Variable: value" ) ); + assertThat( validator.validate( new BeanPropertiesBean( "value" ) ) ) + .containsOnlyViolations( violationOf( BeanPropertiesConstraint.class ).withMessage( "Bean property: 118" ) ); + assertThat( validator.validate( new BeanMethodsBean() ) ) + .containsOnlyViolations( violationOf( BeanMethodsConstraint.class ).withMessage( "Method execution: ${'aaaa'.substring(0, 1)}" ) ); + } + } ); + } + + @Test + public void property_bean_methods() { + validationXmlTestHelper.runWithCustomValidationXml( + "validation-constraints-bean-methods.xml", new Runnable() { + + @Override + public void run() { + Validator validator = ValidatorUtil.getValidator(); + + assertThat( validator.validate( new VariablesBean( "value" ) ) ) + .containsOnlyViolations( violationOf( VariablesConstraint.class ).withMessage( "Variable: value" ) ); + assertThat( validator.validate( new BeanPropertiesBean( "value" ) ) ) + .containsOnlyViolations( violationOf( BeanPropertiesConstraint.class ).withMessage( "Bean property: 118" ) ); + assertThat( validator.validate( new BeanMethodsBean() ) ) + .containsOnlyViolations( violationOf( BeanMethodsConstraint.class ).withMessage( "Method execution: a" ) ); + } + } ); + } + + @Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE }) + @Retention(RUNTIME) + @Documented + @Constraint(validatedBy = { VariablesStringValidator.class }) + private @interface VariablesConstraint { + String message() default "Variable: ${validatedValue}"; + + Class[] groups() default { }; + + Class[] payload() default { }; + } + + public static class VariablesStringValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + return false; + } + } + + public static class VariablesBean { + + public VariablesBean(String value) { + this.value = value; + } + + @VariablesConstraint + public String value; + } + + @Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE }) + @Retention(RUNTIME) + @Documented + @Constraint(validatedBy = { BeanPropertiesConstraintStringValidator.class }) + private @interface BeanPropertiesConstraint { + String message() default "Bean property: ${validatedValue.bytes[0]}"; + + Class[] groups() default { }; + + Class[] payload() default { }; + } + + public static class BeanPropertiesConstraintStringValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + return false; + } + } + + public static class BeanPropertiesBean { + + public BeanPropertiesBean(String value) { + this.value = value; + } + + @BeanPropertiesConstraint + public String value; + } + + @Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE }) + @Retention(RUNTIME) + @Documented + @Constraint(validatedBy = { BeanMethodsConstraintStringValidator.class }) + private @interface BeanMethodsConstraint { + String message() default "Method execution: ${'aaaa'.substring(0, 1)}"; + + Class[] groups() default { }; + + Class[] payload() default { }; + } + + public static class BeanMethodsConstraintStringValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + return false; + } + } + + public static class BeanMethodsBean { + + @BeanMethodsConstraint + public String value; + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/el/CustomViolationExpressionLanguageFeatureLevelTest.java b/engine/src/test/java/org/hibernate/validator/test/el/CustomViolationExpressionLanguageFeatureLevelTest.java new file mode 100644 index 0000000000..01a49f89ac --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/el/CustomViolationExpressionLanguageFeatureLevelTest.java @@ -0,0 +1,388 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.el; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; +import static org.testng.Assert.assertTrue; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import javax.validation.Payload; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.Logger; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.test.appender.ListAppender; +import org.hibernate.validator.HibernateValidator; +import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorContext; +import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; +import org.hibernate.validator.testutil.TestForIssue; +import org.hibernate.validator.testutil.ValidationXmlTestHelper; +import org.hibernate.validator.testutils.ValidatorUtil; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +/** + * @author Guillaume Smet + */ +@TestForIssue(jiraKey = "HV-1816") +public class CustomViolationExpressionLanguageFeatureLevelTest { + + private static ValidationXmlTestHelper validationXmlTestHelper; + + private ListAppender constraintValidatorContextImplLoglistAppender; + + + @BeforeClass + public static void setupValidationXmlTestHelper() { + validationXmlTestHelper = new ValidationXmlTestHelper( ConstraintExpressionLanguageFeatureLevelTest.class ); + } + + @BeforeTest + public void setUp() { + LoggerContext context = LoggerContext.getContext( false ); + Logger logger = context.getLogger( ConstraintValidatorContextImpl.class.getName() ); + constraintValidatorContextImplLoglistAppender = (ListAppender) logger.getAppenders().get( "List" ); + constraintValidatorContextImplLoglistAppender.clear(); + } + + @AfterTest + public void tearDown() { + constraintValidatorContextImplLoglistAppender.clear(); + } + + @Test + public void default_behavior() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .buildValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + + assertThat( validator.validate( new DefaultLevelBean() ) ) + .containsOnlyViolations( violationOf( DefaultLevelConstraint.class ).withMessage( "Variable: ${validatedValue}" ), + violationOf( DefaultLevelConstraint.class ).withMessage( "Bean property: ${validatedValue.bytes[0]}" ), + violationOf( DefaultLevelConstraint.class ).withMessage( "Method execution: ${'aaaa'.substring(0, 1)}" ) ); + } + + @Test + public void enable_el() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .buildValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + + assertThat( validator.validate( new EnableELBean( "value" ) ) ) + .containsOnlyViolations( violationOf( EnableELConstraint.class ).withMessage( "Variable: value" ), + violationOf( EnableELConstraint.class ).withMessage( "Bean property: ${validatedValue.bytes[0]}" ), + violationOf( EnableELConstraint.class ).withMessage( "Method execution: ${'aaaa'.substring(0, 1)}" ) ); + } + + @Test + public void enable_el_bean_properties() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .buildValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + + assertThat( validator.validate( new EnableELBeanPropertiesBean( "value" ) ) ) + .containsOnlyViolations( violationOf( EnableELBeanPropertiesConstraint.class ).withMessage( "Variable: value" ), + violationOf( EnableELBeanPropertiesConstraint.class ).withMessage( "Bean property: 118" ), + violationOf( EnableELBeanPropertiesConstraint.class ).withMessage( "Method execution: ${'aaaa'.substring(0, 1)}" ) ); + } + + @Test + public void enable_el_bean_methods() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .buildValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + + assertThat( validator.validate( new EnableELBeanMethodsBean( "value" ) ) ) + .containsOnlyViolations( violationOf( EnableELBeanMethodsConstraint.class ).withMessage( "Variable: value" ), + violationOf( EnableELBeanMethodsConstraint.class ).withMessage( "Bean property: 118" ), + violationOf( EnableELBeanMethodsConstraint.class ).withMessage( "Method execution: a" ) ); + } + + @Test + public void warn_when_default_behavior_and_expression_variables() { + ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) + .configure() + .buildValidatorFactory(); + + Validator validator = validatorFactory.getValidator(); + + assertThat( validator.validate( new DefaultLevelWithExpressionVariablesBean() ) ) + .containsOnlyViolations( violationOf( DefaultLevelWithExpressionVariablesConstraint.class ).withMessage( "Variable: ${myVariable}" ) ); + + assertTrue( constraintValidatorContextImplLoglistAppender.getEvents().stream() + .filter( event -> event.getLevel().equals( Level.WARN ) ) + .map( event -> event.getMessage().getFormattedMessage() ) + .anyMatch( m -> m.startsWith( "HV000257" ) ) ); + } + + @Test + public void property_default_value() { + validationXmlTestHelper.runWithCustomValidationXml( + "validation-custom-violations-default.xml", new Runnable() { + + @Override + public void run() { + Validator validator = ValidatorUtil.getValidator(); + + assertThat( validator.validate( new EnableELBean( "value" ) ) ) + .containsOnlyViolations( violationOf( EnableELConstraint.class ).withMessage( "Variable: value" ), + violationOf( EnableELConstraint.class ).withMessage( "Bean property: ${validatedValue.bytes[0]}" ), + violationOf( EnableELConstraint.class ).withMessage( "Method execution: ${'aaaa'.substring(0, 1)}" ) ); + } + } ); + } + + @Test + public void property_bean_methods() { + validationXmlTestHelper.runWithCustomValidationXml( + "validation-custom-violations-bean-methods.xml", new Runnable() { + + @Override + public void run() { + Validator validator = ValidatorUtil.getValidator(); + + assertThat( validator.validate( new EnableELBeanMethodsBean( "value" ) ) ) + .containsOnlyViolations( violationOf( EnableELBeanMethodsConstraint.class ).withMessage( "Variable: value" ), + violationOf( EnableELBeanMethodsConstraint.class ).withMessage( "Bean property: 118" ), + violationOf( EnableELBeanMethodsConstraint.class ).withMessage( "Method execution: a" ) ); + } + } ); + } + + @Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE }) + @Retention(RUNTIME) + @Documented + @Constraint(validatedBy = { DefaultLevelStringValidator.class }) + private @interface DefaultLevelConstraint { + + String message() default "-"; + + Class[] groups() default {}; + + Class[] payload() default {}; + } + + public static class DefaultLevelStringValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + HibernateConstraintValidatorContext hibernateContext = (HibernateConstraintValidatorContext) context; + + hibernateContext.disableDefaultConstraintViolation(); + + hibernateContext.buildConstraintViolationWithTemplate( "Variable: ${validatedValue}" ).addConstraintViolation(); + hibernateContext.buildConstraintViolationWithTemplate( "Bean property: ${validatedValue.bytes[0]}" ).addConstraintViolation(); + hibernateContext.buildConstraintViolationWithTemplate( "Method execution: ${'aaaa'.substring(0, 1)}" ).addConstraintViolation(); + + return false; + } + } + + public static class DefaultLevelBean { + + @DefaultLevelConstraint + public String value; + } + + @Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE }) + @Retention(RUNTIME) + @Documented + @Constraint(validatedBy = { EnableELStringValidator.class }) + private @interface EnableELConstraint { + + String message() default "-"; + + Class[] groups() default {}; + + Class[] payload() default {}; + } + + public static class EnableELStringValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + HibernateConstraintValidatorContext hibernateContext = (HibernateConstraintValidatorContext) context; + + hibernateContext.disableDefaultConstraintViolation(); + + hibernateContext.buildConstraintViolationWithTemplate( "Variable: ${validatedValue}" ) + .enableExpressionLanguage() + .addConstraintViolation(); + hibernateContext.buildConstraintViolationWithTemplate( "Bean property: ${validatedValue.bytes[0]}" ) + .enableExpressionLanguage() + .addConstraintViolation(); + hibernateContext.buildConstraintViolationWithTemplate( "Method execution: ${'aaaa'.substring(0, 1)}" ) + .enableExpressionLanguage() + .addConstraintViolation(); + + return false; + } + } + + public static class EnableELBean { + + public EnableELBean(String value) { + this.value = value; + } + + @EnableELConstraint + public String value; + } + + @Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE }) + @Retention(RUNTIME) + @Documented + @Constraint(validatedBy = { EnableELBeanPropertiesStringValidator.class }) + private @interface EnableELBeanPropertiesConstraint { + + String message() default "-"; + + Class[] groups() default {}; + + Class[] payload() default {}; + } + + public static class EnableELBeanPropertiesStringValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + HibernateConstraintValidatorContext hibernateContext = (HibernateConstraintValidatorContext) context; + + hibernateContext.disableDefaultConstraintViolation(); + + hibernateContext.buildConstraintViolationWithTemplate( "Variable: ${validatedValue}" ) + .enableExpressionLanguage( ExpressionLanguageFeatureLevel.BEAN_PROPERTIES ) + .addConstraintViolation(); + hibernateContext.buildConstraintViolationWithTemplate( "Bean property: ${validatedValue.bytes[0]}" ) + .enableExpressionLanguage( ExpressionLanguageFeatureLevel.BEAN_PROPERTIES ) + .addConstraintViolation(); + hibernateContext.buildConstraintViolationWithTemplate( "Method execution: ${'aaaa'.substring(0, 1)}" ) + .enableExpressionLanguage( ExpressionLanguageFeatureLevel.BEAN_PROPERTIES ) + .addConstraintViolation(); + + return false; + } + } + + public static class EnableELBeanPropertiesBean { + + public EnableELBeanPropertiesBean(String value) { + this.value = value; + } + + @EnableELBeanPropertiesConstraint + public String value; + } + + @Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE }) + @Retention(RUNTIME) + @Documented + @Constraint(validatedBy = { EnableELBeanMethodsStringValidator.class }) + private @interface EnableELBeanMethodsConstraint { + + String message() default "-"; + + Class[] groups() default {}; + + Class[] payload() default {}; + } + + public static class EnableELBeanMethodsStringValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + HibernateConstraintValidatorContext hibernateContext = (HibernateConstraintValidatorContext) context; + + hibernateContext.disableDefaultConstraintViolation(); + + hibernateContext.buildConstraintViolationWithTemplate( "Variable: ${validatedValue}" ) + .enableExpressionLanguage( ExpressionLanguageFeatureLevel.BEAN_METHODS ) + .addConstraintViolation(); + hibernateContext.buildConstraintViolationWithTemplate( "Bean property: ${validatedValue.bytes[0]}" ) + .enableExpressionLanguage( ExpressionLanguageFeatureLevel.BEAN_METHODS ) + .addConstraintViolation(); + hibernateContext.buildConstraintViolationWithTemplate( "Method execution: ${'aaaa'.substring(0, 1)}" ) + .enableExpressionLanguage( ExpressionLanguageFeatureLevel.BEAN_METHODS ) + .addConstraintViolation(); + + return false; + } + } + + public static class EnableELBeanMethodsBean { + + public EnableELBeanMethodsBean(String value) { + this.value = value; + } + + @EnableELBeanMethodsConstraint + public String value; + } + + @Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE }) + @Retention(RUNTIME) + @Documented + @Constraint(validatedBy = { DefaultLevelWithExpressionVariablesStringValidator.class }) + private @interface DefaultLevelWithExpressionVariablesConstraint { + + String message() default "-"; + + Class[] groups() default {}; + + Class[] payload() default {}; + } + + public static class DefaultLevelWithExpressionVariablesStringValidator + implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + HibernateConstraintValidatorContext hibernateContext = (HibernateConstraintValidatorContext) context; + + hibernateContext.disableDefaultConstraintViolation(); + + hibernateContext + .addExpressionVariable( "myVariable", "value" ) + .buildConstraintViolationWithTemplate( "Variable: ${myVariable}" ) + .addConstraintViolation(); + + return false; + } + } + + public static class DefaultLevelWithExpressionVariablesBean { + + @DefaultLevelWithExpressionVariablesConstraint + public String value; + } +} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java index be94c108d3..6f75a91b19 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ExpressionLanguageMessageInterpolationTest.java @@ -20,6 +20,7 @@ import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; import org.hibernate.validator.testutil.TestForIssue; import org.testng.annotations.BeforeTest; @@ -69,13 +70,52 @@ public void testExpressionLanguageGraphNavigation() { null, Collections.emptyMap(), Collections.emptyMap(), - true ); + ExpressionLanguageFeatureLevel.BEAN_METHODS, + false ); String expected = "18"; String actual = interpolatorUnderTest.interpolate( "${validatedValue.age}", context ); assertEquals( actual, expected, "Wrong substitution" ); } + @Test + public void testExpressionLanguageGraphNavigationBeanProperties() { + User user = new User(); + user.setAge( 18 ); + MessageInterpolator.Context context = new MessageInterpolatorContext( + notNullDescriptor, + user, + null, + null, + Collections.emptyMap(), + Collections.emptyMap(), + ExpressionLanguageFeatureLevel.BEAN_PROPERTIES, + false ); + + String expected = "18"; + String actual = interpolatorUnderTest.interpolate( "${validatedValue.age}", context ); + assertEquals( actual, expected, "Wrong substitution" ); + } + + @Test + public void testExpressionLanguageGraphNavigationVariables() { + User user = new User(); + user.setAge( 18 ); + MessageInterpolator.Context context = new MessageInterpolatorContext( + notNullDescriptor, + user, + null, + null, + Collections.emptyMap(), + Collections.emptyMap(), + ExpressionLanguageFeatureLevel.VARIABLES, + false ); + + String expected = "${validatedValue.age}"; + String actual = interpolatorUnderTest.interpolate( "${validatedValue.age}", context ); + assertEquals( actual, expected, "Wrong substitution" ); + } + @Test public void testUnknownPropertyInExpressionLanguageGraphNavigation() { MessageInterpolator.Context context = new MessageInterpolatorContext( @@ -85,7 +125,8 @@ public void testUnknownPropertyInExpressionLanguageGraphNavigation() { null, Collections.emptyMap(), Collections.emptyMap(), - true ); + ExpressionLanguageFeatureLevel.BEAN_METHODS, + false ); String expected = "${validatedValue.foo}"; String actual = interpolatorUnderTest.interpolate( "${validatedValue.foo}", context ); @@ -94,7 +135,7 @@ public void testUnknownPropertyInExpressionLanguageGraphNavigation() { @Test public void testNullValidatedValue() { - MessageInterpolator.Context context = createMessageInterpolatorContext( notNullDescriptor ); + MessageInterpolator.Context context = createMessageInterpolatorContextELBeanMethods( notNullDescriptor ); String expected = "Validated value was null"; String actual = interpolatorUnderTest.interpolate( @@ -106,7 +147,7 @@ public void testNullValidatedValue() { @Test public void testExpressionAndParameterInterpolationInSameMessageDescriptor() { - MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor ); + MessageInterpolator.Context context = createMessageInterpolatorContextELBeanMethods( sizeDescriptor ); String expected = "2 0 2147483647"; String actual = interpolatorUnderTest.interpolate( "${1+1} {min} {max}", context ); @@ -115,7 +156,7 @@ public void testExpressionAndParameterInterpolationInSameMessageDescriptor() { @Test public void testEscapedExpressionLanguage() { - MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor ); + MessageInterpolator.Context context = createMessageInterpolatorContextELBeanMethods( sizeDescriptor ); String expected = "${1+1}"; String actual = interpolatorUnderTest.interpolate( "\\${1+1}", context ); @@ -124,7 +165,7 @@ public void testEscapedExpressionLanguage() { @Test public void testTernaryExpressionLanguageOperator() { - MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor ); + MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor, ExpressionLanguageFeatureLevel.VARIABLES ); String expected = "foo"; String actual = interpolatorUnderTest.interpolate( "${min == 0 ? 'foo' : 'bar'}", context ); @@ -133,7 +174,7 @@ public void testTernaryExpressionLanguageOperator() { @Test public void testParameterFormatting() { - MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor ); + MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor, ExpressionLanguageFeatureLevel.VARIABLES ); String expected = "Max 2147483647, min 0"; String actual = interpolatorUnderTest.interpolate( "${formatter.format('Max %s, min %s', max, min)}", context ); @@ -142,7 +183,7 @@ public void testParameterFormatting() { @Test public void testLiteralStaysUnchanged() { - MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor ); + MessageInterpolator.Context context = createMessageInterpolatorContextELBeanMethods( sizeDescriptor ); String expected = "foo"; String actual = interpolatorUnderTest.interpolate( "foo", context ); @@ -151,7 +192,7 @@ public void testLiteralStaysUnchanged() { @Test public void testLiteralBackslash() { - MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor ); + MessageInterpolator.Context context = createMessageInterpolatorContextELBeanMethods( sizeDescriptor ); String expected = "\\foo"; String actual = interpolatorUnderTest.interpolate( "\\foo", context ); @@ -160,7 +201,7 @@ public void testLiteralBackslash() { @Test public void testPrecedenceOfParameterInterpolation() { - MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor ); + MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor, ExpressionLanguageFeatureLevel.VARIABLES ); String expected = "$0"; String actual = interpolatorUnderTest.interpolate( "${min}", context ); @@ -176,7 +217,8 @@ public void testLocaleBasedFormatting() { null, Collections.emptyMap(), Collections.emptyMap(), - true ); + ExpressionLanguageFeatureLevel.VARIABLES, + false ); // german locale String expected = "42,00"; @@ -199,7 +241,7 @@ public void testLocaleBasedFormatting() { @Test public void testMissingFormatArgument() { - MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor ); + MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor, ExpressionLanguageFeatureLevel.VARIABLES ); String expected = "${formatter.format('%1$s')}"; String actual = interpolatorUnderTest.interpolate( "${formatter.format('%1$s')}", context ); @@ -212,7 +254,7 @@ public void testMissingFormatArgument() { @Test public void testNoParametersToFormatter() { - MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor ); + MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor, ExpressionLanguageFeatureLevel.VARIABLES ); String expected = "${formatter.format()}"; String actual = interpolatorUnderTest.interpolate( "${formatter.format()}", context ); @@ -221,13 +263,31 @@ public void testNoParametersToFormatter() { @Test public void testNonFormatterFunction() { - MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor ); + MessageInterpolator.Context context = createMessageInterpolatorContextELBeanMethods( sizeDescriptor ); String expected = "foo"; String actual = interpolatorUnderTest.interpolate( "${'foobar'.substring(0,3)}", context ); assertEquals( actual, expected, "Calling of String#substring should work" ); } + @Test + public void testNonFormatterFunctionVariables() { + MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor, ExpressionLanguageFeatureLevel.VARIABLES ); + + String expected = "${'foobar'.substring(0,3)}"; + String actual = interpolatorUnderTest.interpolate( "${'foobar'.substring(0,3)}", context ); + assertEquals( actual, expected, "Calling of String#substring should work" ); + } + + @Test + public void testNonFormatterFunctionBeanProperties() { + MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor, ExpressionLanguageFeatureLevel.BEAN_PROPERTIES ); + + String expected = "${'foobar'.substring(0,3)}"; + String actual = interpolatorUnderTest.interpolate( "${'foobar'.substring(0,3)}", context ); + assertEquals( actual, expected, "Calling of String#substring should work" ); + } + @Test public void testCallingWrongFormatterMethod() { MessageInterpolator.Context context = new MessageInterpolatorContext( @@ -237,7 +297,8 @@ public void testCallingWrongFormatterMethod() { null, Collections.emptyMap(), Collections.emptyMap(), - true ); + ExpressionLanguageFeatureLevel.BEAN_METHODS, + false ); String expected = "${formatter.foo('%1$.2f', validatedValue)}"; String actual = interpolatorUnderTest.interpolate( @@ -255,7 +316,7 @@ public void testCallingWrongFormatterMethod() { @Test @TestForIssue(jiraKey = "HV-834") public void testOpeningCurlyBraceInELExpression() { - MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor ); + MessageInterpolator.Context context = createMessageInterpolatorContextELBeanMethods( sizeDescriptor ); String expected = "{"; String actual = interpolatorUnderTest.interpolate( "${1 > 0 ? '\\{' : '\\}'}", context ); @@ -265,7 +326,7 @@ public void testOpeningCurlyBraceInELExpression() { @Test @TestForIssue(jiraKey = "HV-834") public void testClosingCurlyBraceInELExpression() { - MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor ); + MessageInterpolator.Context context = createMessageInterpolatorContextELBeanMethods( sizeDescriptor ); String expected = "}"; String actual = interpolatorUnderTest.interpolate( "${1 < 0 ? '\\{' : '\\}'}", context ); @@ -275,7 +336,7 @@ public void testClosingCurlyBraceInELExpression() { @Test @TestForIssue(jiraKey = "HV-834") public void testCurlyBracesInELExpression() { - MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor ); + MessageInterpolator.Context context = createMessageInterpolatorContextELBeanMethods( sizeDescriptor ); String expected = "a{b}d"; String actual = interpolatorUnderTest.interpolate( "${1 < 0 ? 'foo' : 'a\\{b\\}d'}", context ); @@ -285,7 +346,7 @@ public void testCurlyBracesInELExpression() { @Test @TestForIssue(jiraKey = "HV-834") public void testEscapedQuoteInELExpression() { - MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor ); + MessageInterpolator.Context context = createMessageInterpolatorContextELBeanMethods( sizeDescriptor ); String expected = "\""; String actual = interpolatorUnderTest.interpolate( "${ true ? \"\\\"\" : \"foo\"}", context ); @@ -295,7 +356,7 @@ public void testEscapedQuoteInELExpression() { @Test @TestForIssue(jiraKey = "HV-834") public void testSingleEscapedQuoteInELExpression() { - MessageInterpolator.Context context = createMessageInterpolatorContext( sizeDescriptor ); + MessageInterpolator.Context context = createMessageInterpolatorContextELBeanMethods( sizeDescriptor ); String expected = "'"; String actual = interpolatorUnderTest.interpolate( "${ false ? 'foo' : '\\''}", context ); @@ -306,7 +367,12 @@ public void testSingleEscapedQuoteInELExpression() { ); } - private MessageInterpolatorContext createMessageInterpolatorContext(ConstraintDescriptorImpl descriptor) { + private MessageInterpolatorContext createMessageInterpolatorContextELBeanMethods(ConstraintDescriptorImpl descriptor) { + return createMessageInterpolatorContext( descriptor, ExpressionLanguageFeatureLevel.BEAN_METHODS ); + } + + private MessageInterpolatorContext createMessageInterpolatorContext(ConstraintDescriptorImpl descriptor, + ExpressionLanguageFeatureLevel expressionLanguageFeatureLevel) { return new MessageInterpolatorContext( descriptor, null, @@ -314,6 +380,7 @@ private MessageInterpolatorContext createMessageInterpolatorContext(ConstraintDe null, Collections.emptyMap(), Collections.emptyMap(), - true ); + expressionLanguageFeatureLevel, + false ); } } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/MessageInterpolatorContextTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/MessageInterpolatorContextTest.java index 9481471f36..ab24a4675d 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/MessageInterpolatorContextTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/MessageInterpolatorContextTest.java @@ -8,6 +8,7 @@ package org.hibernate.validator.test.internal.engine.messageinterpolation; import org.hibernate.validator.internal.engine.MessageInterpolatorContext; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; import org.hibernate.validator.messageinterpolation.HibernateMessageInterpolatorContext; import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; @@ -93,7 +94,8 @@ public void testContextWithRightDescriptorAndValueAndRootBeanClassIsPassedToMess null, Collections.emptyMap(), Collections.emptyMap(), - true ) + ExpressionLanguageFeatureLevel.BEAN_METHODS, + false ) ) ) .andReturn( "invalid" ); @@ -111,14 +113,14 @@ public void testContextWithRightDescriptorAndValueAndRootBeanClassIsPassedToMess @Test(expectedExceptions = ValidationException.class) public void testUnwrapToImplementationCausesValidationException() { Context context = new MessageInterpolatorContext( null, null, null, null, Collections.emptyMap(), - Collections.emptyMap(), true ); + Collections.emptyMap(), ExpressionLanguageFeatureLevel.BEAN_METHODS, false ); context.unwrap( MessageInterpolatorContext.class ); } @Test public void testUnwrapToInterfaceTypesSucceeds() { Context context = new MessageInterpolatorContext( null, null, null, null, Collections.emptyMap(), - Collections.emptyMap(), true ); + Collections.emptyMap(), ExpressionLanguageFeatureLevel.BEAN_METHODS, false ); MessageInterpolator.Context asMessageInterpolatorContext = context.unwrap( MessageInterpolator.Context.class ); assertSame( asMessageInterpolatorContext, context ); @@ -142,7 +144,8 @@ public void testGetRootBeanType() { null, Collections.emptyMap(), Collections.emptyMap(), - true ); + ExpressionLanguageFeatureLevel.BEAN_METHODS, + false ); assertSame( context.unwrap( HibernateMessageInterpolatorContext.class ).getRootBeanType(), rootBeanType ); } @@ -158,7 +161,8 @@ public void testGetPropertyPath() { pathMock, Collections.emptyMap(), Collections.emptyMap(), - true ); + ExpressionLanguageFeatureLevel.BEAN_METHODS, + false ); assertSame( context.unwrap( HibernateMessageInterpolatorContext.class ).getPropertyPath(), pathMock ); } diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java index 1c6f0810c9..68678d1ba1 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.java @@ -29,6 +29,7 @@ import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl; import org.hibernate.validator.internal.metadata.location.ConstraintLocation.ConstraintLocationKind; import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; import org.hibernate.validator.testutil.TestForIssue; @@ -282,7 +283,8 @@ private MessageInterpolatorContext createMessageInterpolatorContext(ConstraintDe null, Collections.emptyMap(), Collections.emptyMap(), - true ); + ExpressionLanguageFeatureLevel.BEAN_METHODS, + false ); } private void runInterpolation(boolean cachingEnabled) { diff --git a/engine/src/test/java/org/hibernate/validator/testutils/ValidatorUtil.java b/engine/src/test/java/org/hibernate/validator/testutils/ValidatorUtil.java index 061272b05f..b91f10aad5 100644 --- a/engine/src/test/java/org/hibernate/validator/testutils/ValidatorUtil.java +++ b/engine/src/test/java/org/hibernate/validator/testutils/ValidatorUtil.java @@ -28,6 +28,7 @@ import org.hibernate.validator.constraintvalidation.HibernateConstraintValidatorContext; import org.hibernate.validator.internal.engine.DefaultClockProvider; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl; +import org.hibernate.validator.messageinterpolation.ExpressionLanguageFeatureLevel; import org.hibernate.validator.testutil.DummyTraversableResolver; import org.hibernate.validator.testutil.ValidationInvocationHandler; @@ -235,6 +236,7 @@ public static T getValidatingProxy(I implementor, Validator exe } public static HibernateConstraintValidatorContext getConstraintValidatorContext() { - return new ConstraintValidatorContextImpl( DefaultClockProvider.INSTANCE, null, null, null ); + return new ConstraintValidatorContextImpl( DefaultClockProvider.INSTANCE, null, null, null, ExpressionLanguageFeatureLevel.BEAN_PROPERTIES, + ExpressionLanguageFeatureLevel.NONE ); } } diff --git a/engine/src/test/resources/log4j2.properties b/engine/src/test/resources/log4j2.properties index 3a80eeb2c1..6289842165 100644 --- a/engine/src/test/resources/log4j2.properties +++ b/engine/src/test/resources/log4j2.properties @@ -19,4 +19,8 @@ rootLogger.appenderRef.console.ref = console # Specific loggers options logger.parametermessageinterpolator.name = org.hibernate.validator.messageinterpolation.ParameterMessageInterpolator logger.parametermessageinterpolator.level = info -logger.parametermessageinterpolator.appenderRef.list.ref = List \ No newline at end of file +logger.parametermessageinterpolator.appenderRef.list.ref = List + +logger.constraintvalidatorcontextimpl.name = org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl +logger.constraintvalidatorcontextimpl.level = info +logger.constraintvalidatorcontextimpl.appenderRef.list.ref = List \ No newline at end of file diff --git a/engine/src/test/resources/org/hibernate/validator/test/el/validation-constraints-bean-methods.xml b/engine/src/test/resources/org/hibernate/validator/test/el/validation-constraints-bean-methods.xml new file mode 100644 index 0000000000..671eed5699 --- /dev/null +++ b/engine/src/test/resources/org/hibernate/validator/test/el/validation-constraints-bean-methods.xml @@ -0,0 +1,16 @@ + + + + + bean-methods + diff --git a/engine/src/test/resources/org/hibernate/validator/test/el/validation-constraints-default.xml b/engine/src/test/resources/org/hibernate/validator/test/el/validation-constraints-default.xml new file mode 100644 index 0000000000..cc05e3311c --- /dev/null +++ b/engine/src/test/resources/org/hibernate/validator/test/el/validation-constraints-default.xml @@ -0,0 +1,16 @@ + + + + + default + diff --git a/engine/src/test/resources/org/hibernate/validator/test/el/validation-custom-violations-bean-methods.xml b/engine/src/test/resources/org/hibernate/validator/test/el/validation-custom-violations-bean-methods.xml new file mode 100644 index 0000000000..ecd0155803 --- /dev/null +++ b/engine/src/test/resources/org/hibernate/validator/test/el/validation-custom-violations-bean-methods.xml @@ -0,0 +1,16 @@ + + + + + bean-methods + diff --git a/engine/src/test/resources/org/hibernate/validator/test/el/validation-custom-violations-default.xml b/engine/src/test/resources/org/hibernate/validator/test/el/validation-custom-violations-default.xml new file mode 100644 index 0000000000..62a07bde5a --- /dev/null +++ b/engine/src/test/resources/org/hibernate/validator/test/el/validation-custom-violations-default.xml @@ -0,0 +1,16 @@ + + + + + default + From 93c7dd7ec09dc4d1db48ef02fe0255bb33de1e28 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 14 Oct 2020 13:17:38 +0200 Subject: [PATCH 381/393] HV-1812 Avoid reflection-based metadata extraction for built-in value extractors --- .../valueextraction/BooleanArrayValueExtractor.java | 5 ++++- .../valueextraction/ByteArrayValueExtractor.java | 7 +++++-- .../valueextraction/CharArrayValueExtractor.java | 5 ++++- .../valueextraction/DoubleArrayValueExtractor.java | 5 ++++- .../valueextraction/FloatArrayValueExtractor.java | 5 ++++- .../valueextraction/IntArrayValueExtractor.java | 5 ++++- .../valueextraction/IterableValueExtractor.java | 5 ++++- .../valueextraction/ListPropertyValueExtractor.java | 4 +++- .../engine/valueextraction/ListValueExtractor.java | 4 +++- .../valueextraction/LongArrayValueExtractor.java | 5 ++++- .../engine/valueextraction/MapKeyExtractor.java | 4 +++- .../valueextraction/MapPropertyKeyExtractor.java | 4 +++- .../valueextraction/MapPropertyValueExtractor.java | 4 +++- .../engine/valueextraction/MapValueExtractor.java | 4 +++- .../valueextraction/ObjectArrayValueExtractor.java | 5 ++++- .../ObservableValueValueExtractor.java | 5 ++++- .../OptionalDoubleValueExtractor.java | 4 +++- .../valueextraction/OptionalIntValueExtractor.java | 4 +++- .../valueextraction/OptionalLongValueExtractor.java | 4 +++- .../valueextraction/OptionalValueExtractor.java | 3 ++- .../ReadOnlyListPropertyValueExtractor.java | 4 +++- .../ReadOnlyMapPropertyKeyExtractor.java | 4 +++- .../ReadOnlyMapPropertyValueExtractor.java | 4 +++- .../ReadOnlySetPropertyValueExtractor.java | 4 +++- .../valueextraction/SetPropertyValueExtractor.java | 4 +++- .../valueextraction/ShortArrayValueExtractor.java | 5 ++++- .../valueextraction/ValueExtractorDescriptor.java | 13 +++++++++++++ 27 files changed, 102 insertions(+), 27 deletions(-) diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/BooleanArrayValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/BooleanArrayValueExtractor.java index d484ed3744..19c9f0d77e 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/BooleanArrayValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/BooleanArrayValueExtractor.java @@ -6,6 +6,8 @@ */ package org.hibernate.validator.internal.engine.valueextraction; +import java.util.Optional; + import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -13,7 +15,8 @@ class BooleanArrayValueExtractor implements ValueExtractor { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new BooleanArrayValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new BooleanArrayValueExtractor(), boolean[].class, + new ArrayElement( boolean[].class ), false, Optional.empty() ); private BooleanArrayValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ByteArrayValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ByteArrayValueExtractor.java index 384edc9c0a..eab9c7d13b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ByteArrayValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ByteArrayValueExtractor.java @@ -6,14 +6,17 @@ */ package org.hibernate.validator.internal.engine.valueextraction; +import java.util.Optional; + import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; import org.hibernate.validator.internal.engine.path.NodeImpl; -class ByteArrayValueExtractor implements ValueExtractor { +class ByteArrayValueExtractor implements ValueExtractor { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ByteArrayValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ByteArrayValueExtractor(), byte[].class, + new ArrayElement( byte[].class ), false, Optional.empty() ); private ByteArrayValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/CharArrayValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/CharArrayValueExtractor.java index 04026832ec..4e2eb18da3 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/CharArrayValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/CharArrayValueExtractor.java @@ -6,6 +6,8 @@ */ package org.hibernate.validator.internal.engine.valueextraction; +import java.util.Optional; + import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -13,7 +15,8 @@ class CharArrayValueExtractor implements ValueExtractor { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new CharArrayValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new CharArrayValueExtractor(), char[].class, + new ArrayElement( char[].class ), false, Optional.empty() ); private CharArrayValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/DoubleArrayValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/DoubleArrayValueExtractor.java index 62d6ed3e5e..fa100d055a 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/DoubleArrayValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/DoubleArrayValueExtractor.java @@ -6,6 +6,8 @@ */ package org.hibernate.validator.internal.engine.valueextraction; +import java.util.Optional; + import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -13,7 +15,8 @@ class DoubleArrayValueExtractor implements ValueExtractor { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new DoubleArrayValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new DoubleArrayValueExtractor(), double[].class, + new ArrayElement( double[].class ), false, Optional.empty() ); private DoubleArrayValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/FloatArrayValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/FloatArrayValueExtractor.java index f0ea51994f..52b769ab45 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/FloatArrayValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/FloatArrayValueExtractor.java @@ -6,6 +6,8 @@ */ package org.hibernate.validator.internal.engine.valueextraction; +import java.util.Optional; + import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -13,7 +15,8 @@ class FloatArrayValueExtractor implements ValueExtractor { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new FloatArrayValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new FloatArrayValueExtractor(), float[].class, + new ArrayElement( float[].class ), false, Optional.empty() ); private FloatArrayValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/IntArrayValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/IntArrayValueExtractor.java index df91bc873c..44e2ce477f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/IntArrayValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/IntArrayValueExtractor.java @@ -6,6 +6,8 @@ */ package org.hibernate.validator.internal.engine.valueextraction; +import java.util.Optional; + import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -13,7 +15,8 @@ class IntArrayValueExtractor implements ValueExtractor { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new IntArrayValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new IntArrayValueExtractor(), int[].class, + new ArrayElement( int[].class ), false, Optional.empty() ); private IntArrayValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/IterableValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/IterableValueExtractor.java index f48bc25e30..a2b229c9c8 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/IterableValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/IterableValueExtractor.java @@ -6,6 +6,8 @@ */ package org.hibernate.validator.internal.engine.valueextraction; +import java.util.Optional; + import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -13,7 +15,8 @@ class IterableValueExtractor implements ValueExtractor> { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new IterableValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new IterableValueExtractor(), Iterable.class, + Iterable.class.getTypeParameters()[0], false, Optional.empty() ); private IterableValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ListPropertyValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ListPropertyValueExtractor.java index bcccb67566..e425d8858f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ListPropertyValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ListPropertyValueExtractor.java @@ -7,6 +7,7 @@ package org.hibernate.validator.internal.engine.valueextraction; import java.util.List; +import java.util.Optional; import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -29,7 +30,8 @@ @IgnoreForbiddenApisErrors(reason = "Usage of JavaFX classes") class ListPropertyValueExtractor implements ValueExtractor> { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ListPropertyValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ListPropertyValueExtractor(), ListProperty.class, + ListProperty.class.getTypeParameters()[0], false, Optional.empty() ); private ListPropertyValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ListValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ListValueExtractor.java index 39c0b3928c..8d29d2ff59 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ListValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ListValueExtractor.java @@ -7,6 +7,7 @@ package org.hibernate.validator.internal.engine.valueextraction; import java.util.List; +import java.util.Optional; import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -15,7 +16,8 @@ class ListValueExtractor implements ValueExtractor> { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ListValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ListValueExtractor(), List.class, List.class.getTypeParameters()[0], + false, Optional.empty() ); private ListValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/LongArrayValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/LongArrayValueExtractor.java index 1b98b1c26c..642b15c9b6 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/LongArrayValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/LongArrayValueExtractor.java @@ -6,6 +6,8 @@ */ package org.hibernate.validator.internal.engine.valueextraction; +import java.util.Optional; + import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -13,7 +15,8 @@ class LongArrayValueExtractor implements ValueExtractor { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new LongArrayValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new LongArrayValueExtractor(), long[].class, + new ArrayElement( long[].class ), false, Optional.empty() ); private LongArrayValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapKeyExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapKeyExtractor.java index 763ddda58e..d3757f3e94 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapKeyExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapKeyExtractor.java @@ -7,6 +7,7 @@ package org.hibernate.validator.internal.engine.valueextraction; import java.util.Map; +import java.util.Optional; import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -15,7 +16,8 @@ class MapKeyExtractor implements ValueExtractor> { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new MapKeyExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new MapKeyExtractor(), Map.class, Map.class.getTypeParameters()[0], + false, Optional.empty() ); private MapKeyExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapPropertyKeyExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapPropertyKeyExtractor.java index bbd5dc7bc4..75146667b5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapPropertyKeyExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapPropertyKeyExtractor.java @@ -7,6 +7,7 @@ package org.hibernate.validator.internal.engine.valueextraction; import java.util.Map; +import java.util.Optional; import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -29,7 +30,8 @@ @IgnoreForbiddenApisErrors(reason = "Usage of JavaFX classes") class MapPropertyKeyExtractor implements ValueExtractor> { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new MapPropertyKeyExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new MapPropertyKeyExtractor(), MapProperty.class, + MapProperty.class.getTypeParameters()[0], false, Optional.empty() ); private MapPropertyKeyExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapPropertyValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapPropertyValueExtractor.java index 179ed8e51b..d1fc87d599 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapPropertyValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapPropertyValueExtractor.java @@ -7,6 +7,7 @@ package org.hibernate.validator.internal.engine.valueextraction; import java.util.Map; +import java.util.Optional; import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -29,7 +30,8 @@ @IgnoreForbiddenApisErrors(reason = "Usage of JavaFX classes") class MapPropertyValueExtractor implements ValueExtractor> { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new MapPropertyValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new MapPropertyValueExtractor(), MapProperty.class, + MapProperty.class.getTypeParameters()[1], false, Optional.empty() ); private MapPropertyValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapValueExtractor.java index 697bb94c76..091490a139 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/MapValueExtractor.java @@ -7,6 +7,7 @@ package org.hibernate.validator.internal.engine.valueextraction; import java.util.Map; +import java.util.Optional; import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -15,7 +16,8 @@ class MapValueExtractor implements ValueExtractor> { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new MapValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new MapValueExtractor(), Map.class, Map.class.getTypeParameters()[1], + false, Optional.empty() ); private MapValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ObjectArrayValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ObjectArrayValueExtractor.java index ba1b28a677..36560fbfe5 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ObjectArrayValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ObjectArrayValueExtractor.java @@ -6,6 +6,8 @@ */ package org.hibernate.validator.internal.engine.valueextraction; +import java.util.Optional; + import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -13,7 +15,8 @@ class ObjectArrayValueExtractor implements ValueExtractor { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ObjectArrayValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ObjectArrayValueExtractor(), Object[].class, + new ArrayElement( Object[].class ), false, Optional.empty() ); private ObjectArrayValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ObservableValueValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ObservableValueValueExtractor.java index 12232824d0..f334b89c5d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ObservableValueValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ObservableValueValueExtractor.java @@ -6,6 +6,8 @@ */ package org.hibernate.validator.internal.engine.valueextraction; +import java.util.Optional; + import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.UnwrapByDefault; import javax.validation.valueextraction.ValueExtractor; @@ -24,7 +26,8 @@ @UnwrapByDefault class ObservableValueValueExtractor implements ValueExtractor> { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ObservableValueValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ObservableValueValueExtractor(), ObservableValue.class, + ObservableValue.class.getTypeParameters()[0], true, Optional.empty() ); private ObservableValueValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/OptionalDoubleValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/OptionalDoubleValueExtractor.java index ce7ef9455d..6bcd094604 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/OptionalDoubleValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/OptionalDoubleValueExtractor.java @@ -6,6 +6,7 @@ */ package org.hibernate.validator.internal.engine.valueextraction; +import java.util.Optional; import java.util.OptionalDouble; import javax.validation.valueextraction.ExtractedValue; @@ -18,7 +19,8 @@ @UnwrapByDefault class OptionalDoubleValueExtractor implements ValueExtractor<@ExtractedValue(type = Double.class) OptionalDouble> { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new OptionalDoubleValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new OptionalDoubleValueExtractor(), OptionalDouble.class, + AnnotatedObject.INSTANCE, true, Optional.of( Double.class ) ); @Override public void extractValues(OptionalDouble originalValue, ValueReceiver receiver) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/OptionalIntValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/OptionalIntValueExtractor.java index 9aaa2fc97f..bf50814e6d 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/OptionalIntValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/OptionalIntValueExtractor.java @@ -6,6 +6,7 @@ */ package org.hibernate.validator.internal.engine.valueextraction; +import java.util.Optional; import java.util.OptionalInt; import javax.validation.valueextraction.ExtractedValue; @@ -18,7 +19,8 @@ @UnwrapByDefault class OptionalIntValueExtractor implements ValueExtractor<@ExtractedValue(type = Integer.class) OptionalInt> { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new OptionalIntValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new OptionalIntValueExtractor(), OptionalInt.class, + AnnotatedObject.INSTANCE, true, Optional.of( Integer.class ) ); @Override public void extractValues(OptionalInt originalValue, ValueReceiver receiver) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/OptionalLongValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/OptionalLongValueExtractor.java index eccd2dc6c6..5f3cc899db 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/OptionalLongValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/OptionalLongValueExtractor.java @@ -6,6 +6,7 @@ */ package org.hibernate.validator.internal.engine.valueextraction; +import java.util.Optional; import java.util.OptionalLong; import javax.validation.valueextraction.ExtractedValue; @@ -18,7 +19,8 @@ @UnwrapByDefault class OptionalLongValueExtractor implements ValueExtractor<@ExtractedValue(type = Long.class) OptionalLong> { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new OptionalLongValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new OptionalLongValueExtractor(), OptionalLong.class, + AnnotatedObject.INSTANCE, true, Optional.of( Long.class ) ); @Override public void extractValues(OptionalLong originalValue, ValueReceiver receiver) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/OptionalValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/OptionalValueExtractor.java index d8ff162fe6..24652c4ec2 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/OptionalValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/OptionalValueExtractor.java @@ -16,7 +16,8 @@ */ class OptionalValueExtractor implements ValueExtractor> { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new OptionalValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new OptionalValueExtractor(), Optional.class, + Optional.class.getTypeParameters()[0], false, Optional.empty() ); private OptionalValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyListPropertyValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyListPropertyValueExtractor.java index e003c52245..68025f2521 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyListPropertyValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyListPropertyValueExtractor.java @@ -7,6 +7,7 @@ package org.hibernate.validator.internal.engine.valueextraction; import java.util.List; +import java.util.Optional; import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -29,7 +30,8 @@ @IgnoreForbiddenApisErrors(reason = "Usage of JavaFX classes") class ReadOnlyListPropertyValueExtractor implements ValueExtractor> { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ReadOnlyListPropertyValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ReadOnlyListPropertyValueExtractor(), ReadOnlyListProperty.class, + ReadOnlyListProperty.class.getTypeParameters()[0], false, Optional.empty() ); private ReadOnlyListPropertyValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyMapPropertyKeyExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyMapPropertyKeyExtractor.java index c98cefd76f..422465eced 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyMapPropertyKeyExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyMapPropertyKeyExtractor.java @@ -7,6 +7,7 @@ package org.hibernate.validator.internal.engine.valueextraction; import java.util.Map; +import java.util.Optional; import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -29,7 +30,8 @@ @IgnoreForbiddenApisErrors(reason = "Usage of JavaFX classes") class ReadOnlyMapPropertyKeyExtractor implements ValueExtractor> { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ReadOnlyMapPropertyKeyExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ReadOnlyMapPropertyKeyExtractor(), ReadOnlyMapProperty.class, + ReadOnlyMapProperty.class.getTypeParameters()[0], false, Optional.empty() ); private ReadOnlyMapPropertyKeyExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyMapPropertyValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyMapPropertyValueExtractor.java index e843400dd0..7c4aac469c 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyMapPropertyValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlyMapPropertyValueExtractor.java @@ -7,6 +7,7 @@ package org.hibernate.validator.internal.engine.valueextraction; import java.util.Map; +import java.util.Optional; import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -29,7 +30,8 @@ @IgnoreForbiddenApisErrors(reason = "Usage of JavaFX classes") class ReadOnlyMapPropertyValueExtractor implements ValueExtractor> { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ReadOnlyMapPropertyValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ReadOnlyMapPropertyValueExtractor(), ReadOnlyMapProperty.class, + ReadOnlyMapProperty.class.getTypeParameters()[1], false, Optional.empty() ); private ReadOnlyMapPropertyValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlySetPropertyValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlySetPropertyValueExtractor.java index 18635dc017..ea99066d08 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlySetPropertyValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ReadOnlySetPropertyValueExtractor.java @@ -6,6 +6,7 @@ */ package org.hibernate.validator.internal.engine.valueextraction; +import java.util.Optional; import java.util.Set; import javax.validation.valueextraction.ExtractedValue; @@ -29,7 +30,8 @@ @IgnoreForbiddenApisErrors(reason = "Usage of JavaFX classes") class ReadOnlySetPropertyValueExtractor implements ValueExtractor> { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ReadOnlySetPropertyValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ReadOnlySetPropertyValueExtractor(), ReadOnlySetProperty.class, + ReadOnlySetProperty.class.getTypeParameters()[0], false, Optional.empty() ); private ReadOnlySetPropertyValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/SetPropertyValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/SetPropertyValueExtractor.java index bcd0d9b55b..52e08e38f4 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/SetPropertyValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/SetPropertyValueExtractor.java @@ -6,6 +6,7 @@ */ package org.hibernate.validator.internal.engine.valueextraction; +import java.util.Optional; import java.util.Set; import javax.validation.valueextraction.ExtractedValue; @@ -29,7 +30,8 @@ @IgnoreForbiddenApisErrors(reason = "Usage of JavaFX classes") class SetPropertyValueExtractor implements ValueExtractor> { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new SetPropertyValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new SetPropertyValueExtractor(), SetProperty.class, + SetProperty.class.getTypeParameters()[0], false, Optional.empty() ); private SetPropertyValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ShortArrayValueExtractor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ShortArrayValueExtractor.java index 3604e8dc3f..5fa6f6ded2 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ShortArrayValueExtractor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ShortArrayValueExtractor.java @@ -6,6 +6,8 @@ */ package org.hibernate.validator.internal.engine.valueextraction; +import java.util.Optional; + import javax.validation.valueextraction.ExtractedValue; import javax.validation.valueextraction.ValueExtractor; @@ -13,7 +15,8 @@ class ShortArrayValueExtractor implements ValueExtractor { - static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ShortArrayValueExtractor() ); + static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ShortArrayValueExtractor(), short[].class, + new ArrayElement( short[].class ), false, Optional.empty() ); private ShortArrayValueExtractor() { } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorDescriptor.java b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorDescriptor.java index f949be40ab..ecbc73c6ea 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorDescriptor.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/valueextraction/ValueExtractorDescriptor.java @@ -53,6 +53,19 @@ public ValueExtractorDescriptor(ValueExtractor valueExtractor) { this.extractedType = getExtractedType( valueExtractorDefinition ); } + ValueExtractorDescriptor(ValueExtractor valueExtractor, + Class containerType, + TypeVariable extractedTypeParameter, + boolean unwrapByDefault, + Optional> extractedType) { + this.key = new Key( + containerType, + extractedTypeParameter ); + this.valueExtractor = valueExtractor; + this.unwrapByDefault = unwrapByDefault; + this.extractedType = extractedType; + } + @SuppressWarnings("rawtypes") private static TypeVariable getExtractedTypeParameter(AnnotatedParameterizedType valueExtractorDefinition, Class extractorImplementationType) { From 55a24f3368bda1e590b7a2ffe31575e46398f988 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 15 Jul 2020 18:06:24 +0200 Subject: [PATCH 382/393] HV-1790 Remove the SafeHtml constraint and the jsoup dependency There is no replacement for this constraint. It has been deprecated and planned for removal in both 6.0 and 6.1. --- .../ap/internal/util/ConstraintHelper.java | 1 - .../validator/ap/internal/util/TypeNames.java | 1 - .../ap/ConstraintValidationProcessorTest.java | 7 +- ...ateValidatorProvidedCustomConstraints.java | 3 - distribution/pom.xml | 4 - distribution/src/main/assembly/dist.xml | 1 - documentation/src/main/asciidoc/ch02.asciidoc | 5 - engine/pom.xml | 6 - .../validator/cfg/defs/SafeHtmlDef.java | 140 --------- .../validator/constraints/SafeHtml.java | 179 ----------- .../hv/SafeHtmlValidator.java | 103 ------ .../metadata/core/BuiltinConstraint.java | 1 - .../metadata/core/ConstraintHelper.java | 16 - .../validator/ValidationMessages.properties | 1 - .../ValidationMessages_ar.properties | 1 - .../ValidationMessages_cs.properties | 1 - .../ValidationMessages_da.properties | 1 - .../ValidationMessages_de.properties | 1 - .../ValidationMessages_es.properties | 1 - .../ValidationMessages_fa.properties | 1 - .../ValidationMessages_fr.properties | 1 - .../ValidationMessages_hu.properties | 1 - .../ValidationMessages_it.properties | 1 - .../ValidationMessages_ja.properties | 1 - .../ValidationMessages_ko.properties | 1 - .../ValidationMessages_nl.properties | 1 - .../ValidationMessages_pl.properties | 1 - .../ValidationMessages_pt_BR.properties | 1 - .../ValidationMessages_ro.properties | 1 - .../ValidationMessages_ru.properties | 1 - .../ValidationMessages_sk.properties | 1 - .../ValidationMessages_tr.properties | 1 - .../ValidationMessages_uk.properties | 1 - .../ValidationMessages_zh.properties | 1 - .../ValidationMessages_zh_CN.properties | 1 - .../ValidationMessages_zh_TW.properties | 1 - ...ProgrammaticConstraintDefinitionsTest.java | 103 ------ .../hv/SafeHtmlConstrainedTest.java | 52 ---- .../MessagePropertiesTest.java | 5 - .../PredefinedScopeAllConstraintsTest.java | 8 - .../hv/SafeHtmlValidatorTest.java | 292 ------------------ integration/pom.xml | 5 - .../wildfly/OptionalConstraintsIT.java | 17 +- .../KarafFeaturesAreInstallableTest.java | 6 - .../integrationtest/OsgiIntegrationTest.java | 2 +- .../src/main/features/features.xml | 4 - pom.xml | 6 - 47 files changed, 5 insertions(+), 985 deletions(-) delete mode 100644 engine/src/main/java/org/hibernate/validator/cfg/defs/SafeHtmlDef.java delete mode 100644 engine/src/main/java/org/hibernate/validator/constraints/SafeHtml.java delete mode 100644 engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/hv/SafeHtmlValidator.java delete mode 100644 engine/src/test/java/org/hibernate/validator/test/constraints/annotations/hv/SafeHtmlConstrainedTest.java delete mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/SafeHtmlValidatorTest.java diff --git a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/ConstraintHelper.java b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/ConstraintHelper.java index 52e0d702d0..0220534d7e 100644 --- a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/ConstraintHelper.java +++ b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/ConstraintHelper.java @@ -305,7 +305,6 @@ public ConstraintHelper(Types typeUtils, AnnotationApiHelper annotationApiHelper registerAllowedTypesForBuiltInConstraint( HibernateValidatorTypes.NOT_BLANK, CharSequence.class ); registerAllowedTypesForBuiltInConstraint( HibernateValidatorTypes.NOT_EMPTY, TYPES_SUPPORTED_BY_SIZE_AND_NOT_EMPTY_ANNOTATIONS ); registerAllowedTypesForBuiltInConstraint( HibernateValidatorTypes.NORMALIZED, CharSequence.class ); - registerAllowedTypesForBuiltInConstraint( HibernateValidatorTypes.SAFE_HTML, CharSequence.class ); registerAllowedTypesForBuiltInConstraint( HibernateValidatorTypes.SCRIPT_ASSERT, Object.class ); registerAllowedTypesForBuiltInConstraint( HibernateValidatorTypes.UNIQUE_ELEMENTS, Collection.class ); registerAllowedTypesForBuiltInConstraint( HibernateValidatorTypes.URL, CharSequence.class ); diff --git a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/TypeNames.java b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/TypeNames.java index bb6622139a..b346c4a900 100644 --- a/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/TypeNames.java +++ b/annotation-processor/src/main/java/org/hibernate/validator/ap/internal/util/TypeNames.java @@ -81,7 +81,6 @@ public static class HibernateValidatorTypes { public static final String NORMALIZED = ORG_HIBERNATE_VALIDATOR_CONSTRAINTS + ".Normalized"; public static final String NOT_BLANK = ORG_HIBERNATE_VALIDATOR_CONSTRAINTS + ".NotBlank"; public static final String NOT_EMPTY = ORG_HIBERNATE_VALIDATOR_CONSTRAINTS + ".NotEmpty"; - public static final String SAFE_HTML = ORG_HIBERNATE_VALIDATOR_CONSTRAINTS + ".SafeHtml"; public static final String SCRIPT_ASSERT = ORG_HIBERNATE_VALIDATOR_CONSTRAINTS + ".ScriptAssert"; public static final String UNIQUE_ELEMENTS = ORG_HIBERNATE_VALIDATOR_CONSTRAINTS + ".UniqueElements"; public static final String URL = ORG_HIBERNATE_VALIDATOR_CONSTRAINTS + ".URL"; diff --git a/annotation-processor/src/test/java/org/hibernate/validator/ap/ConstraintValidationProcessorTest.java b/annotation-processor/src/test/java/org/hibernate/validator/ap/ConstraintValidationProcessorTest.java index b5777ceb06..8fdad4b55f 100644 --- a/annotation-processor/src/test/java/org/hibernate/validator/ap/ConstraintValidationProcessorTest.java +++ b/annotation-processor/src/test/java/org/hibernate/validator/ap/ConstraintValidationProcessorTest.java @@ -155,6 +155,8 @@ public void hibernateValidatorProvidedCustomConstraints() { assertFalse( compilationResult ); assertThatDiagnosticsMatch( diagnostics, + new DiagnosticExpectation( Kind.ERROR, 66 ), + new DiagnosticExpectation( Kind.ERROR, 67 ), new DiagnosticExpectation( Kind.ERROR, 68 ), new DiagnosticExpectation( Kind.ERROR, 69 ), new DiagnosticExpectation( Kind.ERROR, 70 ), @@ -171,10 +173,7 @@ public void hibernateValidatorProvidedCustomConstraints() { new DiagnosticExpectation( Kind.ERROR, 81 ), new DiagnosticExpectation( Kind.ERROR, 82 ), new DiagnosticExpectation( Kind.ERROR, 83 ), - new DiagnosticExpectation( Kind.ERROR, 84 ), - new DiagnosticExpectation( Kind.ERROR, 85 ), - new DiagnosticExpectation( Kind.ERROR, 86 ), - new DiagnosticExpectation( Kind.ERROR, 87 ) + new DiagnosticExpectation( Kind.ERROR, 84 ) ); } diff --git a/annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/customconstraints/HibernateValidatorProvidedCustomConstraints.java b/annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/customconstraints/HibernateValidatorProvidedCustomConstraints.java index 587fecec97..75d3706624 100644 --- a/annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/customconstraints/HibernateValidatorProvidedCustomConstraints.java +++ b/annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/customconstraints/HibernateValidatorProvidedCustomConstraints.java @@ -19,7 +19,6 @@ import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.NotEmpty; import org.hibernate.validator.constraints.Range; -import org.hibernate.validator.constraints.SafeHtml; import org.hibernate.validator.constraints.ScriptAssert; import org.hibernate.validator.constraints.URL; import org.hibernate.validator.constraints.br.CNPJ; @@ -48,7 +47,6 @@ public class HibernateValidatorProvidedCustomConstraints { @NotBlank @NotEmpty @Range - @SafeHtml @URL @CNPJ @CPF @@ -75,7 +73,6 @@ public class HibernateValidatorProvidedCustomConstraints { @NotBlank @NotEmpty @Range - @SafeHtml @URL @CNPJ @CPF diff --git a/distribution/pom.xml b/distribution/pom.xml index 6138d3bfaa..9688e62064 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -65,10 +65,6 @@ javax.money money-api - - org.jsoup - jsoup - com.thoughtworks.paranamer paranamer diff --git a/distribution/src/main/assembly/dist.xml b/distribution/src/main/assembly/dist.xml index b31d964158..0f1fb92a9e 100644 --- a/distribution/src/main/assembly/dist.xml +++ b/distribution/src/main/assembly/dist.xml @@ -45,7 +45,6 @@ org.apache.logging.log4j:log4j-core joda-time:joda-time jakarta.persistence:jakarta.persistence-api - org.jsoup:jsoup com.thoughtworks.paranamer:paranamer diff --git a/documentation/src/main/asciidoc/ch02.asciidoc b/documentation/src/main/asciidoc/ch02.asciidoc index 1a93ee42c7..b0a5a16a3f 100644 --- a/documentation/src/main/asciidoc/ch02.asciidoc +++ b/documentation/src/main/asciidoc/ch02.asciidoc @@ -715,11 +715,6 @@ With one exception also these constraints apply to the field/property level, onl Supported data types::: `BigDecimal`, `BigInteger`, `CharSequence`, `byte`, `short`, `int`, `long` and the respective wrappers of the primitive types Hibernate metadata impact::: None -`@SafeHtml(whitelistType= , additionalTags=, additionalTagsWithAttributes=, baseURI=)`:: Checks whether the annotated value contains potentially malicious fragments such as `" ); - Set> violations = validator.validate( foo ); - assertThat( violations ).containsOnlyViolations( - violationOf( SafeHtml.class ) - ); - } - - private static class Foo { - - @SafeHtml - private final String html; - - public Foo(String html) { - this.html = html; - } - } -} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/MessagePropertiesTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/MessagePropertiesTest.java index 31ff853c1a..0ad6a0a177 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/MessagePropertiesTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/MessagePropertiesTest.java @@ -59,7 +59,6 @@ import org.hibernate.validator.constraints.Normalized; import org.hibernate.validator.constraints.ParameterScriptAssert; import org.hibernate.validator.constraints.Range; -import org.hibernate.validator.constraints.SafeHtml; import org.hibernate.validator.constraints.ScriptAssert; import org.hibernate.validator.constraints.URL; import org.hibernate.validator.constraints.UniqueElements; @@ -162,7 +161,6 @@ public void testMessageProperties() throws NoSuchMethodException, SecurityExcept violationOf( org.hibernate.validator.constraints.NotBlank.class ), violationOf( org.hibernate.validator.constraints.NotEmpty.class ), violationOf( Range.class ), - violationOf( SafeHtml.class ), violationOf( UniqueElements.class ), violationOf( URL.class ), violationOf( CNPJ.class ), @@ -322,9 +320,6 @@ private static class Bean { @Range(min = 2, max = 4) private int range = 6; - @SafeHtml - private String safeHtml = ""; - @UniqueElements private List uniqueElements = Arrays.asList( "a", "a" ); diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/PredefinedScopeAllConstraintsTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/PredefinedScopeAllConstraintsTest.java index db18219ade..497c3200c6 100644 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/PredefinedScopeAllConstraintsTest.java +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/PredefinedScopeAllConstraintsTest.java @@ -58,7 +58,6 @@ import org.hibernate.validator.constraints.Normalized; import org.hibernate.validator.constraints.ParameterScriptAssert; import org.hibernate.validator.constraints.Range; -import org.hibernate.validator.constraints.SafeHtml; import org.hibernate.validator.constraints.ScriptAssert; import org.hibernate.validator.constraints.URL; import org.hibernate.validator.constraints.UniqueElements; @@ -121,7 +120,6 @@ public void testConstraints() throws NoSuchMethodException, SecurityException { testConstraint( org.hibernate.validator.constraints.NotBlank.class, new HvNotBlankBean() ); testConstraint( org.hibernate.validator.constraints.NotEmpty.class, new HvNotEmptyBean() ); testConstraint( Range.class, new RangeBean() ); - testConstraint( SafeHtml.class, new SafeHtmlBean() ); testConstraint( UniqueElements.class, new UniqueElementsBean() ); testConstraint( URL.class, new URLBean() ); testConstraint( CNPJ.class, new CNPJBean() ); @@ -383,12 +381,6 @@ private static class RangeBean { private int range = 6; } - private static class SafeHtmlBean { - - @SafeHtml - private String safeHtml = ""; - } - private static class UniqueElementsBean { @UniqueElements diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/SafeHtmlValidatorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/SafeHtmlValidatorTest.java deleted file mode 100644 index 45e6f031da..0000000000 --- a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/hv/SafeHtmlValidatorTest.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Hibernate Validator, declare and validate application constraints - * - * License: Apache License, Version 2.0 - * See the license.txt file in the root directory or . - */ -package org.hibernate.validator.test.internal.constraintvalidators.hv; - -import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertNoViolations; -import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; -import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; -import static org.hibernate.validator.testutils.ValidatorUtil.getValidator; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; - -import java.util.Set; - -import javax.validation.ConstraintViolation; -import javax.validation.Validator; - -import org.hibernate.validator.constraints.SafeHtml; -import org.hibernate.validator.constraints.SafeHtml.WhiteListType; -import org.hibernate.validator.internal.constraintvalidators.hv.SafeHtmlValidator; -import org.hibernate.validator.internal.util.annotation.AnnotationDescriptor; -import org.hibernate.validator.internal.util.annotation.ConstraintAnnotationDescriptor; -import org.hibernate.validator.testutil.TestForIssue; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -/** - * Unit test for {@link SafeHtmlValidator}. - * - * @author George Gastaldi - * @author Hardy Ferentschik - * @author Marko Bekhta - */ -public class SafeHtmlValidatorTest { - - private ConstraintAnnotationDescriptor.Builder descriptorBuilder; - - @BeforeMethod - public void setUp() { - descriptorBuilder = new ConstraintAnnotationDescriptor.Builder<>( SafeHtml.class ); - } - - @Test - public void testNullValue() throws Exception { - descriptorBuilder.setAttribute( "whitelistType", WhiteListType.BASIC ); - - assertTrue( getSafeHtmlValidator().isValid( null, null ) ); - } - - @Test - public void testInvalidScriptTagIncluded() throws Exception { - descriptorBuilder.setAttribute( "whitelistType", WhiteListType.BASIC ); - - assertFalse( getSafeHtmlValidator().isValid( "HelloWorld !", null ) ); - } - - @Test - // A "downlevel revealed" conditional 'comment' is not an (X)HTML comment at all, - // despite the misleading name, it is default Microsoft syntax. - // The tag is unrecognized by therefore executed - public void testDownlevelRevealedConditionalComment() throws Exception { - descriptorBuilder.setAttribute( "whitelistType", WhiteListType.BASIC ); - - assertFalse( getSafeHtmlValidator().isValid( "\n\n", null ) ); - } - - @Test - public void testDownlevelHiddenConditionalComment() throws Exception { - descriptorBuilder.setAttribute( "whitelistType", WhiteListType.BASIC ); - - assertFalse( getSafeHtmlValidator().isValid( "", null ) ); - } - - @Test - public void testSimpleComment() throws Exception { - descriptorBuilder.setAttribute( "whitelistType", WhiteListType.BASIC ); - - assertFalse( getSafeHtmlValidator().isValid( "", null ) ); - } - - @Test - public void testServerSideIncludesSSI() throws Exception { - descriptorBuilder.setAttribute( "whitelistType", WhiteListType.BASIC ); - - assertFalse( getSafeHtmlValidator().isValid( "alert{\"XSS\"}'}; ?>", null ) ); - } - - @Test - public void testPHPScript() throws Exception { - descriptorBuilder.setAttribute( "whitelistType", WhiteListType.BASIC ); - - assertFalse( getSafeHtmlValidator().isValid( "alert{\"XSS\"}'}; ?>", null ) ); - } - - @Test - public void testInvalidIncompleteImgTagWithScriptIncluded() { - descriptorBuilder.setAttribute( "whitelistType", WhiteListType.BASIC ); - - assertFalse( getSafeHtmlValidator().isValid( "Link

    ", null ) ); - } - - @Test - public void testAdditionalTags() throws Exception { - descriptorBuilder.setAttribute( "additionalTags", new String[] { "script" } ); - - assertTrue( getSafeHtmlValidator().isValid( "HelloWorld !", null ) ); - } - - @Test - @TestForIssue(jiraKey = "HV-817") - public void testDivNotAllowedInBasicWhiteList() throws Exception { - descriptorBuilder.setAttribute( "whitelistType", WhiteListType.BASIC ); - - SafeHtmlValidator validator = getSafeHtmlValidator(); - assertFalse( validator.isValid( "
    test
    ", null ) ); - } - - @Test - @TestForIssue(jiraKey = "HV-817") - public void testDivAllowedInRelaxedWhiteList() throws Exception { - descriptorBuilder.setAttribute( "whitelistType", WhiteListType.RELAXED ); - - assertTrue( getSafeHtmlValidator().isValid( "
    test
    ", null ) ); - } - - @Test - @TestForIssue(jiraKey = "HV-817") - public void testDivWithWhiteListedClassAttribute() throws Exception { - descriptorBuilder.setAttribute( "whitelistType", WhiteListType.RELAXED ); - - AnnotationDescriptor.Builder tagDescriptorBuilder = new AnnotationDescriptor.Builder<>( SafeHtml.Tag.class ); - tagDescriptorBuilder.setAttribute( "name", "div" ); - tagDescriptorBuilder.setAttribute( "attributes", new String[] { "class" } ); - SafeHtml.Tag tag = tagDescriptorBuilder.build().getAnnotation(); - descriptorBuilder.setAttribute( "additionalTagsWithAttributes", new SafeHtml.Tag[] { tag } ); - - assertTrue( - getSafeHtmlValidator().isValid( "
    test
    ", null ), - "class attribute should be white listed" - ); - assertFalse( - getSafeHtmlValidator().isValid( "
    test
    ", null ), - "style attribute is not white listed" - ); - } - - @Test - @TestForIssue(jiraKey = "HV-817") - public void testDivWithWhiteListedStyleAttribute() throws Exception { - Validator validator = getValidator(); - Set> constraintViolations = validator.validate( new Foo( "
    test
    " ) ); - assertNoViolations( constraintViolations ); - - // the attributes are optional - allowing
    also allows just
    - constraintViolations = validator.validate( new Foo( "
    test
    " ) ); - assertNoViolations( constraintViolations ); - - constraintViolations = validator.validate( new Foo( "
    test
    " ) ); - assertThat( constraintViolations ).containsOnlyViolations( - violationOf( SafeHtml.class ) - ); - } - - @Test - @TestForIssue(jiraKey = "HV-873") - public void testValidationOfInvalidFragment() throws Exception { - descriptorBuilder.setAttribute( "whitelistType", WhiteListType.NONE ); - - assertFalse( getSafeHtmlValidator().isValid( "1234qwer", null ) ); - } - - @Test - @TestForIssue(jiraKey = "HV-873") - public void testValidationOfValidFragment() throws Exception { - descriptorBuilder.setAttribute( "whitelistType", WhiteListType.RELAXED ); - - assertTrue( getSafeHtmlValidator().isValid( "1234qwer", null ) ); - } - - @Test - @TestForIssue(jiraKey = "HV-873") - public void testValidationOfTextFragment() throws Exception { - descriptorBuilder.setAttribute( "whitelistType", WhiteListType.NONE ); - - assertTrue( getSafeHtmlValidator().isValid( "Foobar", null ) ); - } - - @Test - @TestForIssue(jiraKey = "HV-1302") - public void testAdditionalProtocols() { - Validator validator = getValidator(); - - assertNoViolations( validator.validate( new Bar( "" ) ) ); - assertNoViolations( validator.validate( new Bar( "" ) ) ); - assertThat( validator.validate( new Bar( "" ) ) ) - .containsOnlyViolations( - violationOf( SafeHtml.class ) - ); - assertThat( validator.validate( new Bar( "" ) ) ) - .containsOnlyViolations( - violationOf( SafeHtml.class ) - ); - assertThat( validator.validate( new Bar( "
    " ) ) ) - .containsOnlyViolations( - violationOf( SafeHtml.class ) - ); - assertThat( validator.validate( new Bar( "
    " ) ) ) - .containsOnlyViolations( - violationOf( SafeHtml.class ) - ); - assertNoViolations( validator.validate( new Bar( - "" + - " " + - " " + - " " + - " " + - "
    " + - " " + - "" ) ) ); - assertThat( validator.validate( new Bar( - "
    " + - "" + - "" + - "/
    " - ) ) ).containsOnlyViolations( - violationOf( SafeHtml.class ) - ); - } - - @Test - @TestForIssue(jiraKey = "HV-1303") - public void testPreserveRelativeLinks() throws Exception { - descriptorBuilder.setAttribute( "whitelistType", WhiteListType.RELAXED ); - descriptorBuilder.setAttribute( "baseURI", "http://127.0.0.1" ); - - assertTrue( getSafeHtmlValidator().isValid( "", null ) ); - - descriptorBuilder.setAttribute( "whitelistType", WhiteListType.RELAXED ); - descriptorBuilder.setAttribute( "baseURI", "" ); - - assertFalse( getSafeHtmlValidator().isValid( "", null ) ); - } - - private SafeHtmlValidator getSafeHtmlValidator() { - SafeHtml p = descriptorBuilder.build().getAnnotation(); - SafeHtmlValidator validator = new SafeHtmlValidator(); - validator.initialize( p ); - return validator; - } - - public static class Foo { - @SafeHtml( - whitelistType = WhiteListType.BASIC, - additionalTagsWithAttributes = @SafeHtml.Tag(name = "div", attributes = { "style" }) - ) - String source; - - public Foo(String source) { - this.source = source; - } - } - - public static class Bar { - @SafeHtml( - whitelistType = WhiteListType.BASIC, - additionalTagsWithAttributes = { - @SafeHtml.Tag(name = "img", attributesWithProtocols = @SafeHtml.Attribute(name = "src", protocols = { "data" })), - @SafeHtml.Tag(name = "custom", attributesWithProtocols = { - @SafeHtml.Attribute(name = "attr1", protocols = { "dataprotocol", "strange_protocol" }), - @SafeHtml.Attribute(name = "attr2", protocols = { "dataprotocol", "strange_protocol" }), - @SafeHtml.Attribute(name = "attr3", protocols = "some_protocol") - }), - @SafeHtml.Tag(name = "section", attributes = { "attr", "id" }) - } - ) - String source; - - public Bar(String source) { - this.source = source; - } - } -} diff --git a/integration/pom.xml b/integration/pom.xml index e9525e8b9a..1e170f3d5a 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -62,11 +62,6 @@ joda-time test - - org.jsoup - jsoup - test - javax.money money-api diff --git a/integration/src/test/java/org/hibernate/validator/integration/wildfly/OptionalConstraintsIT.java b/integration/src/test/java/org/hibernate/validator/integration/wildfly/OptionalConstraintsIT.java index 52c4f6218e..ab6d7246d5 100644 --- a/integration/src/test/java/org/hibernate/validator/integration/wildfly/OptionalConstraintsIT.java +++ b/integration/src/test/java/org/hibernate/validator/integration/wildfly/OptionalConstraintsIT.java @@ -18,7 +18,6 @@ import javax.validation.constraints.Future; import org.hibernate.validator.constraints.Currency; -import org.hibernate.validator.constraints.SafeHtml; import org.hibernate.validator.integration.AbstractArquillianIT; import org.javamoney.moneta.Money; import org.jboss.arquillian.container.test.api.Deployment; @@ -28,7 +27,7 @@ import org.testng.annotations.Test; /** - * Asserts that the constraints based on the JodaTime and JSoup server modules can be used. + * Asserts that the constraints based on the JodaTime and Javax Money server modules can be used. * * @author Gunnar Morling * @author Guillaume Smet @@ -57,14 +56,6 @@ public void canUseJodaTimeConstraintValidator() { assertThat( violations.iterator().next().getConstraintDescriptor().getAnnotation().annotationType() ).isEqualTo( Future.class ); } - @Test - public void canUseJsoupBasedConstraint() { - Set> violations = validator.validate( new Item() ); - - assertThat( violations.size() ).isEqualTo( 1 ); - assertThat( violations.iterator().next().getConstraintDescriptor().getAnnotation().annotationType() ).isEqualTo( SafeHtml.class ); - } - @Test public void canUseJavaMoneyBasedConstraint() { Set> violations = validator.validate( new Order( Money.of( 1200.0, "EUR" ) ) ); @@ -84,12 +75,6 @@ private static class Shipment { public DateTime deliveryDate = new DateTime( 2014, 10, 21, 0, 0, 0, 0 ); } - private static class Item { - - @SafeHtml - public String descriptionHtml = "