diff --git a/README.md b/README.md index 991443e161..243e48fccb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hibernate Validator -*Version: 5.4.1.Final - 16-03-2017* +*Version: 5.4.2.Final - 19-10-2017* ## What is it? @@ -35,7 +35,7 @@ Logging will delegate any log requests to that provider. org.hibernate hibernate-validator - 5.4.1.Final + 5.4.2.Final You also need an API and implementation of the Unified Expression Language. These dependencies must be explicitly added in an SE environment. @@ -54,7 +54,7 @@ extension by adding the following dependency: org.hibernate hibernate-validator-cdi - 5.4.1.Final + 5.4.2.Final * _hibernate-validator-annotation-processor-<version>.jar_ is an optional jar which can be integrated with your build diff --git a/annotation-processor/pom.xml b/annotation-processor/pom.xml index a73b833c18..e7eaa1f724 100644 --- a/annotation-processor/pom.xml +++ b/annotation-processor/pom.xml @@ -11,7 +11,7 @@ hibernate-validator-parent org.hibernate - 5.4.1.Final + 5.4.2.Final ../pom.xml diff --git a/annotation-processor/src/main/java/org/hibernate/validator/ap/ClassVisitor.java b/annotation-processor/src/main/java/org/hibernate/validator/ap/ClassVisitor.java index 887f429089..cea7a40c3b 100644 --- a/annotation-processor/src/main/java/org/hibernate/validator/ap/ClassVisitor.java +++ b/annotation-processor/src/main/java/org/hibernate/validator/ap/ClassVisitor.java @@ -11,6 +11,7 @@ import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Name; import javax.lang.model.element.TypeElement; import javax.lang.model.util.Elements; import javax.tools.Diagnostic; @@ -33,6 +34,8 @@ */ public class ClassVisitor extends AbstractElementVisitor { + private final Set processedTypes; + private final ClassCheckFactory factory; private final Elements elementUtils; @@ -54,6 +57,8 @@ public ClassVisitor( ) ) ); + + this.processedTypes = CollectionHelper.newHashSet(); } /** @@ -101,8 +106,12 @@ public Void visitExecutableAsMethod(ExecutableElement element, Void aVoid) { * @param typeElement inner elements of which you want to visit */ private void visitAllMyElements(TypeElement typeElement) { - for ( Element element : elementUtils.getAllMembers( typeElement ) ) { - visit( element ); + Name qualifiedName = typeElement.getQualifiedName(); + if ( !processedTypes.contains( qualifiedName ) ) { + processedTypes.add( qualifiedName ); + for ( Element element : elementUtils.getAllMembers( typeElement ) ) { + visit( element ); + } } } diff --git a/annotation-processor/src/test/java/org/hibernate/validator/ap/CircularNestedTypesTest.java b/annotation-processor/src/test/java/org/hibernate/validator/ap/CircularNestedTypesTest.java new file mode 100644 index 0000000000..a1bd00b4ee --- /dev/null +++ b/annotation-processor/src/test/java/org/hibernate/validator/ap/CircularNestedTypesTest.java @@ -0,0 +1,32 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.ap; + +import static org.testng.Assert.assertTrue; + +import org.hibernate.validator.ap.testmodel.circular.CircularProperty; +import org.hibernate.validator.ap.testmodel.circular.CircularPropertyImpl; +import org.testng.annotations.Test; + +/** + * Tests that in case of circular nested types there's no infinite loop during analysis. + * + * @author Marko Bekhta + */ +public class CircularNestedTypesTest extends ConstraintValidationProcessorTestBase { + + @Test + public void testNoInfiniteLoop() { + boolean compilationResult = + compilerHelper.compile( new ConstraintValidationProcessor(), diagnostics, + compilerHelper.getSourceFile( CircularPropertyImpl.class ), + compilerHelper.getSourceFile( CircularProperty.class ) + ); + + assertTrue( compilationResult ); + } +} diff --git a/annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/circular/CircularProperty.java b/annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/circular/CircularProperty.java new file mode 100644 index 0000000000..78376f5176 --- /dev/null +++ b/annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/circular/CircularProperty.java @@ -0,0 +1,20 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.ap.testmodel.circular; + +/** + * @author Marko Bekhta + */ +public interface CircularProperty { + + void doSomething(); + + interface ImprovedCircularProperty extends CircularProperty { + + void maybeDoSomething(); + } +} diff --git a/annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/circular/CircularPropertyImpl.java b/annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/circular/CircularPropertyImpl.java new file mode 100644 index 0000000000..158590de4b --- /dev/null +++ b/annotation-processor/src/test/java/org/hibernate/validator/ap/testmodel/circular/CircularPropertyImpl.java @@ -0,0 +1,18 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.ap.testmodel.circular; + +/** + * @author Marko Bekhta + */ +public class CircularPropertyImpl implements CircularProperty { + + @Override + public void doSomething() { + //nothing here + } +} diff --git a/build-config/pom.xml b/build-config/pom.xml index 1023709042..4c256a224b 100644 --- a/build-config/pom.xml +++ b/build-config/pom.xml @@ -11,7 +11,7 @@ hibernate-validator-parent org.hibernate - 5.4.1.Final + 5.4.2.Final ../pom.xml diff --git a/cdi/pom.xml b/cdi/pom.xml index b94db100b5..a37865b167 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -11,7 +11,7 @@ hibernate-validator-parent org.hibernate - 5.4.1.Final + 5.4.2.Final ../pom.xml @@ -145,6 +145,15 @@ jar + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + Bean Validation + 2.0 + + + @@ -160,8 +169,8 @@ javax.interceptor.*;version="[1.2,2.0)", javax.enterprise.*;version="[1.2,2.0)" - org.hibernate.validator.cdi - org.hibernate.validator.internal.* + org.hibernate.validator.cdi;version="${project.version}" + org.hibernate.validator.internal.*;version="${project.version}" diff --git a/changelog.txt b/changelog.txt index 8940c09cd1..f21f3bbb3f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,21 @@ Hibernate Validator Changelog ============================= +5.4.2.Final (19-10-2017) +------------------------- + +** Bug + * HV-1498 - engine - Privilege escalation when running under the security manager + * HV-1494 - validators - Hibernate Validator specific @NotEmpty used on return type throws an exception + * HV-1429 - integration - Incorrect URL in Paranamer Karaf feature + * HV-1377 - annotation-processor - StackOverflowError during compilation with annotation-processor enabled + * HV-1352 - engine - Incorrect value handler on trace logging + * HV-1293 - validators - @Size validator is not declared for short[] + +** Improvement + * HV-1454 - build - Support JDK 9 build 180 + * HV-1294 - build - hibernate-validator-cdi artefact is not OSGI'ed + 5.4.1.Final (16-03-2017) ------------------------- diff --git a/distribution/pom.xml b/distribution/pom.xml index af3833cdf8..d3eac0e327 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -10,7 +10,7 @@ hibernate-validator-parent org.hibernate - 5.4.1.Final + 5.4.2.Final ../pom.xml diff --git a/documentation/pom.xml b/documentation/pom.xml index da0713952a..663a176c72 100644 --- a/documentation/pom.xml +++ b/documentation/pom.xml @@ -11,7 +11,7 @@ hibernate-validator-parent org.hibernate - 5.4.1.Final + 5.4.2.Final ../pom.xml diff --git a/documentation/src/main/asciidoc/ch01.asciidoc b/documentation/src/main/asciidoc/ch01.asciidoc index 608e9660db..35daf8dec7 100644 --- a/documentation/src/main/asciidoc/ch01.asciidoc +++ b/documentation/src/main/asciidoc/ch01.asciidoc @@ -101,6 +101,8 @@ grant codeBase "file:path/to/hibernate-validator-{hvVersion}.jar" { permission java.lang.RuntimePermission "accessDeclaredMembers"; permission java.lang.RuntimePermission "setContextClassLoader"; + permission org.hibernate.validator.HibernateValidatorPermission "accessPrivateMembers"; + // Only needed when working with XML descriptors (validation.xml or XML constraint mappings) permission java.util.PropertyPermission "mapAnyUriToUri", "read"; }; diff --git a/engine-jdk8-tests/pom.xml b/engine-jdk8-tests/pom.xml index 6ddda523ac..c24b7cf08f 100644 --- a/engine-jdk8-tests/pom.xml +++ b/engine-jdk8-tests/pom.xml @@ -10,7 +10,7 @@ org.hibernate hibernate-validator-parent - 5.4.1.Final + 5.4.2.Final hibernate-validator-engine-jdk8-tests diff --git a/engine/pom.xml b/engine/pom.xml index 59dba7cc29..343639b757 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -11,7 +11,7 @@ hibernate-validator-parent org.hibernate - 5.4.1.Final + 5.4.2.Final ../pom.xml diff --git a/engine/src/main/java/org/hibernate/validator/HibernateValidatorPermission.java b/engine/src/main/java/org/hibernate/validator/HibernateValidatorPermission.java new file mode 100644 index 0000000000..71b33b75fb --- /dev/null +++ b/engine/src/main/java/org/hibernate/validator/HibernateValidatorPermission.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; + +import java.security.BasicPermission; + +/** + * Our specific implementation of {@link BasicPermission} as we cannot define additional {@link RuntimePermission}. + *

