From 32e58c9ee36667ca510f88a021f9af1e4591400f Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 9 Apr 2020 14:39:43 +0200 Subject: [PATCH 01/94] HV-1763 Adjust performance profiles and add a benchmark for executable --- performance/pom.xml | 13 +- .../simple/ExecutableValidation.java | 158 ++++++++++++++++++ 2 files changed, 166 insertions(+), 5 deletions(-) create mode 100644 performance/src/main/java/org/hibernate/validator/performance/simple/ExecutableValidation.java diff --git a/performance/pom.xml b/performance/pom.xml index a00d6b54fe..ff638ad2d1 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -21,6 +21,9 @@ Hibernate Validator performance tests. + + true + From 65c54b2523a40678ea13d3edbf70408ae18e1848 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 10 Apr 2020 09:59:03 +0200 Subject: [PATCH 06/94] HV-1765 Upgrade WildFly versions to 18.0.1 and 19.0.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 1157f3adf1..2dcdfd1436 100644 --- a/pom.xml +++ b/pom.xml @@ -122,9 +122,9 @@ 2.1.0.Final - 18.0.0.Final + 19.0.0.Final - 17.0.1.Final + 18.0.1.Final ${version.wildfly} From 19699572cc7904990bc9ea44e51fae023f3a2c35 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 10 Apr 2020 12:06:51 +0200 Subject: [PATCH 07/94] HV-1765 Adjust javafx module installation for incontainer tests --- tck-runner/src/script/updateStandaloneXml.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tck-runner/src/script/updateStandaloneXml.groovy b/tck-runner/src/script/updateStandaloneXml.groovy index 258f1527f0..766bdff874 100644 --- a/tck-runner/src/script/updateStandaloneXml.groovy +++ b/tck-runner/src/script/updateStandaloneXml.groovy @@ -18,7 +18,7 @@ standaloneXml = new File( getPropertyValue('wildfly.target-dir'), 'standalone/co println "[INFO] Add javafx.api as global module" processFileInplace( standaloneXml ) { text -> - text.replaceAll( //, '\n \n \n ' ) + text.replaceAll( //, '\n \n \n ' ) } println "[INFO] ------------------------------------------------------------------------"; From 9f0b1498e8040703c8afd1acfcbf91ac759edef1 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 10 Apr 2020 11:22:27 +0000 Subject: [PATCH 08/94] [Jenkins release job] README.md updated by release build 6.1.3.Final --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ab0cabbb14..f779246c41 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hibernate Validator -*Version: 6.1.2.Final - 31-01-2020* +*Version: 6.1.3.Final - 10-04-2020* ## What is it? @@ -35,7 +35,7 @@ Logging will delegate any log requests to that provider. org.hibernate.validator hibernate-validator - 6.1.2.Final + 6.1.3.Final You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. @@ -54,7 +54,7 @@ extension by adding the following dependency: org.hibernate.validator hibernate-validator-cdi - 6.1.2.Final + 6.1.3.Final * _hibernate-validator-annotation-processor-<version>.jar_ is an optional jar which can be integrated with your build From ec2d496ffb2d82950ac081f76d7369545a5adcea Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 10 Apr 2020 11:22:27 +0000 Subject: [PATCH 09/94] [Jenkins release job] changelog.txt updated by release build 6.1.3.Final --- changelog.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/changelog.txt b/changelog.txt index c9510ff45d..ca5e7e0070 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,22 @@ Hibernate Validator Changelog ============================= +6.1.3.Final (10-04-2020) +------------------------- + +** Bug + * HV-1758 - translations - Extra dollar sign in validation messages for ModCheck + +** Improvement + * HV-1763 - engine - Improve performances of ExecutableHelper#getSignature + +** New Feature + * HV-1755 - engine - Introduce the notion of BeanMetaDataClassNormalizer in the standard ValidatorFactory + +** Task + * HV-1765 - integration - Upgrade WildFly versions to 18.0.1.Final and 19.0.0.Final + * HV-1764 - tests - Upgrade Jackson test dependencies to 2.10.3 + 6.1.2.Final (31-01-2020) ------------------------- From 0276343b8b0beeeb5bf33eb11e11eede91997670 Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 10 Apr 2020 11:22:34 +0000 Subject: [PATCH 10/94] [Jenkins release job] Preparing release 6.1.3.Final --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index 09b51bfb95..b25eb7b574 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index e5bd46024b..1d0b0dabe6 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index 43e9a6e463..cac39ef0d9 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index abccaa3efc..bd1fbf7222 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 82469be62b..1d2a3b08af 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index 51bf49a7da..4f3aded4da 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 5053e46480..53f5f9f8bc 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index f8268c9013..3abb7802af 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 1143f70ee5..547acbcac0 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 1ca38b61c0..86c46b4044 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 2f94c135be..6af6458a3a 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index 312d1f5749..72e6463d48 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index ff638ad2d1..b7c490d717 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/pom.xml b/pom.xml index 2dcdfd1436..2ebb2bc3bb 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 4bdb3a8d19..6d14318f13 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.3-SNAPSHOT + 6.1.3.Final org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index f75663d079..33940a623a 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.3-SNAPSHOT + 6.1.3.Final org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index 4af4e218e1..21af294406 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.3-SNAPSHOT + 6.1.3.Final org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index 956fc14494..0f21187879 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.3-SNAPSHOT + 6.1.3.Final org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 89f763fc8b..459823284f 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 70eeff7700..9782b4a65c 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index a7a3dfe691..03cf20bdd5 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3-SNAPSHOT + 6.1.3.Final hibernate-validator-test-utils From e7481a8bc8e18a92cb2d5521ae86125349655c3a Mon Sep 17 00:00:00 2001 From: Hibernate-CI Date: Fri, 10 Apr 2020 11:25:28 +0000 Subject: [PATCH 11/94] [Jenkins release job] Preparing next development iteration --- annotation-processor/pom.xml | 2 +- build-config/pom.xml | 2 +- cdi/pom.xml | 2 +- distribution/pom.xml | 2 +- documentation/pom.xml | 2 +- engine/pom.xml | 2 +- integration/pom.xml | 2 +- modules/pom.xml | 2 +- osgi/felixtest/pom.xml | 2 +- osgi/integrationtest/pom.xml | 2 +- osgi/karaf-features/pom.xml | 2 +- osgi/pom.xml | 2 +- performance/pom.xml | 2 +- pom.xml | 2 +- relocation/annotation-processor/pom.xml | 2 +- relocation/cdi/pom.xml | 2 +- relocation/engine/pom.xml | 2 +- relocation/karaf-features/pom.xml | 2 +- relocation/pom.xml | 2 +- tck-runner/pom.xml | 2 +- test-utils/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index b25eb7b574..59c19db310 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/build-config/pom.xml b/build-config/pom.xml index 1d0b0dabe6..b4dd834c9f 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index cac39ef0d9..4deda9adc1 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/distribution/pom.xml b/distribution/pom.xml index bd1fbf7222..10f2fac979 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index 1d2a3b08af..b7d925afb4 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/engine/pom.xml b/engine/pom.xml index 4f3aded4da..f68f0ecde1 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/integration/pom.xml b/integration/pom.xml index 53f5f9f8bc..37bc261fdd 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index 3abb7802af..f6b0817a02 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT 4.0.0 diff --git a/osgi/felixtest/pom.xml b/osgi/felixtest/pom.xml index 547acbcac0..7d627d5dbd 100644 --- a/osgi/felixtest/pom.xml +++ b/osgi/felixtest/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index 86c46b4044..a7dc8e5d0f 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 6af6458a3a..9e5867237d 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-osgi - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/osgi/pom.xml b/osgi/pom.xml index 72e6463d48..9c6b9294c3 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index b7c490d717..a79626ba2b 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 2ebb2bc3bb..2e47778273 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT pom Hibernate Validator Aggregator diff --git a/relocation/annotation-processor/pom.xml b/relocation/annotation-processor/pom.xml index 6d14318f13..33822787af 100644 --- a/relocation/annotation-processor/pom.xml +++ b/relocation/annotation-processor/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.3.Final + 6.1.4-SNAPSHOT org.hibernate diff --git a/relocation/cdi/pom.xml b/relocation/cdi/pom.xml index 33940a623a..6054919232 100644 --- a/relocation/cdi/pom.xml +++ b/relocation/cdi/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.3.Final + 6.1.4-SNAPSHOT org.hibernate diff --git a/relocation/engine/pom.xml b/relocation/engine/pom.xml index 21af294406..297bf58af5 100644 --- a/relocation/engine/pom.xml +++ b/relocation/engine/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.3.Final + 6.1.4-SNAPSHOT org.hibernate diff --git a/relocation/karaf-features/pom.xml b/relocation/karaf-features/pom.xml index 0f21187879..9dddc1ac27 100644 --- a/relocation/karaf-features/pom.xml +++ b/relocation/karaf-features/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-relocation - 6.1.3.Final + 6.1.4-SNAPSHOT org.hibernate diff --git a/relocation/pom.xml b/relocation/pom.xml index 459823284f..a14f5a2dbe 100644 --- a/relocation/pom.xml +++ b/relocation/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT hibernate-validator-relocation diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 9782b4a65c..447ae37af8 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT ../pom.xml diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 03cf20bdd5..330474de80 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate.validator hibernate-validator-parent - 6.1.3.Final + 6.1.4-SNAPSHOT hibernate-validator-test-utils From 94364343b598bc37e2bd5d18a486970c86668146 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Wed, 15 Apr 2020 20:03:21 +0200 Subject: [PATCH 12/94] HV-1767 Reduce the overhead of ConstraintHelper initialization in the predefined scope case --- ...dScopeHibernateValidatorConfiguration.java | 3 + .../PredefinedScopeConfigurationImpl.java | 13 + .../PredefinedScopeValidatorFactoryImpl.java | 2 +- .../internal/engine/ValidatorFactoryImpl.java | 2 +- .../metadata/core/BuiltinConstraint.java | 139 +++ .../metadata/core/ConstraintHelper.java | 853 ++++++++++-------- .../PredefinedScopeAllConstraintsTest.java | 457 ++++++++++ ...ssionLanguageMessageInterpolationTest.java | 4 +- ...ResourceBundleMessageInterpolatorTest.java | 8 +- .../metadata/core/ConstraintHelperTest.java | 2 +- .../metadata/core/MetaConstraintTest.java | 2 +- .../PredefinedScopeValidatorFactoryTest.java | 6 + ...nstraintValidatorInitializationHelper.java | 4 +- 13 files changed, 1092 insertions(+), 403 deletions(-) create mode 100644 engine/src/main/java/org/hibernate/validator/internal/metadata/core/BuiltinConstraint.java create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/PredefinedScopeAllConstraintsTest.java diff --git a/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java index 1f4a85118d..a295e88430 100644 --- a/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java +++ b/engine/src/main/java/org/hibernate/validator/PredefinedScopeHibernateValidatorConfiguration.java @@ -20,6 +20,9 @@ @Incubating public interface PredefinedScopeHibernateValidatorConfiguration extends BaseHibernateValidatorConfiguration { + @Incubating + PredefinedScopeHibernateValidatorConfiguration builtinConstraints(Set constraints); + @Incubating PredefinedScopeHibernateValidatorConfiguration initializeBeanMetaData(Set> beanClassesToInitialize); diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java index 3b8aadca30..15b239e627 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeConfigurationImpl.java @@ -8,6 +8,7 @@ import static org.hibernate.validator.internal.util.logging.Messages.MESSAGES; +import java.util.Collections; import java.util.Locale; import java.util.Set; @@ -25,6 +26,8 @@ public class PredefinedScopeConfigurationImpl extends AbstractConfigurationImpl implements PredefinedScopeHibernateValidatorConfiguration, ConfigurationState { + private Set builtinConstraints = Collections.emptySet(); + private Set> beanClassesToInitialize; public PredefinedScopeConfigurationImpl(BootstrapState state) { @@ -35,12 +38,22 @@ public PredefinedScopeConfigurationImpl(ValidationProvider validationProvider super( validationProvider ); } + @Override + public PredefinedScopeHibernateValidatorConfiguration builtinConstraints(Set constraints) { + this.builtinConstraints = CollectionHelper.toImmutableSet( constraints ); + return thisAsT(); + } + @Override public PredefinedScopeHibernateValidatorConfiguration initializeBeanMetaData(Set> beanMetaDataToInitialize) { beanClassesToInitialize = CollectionHelper.toImmutableSet( beanMetaDataToInitialize ); return thisAsT(); } + public Set getBuiltinConstraints() { + return builtinConstraints; + } + public Set> getBeanClassesToInitialize() { return beanClassesToInitialize; } diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java index 8785843e17..2eddf9153f 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/PredefinedScopeValidatorFactoryImpl.java @@ -132,7 +132,7 @@ public PredefinedScopeValidatorFactoryImpl(ConfigurationState configurationState this.getterPropertySelectionStrategy = ValidatorFactoryConfigurationHelper.determineGetterPropertySelectionStrategy( hibernateSpecificConfig, properties, externalClassLoader ); this.valueExtractorManager = new ValueExtractorManager( configurationState.getValueExtractors() ); - ConstraintHelper constraintHelper = new ConstraintHelper(); + ConstraintHelper constraintHelper = ConstraintHelper.forBuiltinConstraints( hibernateSpecificConfig.getBuiltinConstraints() ); TypeResolutionHelper typeResolutionHelper = new TypeResolutionHelper(); ConstraintCreationContext constraintCreationContext = new ConstraintCreationContext( constraintHelper, diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java index 581b597443..918177fd46 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorFactoryImpl.java @@ -167,7 +167,7 @@ public ValidatorFactoryImpl(ConfigurationState configurationState) { this.validationOrderGenerator = new ValidationOrderGenerator(); ValueExtractorManager valueExtractorManager = new ValueExtractorManager( configurationState.getValueExtractors() ); - ConstraintHelper constraintHelper = new ConstraintHelper(); + ConstraintHelper constraintHelper = ConstraintHelper.forAllBuiltinConstraints(); TypeResolutionHelper typeResolutionHelper = new TypeResolutionHelper(); this.constraintCreationContext = new ConstraintCreationContext( constraintHelper, constraintValidatorManager, typeResolutionHelper, valueExtractorManager ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/core/BuiltinConstraint.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/BuiltinConstraint.java new file mode 100644 index 0000000000..9a7197359b --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/core/BuiltinConstraint.java @@ -0,0 +1,139 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.internal.metadata.core; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * The list of built-in constraints. + *

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

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

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

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

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

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

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

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

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

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

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

+ * Depends on the context. + *

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

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

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

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

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