From 6b69a608b5ffef54d483bae2e932949ce733119a Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 4 Apr 2018 16:43:11 +0200 Subject: [PATCH 001/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] [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/271] [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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] [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/271] 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/271] 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/271] [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/271] [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/271] [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/271] [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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] [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/271] [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/271] [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/271] [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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] [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/271] [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/271] [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/271] [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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] =?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/271] 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/271] 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/271] 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/271] 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/271] 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/271] [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/271] [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/271] [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/271] [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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] [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/271] [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/271] [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/271] [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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] [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/271] [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/271] [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/271] [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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] [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/271] [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/271] [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/271] [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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] 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/271] [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/271] [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/271] [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