+ * {@code HibernateValidatorPermission} is thread-safe and immutable. + * + * @author Guillaume Smet + */ +public class HibernateValidatorPermission extends BasicPermission { + + public static final HibernateValidatorPermission ACCESS_PRIVATE_MEMBERS = new HibernateValidatorPermission( "accessPrivateMembers" ); + + public HibernateValidatorPermission(String name) { + super( name ); + } + + public HibernateValidatorPermission(String name, String actions) { + super( name, actions ); + } +} diff --git a/engine/src/main/java/org/hibernate/validator/constraints/NotEmpty.java b/engine/src/main/java/org/hibernate/validator/constraints/NotEmpty.java index a4112b38d6..7115622572 100644 --- a/engine/src/main/java/org/hibernate/validator/constraints/NotEmpty.java +++ b/engine/src/main/java/org/hibernate/validator/constraints/NotEmpty.java @@ -14,6 +14,8 @@ import javax.validation.ReportAsSingleViolation; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; +import javax.validation.constraintvalidation.SupportedValidationTarget; +import javax.validation.constraintvalidation.ValidationTarget; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.CONSTRUCTOR; @@ -30,6 +32,7 @@ */ @Documented @Constraint(validatedBy = { }) +@SupportedValidationTarget(ValidationTarget.ANNOTATED_ELEMENT) @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) @Retention(RUNTIME) @ReportAsSingleViolation diff --git a/engine/src/main/java/org/hibernate/validator/constraints/Range.java b/engine/src/main/java/org/hibernate/validator/constraints/Range.java index 1ec6abab73..676c03fb0c 100644 --- a/engine/src/main/java/org/hibernate/validator/constraints/Range.java +++ b/engine/src/main/java/org/hibernate/validator/constraints/Range.java @@ -15,6 +15,8 @@ import javax.validation.ReportAsSingleViolation; import javax.validation.constraints.Max; import javax.validation.constraints.Min; +import javax.validation.constraintvalidation.SupportedValidationTarget; +import javax.validation.constraintvalidation.ValidationTarget; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.CONSTRUCTOR; @@ -31,6 +33,7 @@ */ @Documented @Constraint(validatedBy = { }) +@SupportedValidationTarget(ValidationTarget.ANNOTATED_ELEMENT) @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) @Retention(RUNTIME) @Min(0) diff --git a/engine/src/main/java/org/hibernate/validator/constraints/br/TituloEleitoral.java b/engine/src/main/java/org/hibernate/validator/constraints/br/TituloEleitoral.java index 435ca54372..2c21049af1 100644 --- a/engine/src/main/java/org/hibernate/validator/constraints/br/TituloEleitoral.java +++ b/engine/src/main/java/org/hibernate/validator/constraints/br/TituloEleitoral.java @@ -13,6 +13,8 @@ import javax.validation.Payload; import javax.validation.ReportAsSingleViolation; import javax.validation.constraints.Pattern; +import javax.validation.constraintvalidation.SupportedValidationTarget; +import javax.validation.constraintvalidation.ValidationTarget; import org.hibernate.validator.constraints.Mod11Check; import org.hibernate.validator.constraints.Mod11Check.List; @@ -42,6 +44,7 @@ @ReportAsSingleViolation @Documented @Constraint(validatedBy = { }) +@SupportedValidationTarget(ValidationTarget.ANNOTATED_ELEMENT) @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) @Retention(RUNTIME) public @interface TituloEleitoral { diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java index d65277818f..19dd8075a9 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java @@ -40,6 +40,7 @@ import javax.validation.groups.Default; import javax.validation.metadata.BeanDescriptor; +import org.hibernate.validator.HibernateValidatorPermission; import org.hibernate.validator.internal.engine.ValidationContext.ValidationContextBuilder; import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManager; import org.hibernate.validator.internal.engine.groups.Group; @@ -1739,6 +1740,11 @@ private Member getAccessible(Member original) { return member; } + SecurityManager sm = System.getSecurityManager(); + if ( sm != null ) { + sm.checkPermission( HibernateValidatorPermission.ACCESS_PRIVATE_MEMBERS ); + } + Class clazz = original.getDeclaringClass(); if ( original instanceof Field ) { diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java index e4eba77281..aeb0b1d8d7 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java +++ b/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintTree.java @@ -6,11 +6,18 @@ */ package org.hibernate.validator.internal.engine.constraintvalidation; +import static org.hibernate.validator.constraints.CompositionType.ALL_FALSE; +import static org.hibernate.validator.constraints.CompositionType.AND; +import static org.hibernate.validator.constraints.CompositionType.OR; +import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; +import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; + import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.Collections; import java.util.List; import java.util.Set; + import javax.validation.ConstraintValidator; import javax.validation.ConstraintViolation; @@ -23,12 +30,6 @@ import org.hibernate.validator.internal.util.logging.LoggerFactory; import org.hibernate.validator.spi.valuehandling.ValidatedValueUnwrapper; -import static org.hibernate.validator.constraints.CompositionType.ALL_FALSE; -import static org.hibernate.validator.constraints.CompositionType.AND; -import static org.hibernate.validator.constraints.CompositionType.OR; -import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList; -import static org.hibernate.validator.internal.util.CollectionHelper.newHashSet; - /** * Due to constraint composition a single constraint annotation can lead to a whole constraint tree being validated. * This class encapsulates such a tree. @@ -104,6 +105,9 @@ private void validateConstraints(ValidationContext validationContext, // After all children are validated the actual ConstraintValidator of the constraint itself is executed if ( mainConstraintNeedsEvaluation( validationContext, constraintViolations ) ) { + // find the right constraint validator + ConstraintValidator validator = getInitializedConstraintValidator( validationContext, valueContext ); + if ( log.isTraceEnabled() ) { log.tracef( "Validating value %s against constraint defined by %s.", @@ -112,9 +116,6 @@ private void validateConstraints(ValidationContext validationContext, ); } - // find the right constraint validator - ConstraintValidator validator = getInitializedConstraintValidator( validationContext, valueContext ); - // create a constraint validator context ConstraintValidatorContextImpl constraintValidatorContext = new ConstraintValidatorContextImpl( validationContext.getParameterNames(), diff --git a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java index bda4c64c86..9d3fd7e329 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java +++ b/engine/src/main/java/org/hibernate/validator/internal/metadata/aggregated/PropertyMetaData.java @@ -25,6 +25,7 @@ import javax.validation.ElementKind; import javax.validation.metadata.GroupConversionDescriptor; +import org.hibernate.validator.HibernateValidatorPermission; import org.hibernate.validator.internal.engine.valuehandling.UnwrapMode; import org.hibernate.validator.internal.metadata.core.ConstraintHelper; import org.hibernate.validator.internal.metadata.core.MetaConstraint; @@ -119,6 +120,11 @@ private static Member getAccessible(Member original) { return original; } + SecurityManager sm = System.getSecurityManager(); + if ( sm != null ) { + sm.checkPermission( HibernateValidatorPermission.ACCESS_PRIVATE_MEMBERS ); + } + Class clazz = original.getDeclaringClass(); Member member; 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 a324afd0c2..7d47e11290 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 @@ -102,6 +102,7 @@ import org.hibernate.validator.internal.constraintvalidators.bv.size.SizeValidatorForArraysOfFloat; import org.hibernate.validator.internal.constraintvalidators.bv.size.SizeValidatorForArraysOfInt; import org.hibernate.validator.internal.constraintvalidators.bv.size.SizeValidatorForArraysOfLong; +import org.hibernate.validator.internal.constraintvalidators.bv.size.SizeValidatorForArraysOfShort; import org.hibernate.validator.internal.constraintvalidators.bv.size.SizeValidatorForCharSequence; import org.hibernate.validator.internal.constraintvalidators.bv.size.SizeValidatorForCollection; import org.hibernate.validator.internal.constraintvalidators.bv.size.SizeValidatorForMap; @@ -231,6 +232,7 @@ public ConstraintHelper() { sizeValidators.add( SizeValidatorForArraysOfFloat.class ); sizeValidators.add( SizeValidatorForArraysOfInt.class ); sizeValidators.add( SizeValidatorForArraysOfLong.class ); + sizeValidators.add( SizeValidatorForArraysOfShort.class ); putConstraints( tmpConstraints, Size.class, sizeValidators ); diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetDeclaredField.java b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetDeclaredField.java index e996f7fd8c..2a4392e368 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetDeclaredField.java +++ b/engine/src/main/java/org/hibernate/validator/internal/util/privilegedactions/GetDeclaredField.java @@ -31,7 +31,6 @@ private GetDeclaredField(Class clazz, String fieldName) { public Field run() { try { final Field field = clazz.getDeclaredField( fieldName ); - field.setAccessible( true ); return field; } catch (NoSuchFieldException e) { diff --git a/engine/src/test/java/org/hibernate/validator/test/TraceLoggingTest.java b/engine/src/test/java/org/hibernate/validator/test/TraceLoggingTest.java new file mode 100644 index 0000000000..cd1f092af4 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/TraceLoggingTest.java @@ -0,0 +1,63 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test; + +import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertNumberOfViolations; +import static org.hibernate.validator.testutils.ValidatorUtil.getValidator; + +import java.util.Optional; + +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.testutil.TestForIssue; +import org.hibernate.validator.valuehandling.UnwrapValidatedValue; + +import org.apache.log4j.Level; +import org.apache.log4j.LogManager; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * @author Marko Bekhta + */ +public class TraceLoggingTest { + + private Level currentLevel; + + @BeforeMethod + public void setUp() throws Exception { + currentLevel = LogManager.getRootLogger().getLevel(); + LogManager.getRootLogger().setLevel( Level.TRACE ); + } + + @Test + @TestForIssue(jiraKey = "HV-1352") + public void testLoggingIsNotFailing() { + assertNumberOfViolations( getValidator().validate( new Foo( Optional.of( 1 ), 1 ) ), 0 ); + } + + @AfterMethod + public void tearDown() throws Exception { + LogManager.getRootLogger().setLevel( currentLevel ); + } + + private static class Foo { + + @NotNull + @UnwrapValidatedValue + private final Optional optInt; + @NotNull + private final Integer integer; + + public Foo(@NotNull Optional optInt, @NotNull Integer integer) { + this.optInt = optInt; + this.integer = integer; + } + } + +} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/PureCompositeConstraintsOnReturnValueTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/PureCompositeConstraintsOnReturnValueTest.java new file mode 100644 index 0000000000..935c0735d3 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/methodvalidation/PureCompositeConstraintsOnReturnValueTest.java @@ -0,0 +1,149 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.engine.methodvalidation; + +import static 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 static org.hibernate.validator.testutil.ConstraintViolationAssert.assertCorrectConstraintTypes; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertNumberOfViolations; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.util.Set; + +import javax.validation.Constraint; +import javax.validation.ConstraintViolation; +import javax.validation.Payload; +import javax.validation.ReportAsSingleViolation; +import javax.validation.Validator; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; +import javax.validation.constraintvalidation.SupportedValidationTarget; +import javax.validation.constraintvalidation.ValidationTarget; + +import org.hibernate.validator.constraints.NotEmpty; +import org.hibernate.validator.testutil.TestForIssue; +import org.hibernate.validator.testutils.ValidatorUtil; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * @author Marko Bekhta + */ +public class PureCompositeConstraintsOnReturnValueTest { + private Validator validator; + private Foo foo; + + @BeforeMethod + public void setUp() throws Exception { + validator = ValidatorUtil.getValidator(); + foo = new Foo( "" ); + } + + @Test + @TestForIssue( jiraKey = "HV-1494") + public void testHVSpecificNotEmpty() throws Exception { + Set> violations = validator.forExecutables() + .validateReturnValue( + foo, + Foo.class.getDeclaredMethod( "createBarString", String.class ), + "" + ); + assertCorrectConstraintTypes( violations, NotEmpty.class ); + + violations = validator.forExecutables() + .validateReturnValue( + foo, + Foo.class.getDeclaredMethod( "createBarString", String.class ), + " " + ); + assertNumberOfViolations( violations, 0 ); + } + + @Test + @TestForIssue( jiraKey = "HV-1494") + public void testCustomComposingConstraintOnReturnValue() throws Exception { + Set> violations = validator.forExecutables() + .validateReturnValue( + foo, + Foo.class.getDeclaredMethod( "createCustomBarString", String.class ), + "a" + ); + assertCorrectConstraintTypes( violations, CustomCompositeConstraint.class ); + + violations = validator.forExecutables() + .validateReturnValue( + foo, + Foo.class.getDeclaredMethod( "createCustomBarString", String.class ), + "1" + ); + assertNumberOfViolations( violations, 0 ); + } + + @Test + @TestForIssue( jiraKey = "HV-1494") + public void testCustomComposingConstraintOnParameters() throws Exception { + Set> violations = validator.forExecutables() + .validateParameters( + foo, + Foo.class.getDeclaredMethod( "createCustomBarString", String.class ), + new String[] { "abc" } + ); + assertCorrectConstraintTypes( violations, CustomCompositeConstraint.class ); + + violations = validator.forExecutables() + .validateParameters( + foo, + Foo.class.getDeclaredMethod( "createCustomBarString", String.class ), + new String[] { "1" } + ); + assertNumberOfViolations( violations, 0 ); + } + + private static class Foo { + + private String bar; + + public Foo(String bar) { + this.bar = bar; + } + + @NotEmpty + public String createBarString(String a) { + return bar; + } + + @CustomCompositeConstraint + public String createCustomBarString(@CustomCompositeConstraint String a) { + return bar; + } + } + + @Documented + @Constraint(validatedBy = { }) + @SupportedValidationTarget(ValidationTarget.ANNOTATED_ELEMENT) + @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) + @Retention(RUNTIME) + @ReportAsSingleViolation + @NotNull + @Size(min = 1) + @Pattern(regexp = "\\d*") + public @interface CustomCompositeConstraint { + String message() default "no message"; + + Class[] groups() default { }; + + Class[] payload() default { }; + } +} diff --git a/integration/pom.xml b/integration/pom.xml index 4f35198912..dccf129bc4 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -11,7 +11,7 @@ hibernate-validator-parent org.hibernate - 5.4.1.Final + 5.4.2.Final ../pom.xml diff --git a/modules/pom.xml b/modules/pom.xml index 76ce03949c..31b1370795 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -5,7 +5,7 @@ hibernate-validator-parent org.hibernate - 5.4.1.Final + 5.4.2.Final 4.0.0 diff --git a/osgi/integrationtest/pom.xml b/osgi/integrationtest/pom.xml index e23b1794bb..b8020a7887 100644 --- a/osgi/integrationtest/pom.xml +++ b/osgi/integrationtest/pom.xml @@ -11,7 +11,7 @@ hibernate-validator-osgi org.hibernate - 5.4.1.Final + 5.4.2.Final ../pom.xml @@ -85,6 +85,12 @@ + + org.apache.karaf.features + org.apache.karaf.features.core + ${apache.karaf.version} + test + org.ops4j.pax.exam pax-exam-junit4 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 new file mode 100644 index 0000000000..99b15c40ba --- /dev/null +++ b/osgi/integrationtest/src/test/java/org/hibernate/validator/osgi/integrationtest/KarafFeaturesAreInstallableTest.java @@ -0,0 +1,120 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.osgi.integrationtest; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.ops4j.pax.exam.CoreOptions.maven; +import static org.ops4j.pax.exam.CoreOptions.options; +import static org.ops4j.pax.exam.CoreOptions.systemProperty; +import static org.ops4j.pax.exam.CoreOptions.when; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.configureConsole; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.logLevel; + +import java.io.File; +import java.net.URI; +import java.util.Locale; + +import javax.inject.Inject; + +import org.apache.karaf.features.Feature; +import org.apache.karaf.features.FeaturesService; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.karaf.options.LogLevelOption; +import org.ops4j.pax.exam.options.MavenArtifactUrlReference; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +/** + * Integration test for Bean Validation and Hibernate Validator under OSGi. + *

+ * This test makes sure that the Karaf features provided by this project are installable. + *

+ * Note that if a feature is not installable, the test gets stuck for a while but it is a + * good indication that something is wrong. + * + * @author Toni Menzel (toni@rebaze.com) + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class KarafFeaturesAreInstallableTest { + + @Inject + private FeaturesService featuresService; + + private static final boolean DEBUG = false; + + @Configuration + public Option[] config() { + MavenArtifactUrlReference hibernateValidatorFeature = maven() + .groupId( "org.hibernate" ) + .artifactId( "hibernate-validator-osgi-karaf-features" ) + .classifier( "features" ) + .type( "xml" ) + .versionAsInProject(); + + return options( + when( DEBUG ).useOptions( debugConfiguration( "5005", true ) ), + karafDistributionConfiguration() + .frameworkUrl( + maven() + .groupId( "org.apache.karaf" ) + .artifactId( "apache-karaf" ) + .type( "tar.gz" ) + .versionAsInProject() + ) + .unpackDirectory( new File( "target/exam" ) ) + .useDeployFolder( false ), + configureConsole() + .ignoreLocalConsole() + .ignoreRemoteShell(), + when( DEBUG ).useOptions( keepRuntimeFolder() ), + logLevel( LogLevelOption.LogLevel.INFO ), + // avoiding additional boot features; specifically "enterprise" which already comes with a HV feature + // "system" is the absolute minimum, but enough for our purposes + editConfigurationFilePut( + "etc/org.apache.karaf.features.cfg", + "featuresBoot", + "system" + ), + systemProperty( "validatorRepositoryUrl" ).value( hibernateValidatorFeature.getURL() ) + ); + } + + @BeforeClass + public static void setLocaleToEnglish() { + Locale.setDefault( Locale.ENGLISH ); + } + + @Test + public void canInstallFeatureHibernateValidator() throws Exception { + featuresService.addRepository( new URI( System.getProperty( "validatorRepositoryUrl" ) ) ); + canInstallFeature( "hibernate-validator" ); + } + + @Test + public void canInstallFeatureHibernateValidatorParanamer() throws Exception { + featuresService.addRepository( new URI( System.getProperty( "validatorRepositoryUrl" ) ) ); + canInstallFeature( "hibernate-validator-paranamer" ); + } + + public void canInstallFeature(String featureName) throws Exception { + Feature feature = featuresService.getFeature( featureName ); + assertNotNull( "Feature " + featureName + " is not available from features list", feature ); + featuresService.installFeature( featureName ); + assertTrue( "Feature " + featureName + " isn't installed, though available from features list", featuresService.isInstalled( feature ) ); + } +} diff --git a/osgi/karaf-features/pom.xml b/osgi/karaf-features/pom.xml index 0d135bca71..057991dcb1 100644 --- a/osgi/karaf-features/pom.xml +++ b/osgi/karaf-features/pom.xml @@ -11,7 +11,7 @@ hibernate-validator-osgi org.hibernate - 5.4.1.Final + 5.4.2.Final ../pom.xml diff --git a/osgi/karaf-features/src/main/features/features.xml b/osgi/karaf-features/src/main/features/features.xml index 0e34fbbef0..ff41daff20 100644 --- a/osgi/karaf-features/src/main/features/features.xml +++ b/osgi/karaf-features/src/main/features/features.xml @@ -26,6 +26,6 @@ wrap hibernate-validator - wrap:mvn:com.thoughtworks.paranamer:paranamer:${paranamer.version} + wrap:mvn:com.thoughtworks.paranamer/paranamer/${paranamer.version} diff --git a/osgi/pom.xml b/osgi/pom.xml index a6c75fdb56..c8cea5eedf 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -11,7 +11,7 @@ hibernate-validator-parent org.hibernate - 5.4.1.Final + 5.4.2.Final ../pom.xml diff --git a/performance/pom.xml b/performance/pom.xml index be160a9bbe..bc4214085b 100644 --- a/performance/pom.xml +++ b/performance/pom.xml @@ -11,7 +11,7 @@ hibernate-validator-parent org.hibernate - 5.4.1.Final + 5.4.2.Final ../pom.xml diff --git a/pom.xml b/pom.xml index 17ea961d3f..4fb84887d5 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.hibernate hibernate-validator-parent - 5.4.1.Final + 5.4.2.Final pom Hibernate Validator Aggregator @@ -387,7 +387,7 @@ maven-enforcer-plugin - 1.4.1 + 3.0.0-M1 enforce-java @@ -673,7 +673,7 @@ maven-javadoc-plugin - 2.10.4 + 3.0.0-M1 true ${project.basedir}/../src/main/javadoc diff --git a/tck-runner/pom.xml b/tck-runner/pom.xml index 7f3547d73a..4a64855c1c 100644 --- a/tck-runner/pom.xml +++ b/tck-runner/pom.xml @@ -11,7 +11,7 @@ hibernate-validator-parent org.hibernate - 5.4.1.Final + 5.4.2.Final ../pom.xml diff --git a/tck-runner/src/test/resources/test.policy b/tck-runner/src/test/resources/test.policy index b2a4fbd1c6..fedfaede4e 100644 --- a/tck-runner/src/test/resources/test.policy +++ b/tck-runner/src/test/resources/test.policy @@ -28,6 +28,8 @@ grant codeBase "file:${localRepository}/org/hibernate/hibernate-validator/${proj permission java.lang.RuntimePermission "accessDeclaredMembers"; permission java.lang.RuntimePermission "setContextClassLoader"; + permission org.hibernate.validator.HibernateValidatorPermission "accessPrivateMembers"; + // JAXB permission java.util.PropertyPermission "mapAnyUriToUri", "read"; }; @@ -39,6 +41,8 @@ grant codeBase "file:${basedir}/../engine/target/hibernate-validator-${project.v permission java.lang.RuntimePermission "accessDeclaredMembers"; permission java.lang.RuntimePermission "setContextClassLoader"; + permission org.hibernate.validator.HibernateValidatorPermission "accessPrivateMembers"; + // JAXB permission java.util.PropertyPermission "mapAnyUriToUri", "read"; }; @@ -81,6 +85,7 @@ grant codeBase "file:${project.build.directory}/classes" { permission java.util.PropertyPermission "validation.provider", "read"; permission java.io.FilePermission "${localRepository}/org/hibernate/beanvalidation/tck/beanvalidation-tck-tests/${tck.version}/beanvalidation-tck-tests-${tck.version}.jar", "read"; permission java.util.PropertyPermission "user.language", "write"; + permission org.hibernate.validator.HibernateValidatorPermission "accessPrivateMembers"; }; grant codeBase "file:${project.build.directory}/test-classes" { diff --git a/test-utils/pom.xml b/test-utils/pom.xml index 81076cab9f..9ebae6a184 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -10,7 +10,7 @@ org.hibernate hibernate-validator-parent - 5.4.1.Final + 5.4.2.Final hibernate-validator-test-utils