From 7d6980d6844160af24ae20bfcc1bb80bba29fa56 Mon Sep 17 00:00:00 2001 From: Hardy Ferentschik Date: Fri, 23 Mar 2012 15:57:46 +0100 Subject: [PATCH 1/8] HV-563 Using @TestForIssue annotation --- .../test/internal/xml/XmlMappingTest.java | 25 ++++++------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/internal/xml/XmlMappingTest.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/internal/xml/XmlMappingTest.java index c8d5c16841..8ea6a984b5 100644 --- a/hibernate-validator/src/test/java/org/hibernate/validator/test/internal/xml/XmlMappingTest.java +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/internal/xml/XmlMappingTest.java @@ -33,6 +33,7 @@ import org.hibernate.validator.HibernateValidatorConfiguration; import org.hibernate.validator.cfg.ConstraintMapping; import org.hibernate.validator.cfg.defs.SizeDef; +import org.hibernate.validator.testutil.TestForIssue; import org.hibernate.validator.testutil.ValidatorUtil; import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertCorrectConstraintViolationMessages; @@ -45,9 +46,7 @@ public class XmlMappingTest { @Test - /** - * HV-214 - */ + @TestForIssue(jiraKey = "HV-214") public void testConstraintInheritanceWithXmlConfiguration() { final Configuration configuration = ValidatorUtil.getConfiguration(); @@ -62,9 +61,7 @@ public void testConstraintInheritanceWithXmlConfiguration() { } @Test - /** - * HV-252 - */ + @TestForIssue(jiraKey = "HV-252") public void testListOfString() { final Configuration configuration = ValidatorUtil.getConfiguration(); @@ -86,9 +83,7 @@ public void testListOfString() { } @Test - /** - * HV-262 - */ + @TestForIssue(jiraKey = "HV-262") public void testInterfaceConfiguration() { final Configuration configuration = ValidatorUtil.getConfiguration(); @@ -102,9 +97,7 @@ public void testInterfaceConfiguration() { } @Test - /** - * HV-262 - */ + @TestForIssue(jiraKey = "HV-262") public void testInterfaceImplementationConfiguration() { final Configuration configuration = ValidatorUtil.getConfiguration(); @@ -118,9 +111,7 @@ public void testInterfaceImplementationConfiguration() { } @Test - /** - * HV-263 - */ + @TestForIssue(jiraKey = "HV-263") public void testEmptyInterfaceConfiguration() { final Configuration configuration = ValidatorUtil.getConfiguration(); @@ -133,10 +124,8 @@ public void testEmptyInterfaceConfiguration() { assertEquals( violations.size(), 0 ); } - /** - * HV-480 - */ @Test + @TestForIssue(jiraKey = "HV-480") public void testConstraintsFromXmlAndProgrammaticApiAddUp() { //given From 58beb5e9bb3f5e458c7291d7706d6f4511d48c49 Mon Sep 17 00:00:00 2001 From: Hardy Ferentschik Date: Fri, 23 Mar 2012 16:35:30 +0100 Subject: [PATCH 2/8] HV-563 don't reset configuration state so that the configuration can be reused --- .../hibernate/validator/internal/engine/ConfigurationImpl.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java b/hibernate-validator/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java index dd1fd6019f..2f8b204df4 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java @@ -201,8 +201,6 @@ public final ValidatorFactory buildValidatorFactory() { } } - // reset the param holder - validationBootstrapParameters = new ValidationBootstrapParameters(); return factory; } From f3fb9de3d890bbc619d3c067c3ba40a1718f6d56 Mon Sep 17 00:00:00 2001 From: Hardy Ferentschik Date: Fri, 23 Mar 2012 16:37:28 +0100 Subject: [PATCH 3/8] HV-563 XmlMappingParser tries now to reset the stream (if supported). This will allow to reuse the Configuration even if xml configuration is used. Also introducing CloseIgnoringInputStream which prevents that JAXB closes the input stream. This should be done by the client anyways. --- .../internal/xml/XmlMappingParser.java | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/internal/xml/XmlMappingParser.java b/hibernate-validator/src/main/java/org/hibernate/validator/internal/xml/XmlMappingParser.java index d21b04f0e7..58d01c4bfb 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/internal/xml/XmlMappingParser.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/internal/xml/XmlMappingParser.java @@ -16,6 +16,8 @@ */ package org.hibernate.validator.internal.xml; +import java.io.FilterInputStream; +import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.lang.annotation.Annotation; @@ -577,12 +579,27 @@ private ConstraintMappingsType getValidationConfig(InputStream in) { ConstraintMappingsType constraintMappings; Schema schema = getMappingSchema(); try { + // check whether mark is supported, if so we can reset the stream in order to allow reuse of Configuration + boolean markSupported = in.markSupported(); + if ( markSupported ) { + in.mark( Integer.MAX_VALUE ); + } + JAXBContext jc = JAXBContext.newInstance( ConstraintMappingsType.class ); Unmarshaller unmarshaller = jc.createUnmarshaller(); unmarshaller.setSchema( schema ); - StreamSource stream = new StreamSource( in ); + StreamSource stream = new StreamSource( new CloseIgnoringInputStream( in ) ); JAXBElement root = unmarshaller.unmarshal( stream, ConstraintMappingsType.class ); constraintMappings = root.getValue(); + + if ( markSupported ) { + try { + in.reset(); + } + catch ( IOException e ) { + log.debug( "Unable to reset input stream." ); + } + } } catch ( JAXBException e ) { throw log.getErrorParsingMappingFileException( e ); @@ -603,4 +620,16 @@ private Schema getMappingSchema() { } return schema; } + + // JAXB closes the underlying input stream + public class CloseIgnoringInputStream extends FilterInputStream { + public CloseIgnoringInputStream(InputStream in) { + super( in ); + } + + @Override + public void close() { + // do nothing + } + } } From fb846e28133759b0fb8bd2502a5180631c860949 Mon Sep 17 00:00:00 2001 From: Hardy Ferentschik Date: Fri, 23 Mar 2012 16:40:12 +0100 Subject: [PATCH 4/8] HV-563 tests --- .../engine/ConfigurationImplTest.java | 126 ++++++++++++++++++ .../test/internal/engine/mapping.xml | 8 ++ 2 files changed, 134 insertions(+) create mode 100644 hibernate-validator/src/test/java/org/hibernate/validator/test/internal/engine/ConfigurationImplTest.java create mode 100644 hibernate-validator/src/test/resources/org/hibernate/validator/test/internal/engine/mapping.xml diff --git a/hibernate-validator/src/test/java/org/hibernate/validator/test/internal/engine/ConfigurationImplTest.java b/hibernate-validator/src/test/java/org/hibernate/validator/test/internal/engine/ConfigurationImplTest.java new file mode 100644 index 0000000000..6cb0028c72 --- /dev/null +++ b/hibernate-validator/src/test/java/org/hibernate/validator/test/internal/engine/ConfigurationImplTest.java @@ -0,0 +1,126 @@ +/* +* JBoss, Home of Professional Open Source +* Copyright 2012, Red Hat, Inc. and/or its affiliates, and individual contributors +* by the @authors tag. See the copyright.txt in the distribution for a +* full listing of individual contributors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.hibernate.validator.test.internal.engine; + +import java.io.InputStream; +import java.lang.annotation.ElementType; +import javax.validation.Configuration; +import javax.validation.Path; +import javax.validation.TraversableResolver; +import javax.validation.ValidationException; +import javax.validation.ValidatorFactory; + +import org.testng.annotations.Test; + +import org.hibernate.validator.HibernateValidatorConfiguration; +import org.hibernate.validator.testutil.TestForIssue; + +import static org.hibernate.validator.testutil.ValidatorUtil.getConfiguration; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNotSame; +import static org.testng.Assert.assertTrue; + +/** + * @author Hardy Ferentschik + */ +public class ConfigurationImplTest { + + @Test + @TestForIssue(jiraKey = "HV-563") + public void testCallBuildValidatorFactoryMultipleTimes() { + final Configuration configuration = getConfiguration(); + + ValidatorFactory factory1 = configuration.buildValidatorFactory(); + assertNotNull( factory1 ); + + ValidatorFactory factory2 = configuration.buildValidatorFactory(); + assertNotNull( factory2 ); + + assertNotSame( factory1, factory2 ); + } + + @Test + @TestForIssue(jiraKey = "HV-563") + public void testConfigurationReusableAndMutable() { + final Configuration configuration = getConfiguration(); + + ValidatorFactory factory1 = configuration.buildValidatorFactory(); + assertNotNull( factory1 ); + + configuration.traversableResolver( new TestTraversableResolver() ); + ValidatorFactory factory2 = configuration.buildValidatorFactory(); + assertNotNull( factory2 ); + + assertNotSame( factory1.getTraversableResolver(), factory2.getTraversableResolver() ); + assertTrue( factory2.getTraversableResolver() instanceof TestTraversableResolver ); + } + + + @Test + @TestForIssue(jiraKey = "HV-563") + public void testReusableConfigurationWithInputStream() throws Exception { + final Configuration configuration = getConfiguration(); + + InputStream mappingStream = ConfigurationImplTest.class.getResourceAsStream( "mapping.xml" ); + + try { + configuration.addMapping( mappingStream ); + ValidatorFactory factory1 = configuration.buildValidatorFactory(); + assertNotNull( factory1 ); + + ValidatorFactory factory2 = configuration.buildValidatorFactory(); + assertNotNull( factory2 ); + + assertNotSame( factory1, factory2 ); + } + finally { + mappingStream.close(); + } + } + + @Test(expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "HV000115.*") + @TestForIssue(jiraKey = "HV-563") + public void testReusableConfigurationWithClosedInputStream() throws Exception { + final Configuration configuration = getConfiguration(); + + InputStream mappingStream = ConfigurationImplTest.class.getResourceAsStream( "mapping.xml" ); + + try { + configuration.addMapping( mappingStream ); + ValidatorFactory factory1 = configuration.buildValidatorFactory(); + assertNotNull( factory1 ); + } + finally { + mappingStream.close(); + } + + configuration.buildValidatorFactory(); + } + + public class TestTraversableResolver implements TraversableResolver { + + public boolean isReachable(Object traversableObject, Path.Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, ElementType elementType) { + return true; + } + + public boolean isCascadable(Object traversableObject, Path.Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, ElementType elementType) { + return true; + } + } +} + + diff --git a/hibernate-validator/src/test/resources/org/hibernate/validator/test/internal/engine/mapping.xml b/hibernate-validator/src/test/resources/org/hibernate/validator/test/internal/engine/mapping.xml new file mode 100644 index 0000000000..10a8443e4d --- /dev/null +++ b/hibernate-validator/src/test/resources/org/hibernate/validator/test/internal/engine/mapping.xml @@ -0,0 +1,8 @@ + + + org.hibernate.validator.test.internal.engine + \ No newline at end of file From c682ee866add7095180b04cd119e7394c779bd30 Mon Sep 17 00:00:00 2001 From: Hardy Ferentschik Date: Mon, 26 Mar 2012 18:33:20 +0200 Subject: [PATCH 5/8] HV-563 javadocs --- .../metadata/provider/XmlConfigurationMetaDataProvider.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlConfigurationMetaDataProvider.java b/hibernate-validator/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlConfigurationMetaDataProvider.java index bcb1d5a224..18f463123e 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlConfigurationMetaDataProvider.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlConfigurationMetaDataProvider.java @@ -52,7 +52,8 @@ public class XmlConfigurationMetaDataProvider extends MetaDataProviderImplBase { private final AnnotationIgnores annotationIgnores; /** - * @param mappingStreams + * @param constraintHelper the constraint helper utility + * @param mappingStreams the defined mapping streams */ public XmlConfigurationMetaDataProvider(ConstraintHelper constraintHelper, Set mappingStreams) { From daffddfdfab0ca269c1d5731150dc4697b452c80 Mon Sep 17 00:00:00 2001 From: Hardy Ferentschik Date: Mon, 26 Mar 2012 18:35:10 +0200 Subject: [PATCH 6/8] HV-563 Extending javadocs for Configuration#addMapping to explain that a buffered input stream needs to be passed in order to make the configuration reusable --- .../validator/internal/engine/ConfigurationImpl.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java b/hibernate-validator/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java index 2f8b204df4..9eb7f2fa49 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java @@ -135,6 +135,16 @@ public final ConfigurationImpl constraintValidatorFactory(ConstraintValidatorFac return this; } + /** + * {@inheritDoc} + * + * @param stream XML mapping stream. + *

+ * Note: In order to reuse the {@code ConfigurationInstance} to build multiple + * validator factories a {@link java.io.BufferedInputStream} has to be provided. + *

+ */ + public final HibernateValidatorConfiguration addMapping(InputStream stream) { Contracts.assertNotNull( stream, MESSAGES.parameterMustNotBeNull( "stream" ) ); From ae854e8bbd5adf5b877704c15c8f23ec84b2a6b7 Mon Sep 17 00:00:00 2001 From: Hardy Ferentschik Date: Tue, 27 Mar 2012 10:16:55 +0200 Subject: [PATCH 7/8] HV-563 Javadocs --- .../XmlConfigurationMetaDataProvider.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlConfigurationMetaDataProvider.java b/hibernate-validator/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlConfigurationMetaDataProvider.java index 18f463123e..bca0183748 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlConfigurationMetaDataProvider.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/internal/metadata/provider/XmlConfigurationMetaDataProvider.java @@ -46,6 +46,7 @@ * XML descriptors as defined by the Bean Validation API. * * @author Gunnar Morling + * @author Hardy Ferentschik */ public class XmlConfigurationMetaDataProvider extends MetaDataProviderImplBase { @@ -67,7 +68,7 @@ public XmlConfigurationMetaDataProvider(ConstraintHelper constraintHelper, Set>> constraintsByLocation = partition( mappingParser.getConstraintsForClass( clazz ), byLocation() ); - Set cascades = getCascades( mappingParser, clazz ); + Set cascades = getCascades( mappingParser, clazz ); Set constrainedElements = getConstrainedElements( constraintsByLocation, cascades ); @@ -86,7 +87,7 @@ public XmlConfigurationMetaDataProvider(ConstraintHelper constraintHelper, Set getConstrainedElements(Map>> constraintsByLocation, Set cascades) { + private Set getConstrainedElements(Map>> constraintsByLocation, Set cascades) { Set configuredLocations = new HashSet( cascades ); configuredLocations.addAll( constraintsByLocation.keySet() ); @@ -130,20 +131,20 @@ else if ( oneConfiguredLocation.getElementType() == ElementType.TYPE ) { } /** - * @param mappingParser - * @param clazz + * @param mappingParser the xml parser + * @param clazz the type for which to retrieve cascaded members * - * @return + * @return returns a set of cascaded constraints */ - private Set getCascades(XmlMappingParser mappingParser, Class clazz) { + private Set getCascades(XmlMappingParser mappingParser, Class clazz) { - Set theValue = newHashSet(); + Set cascadedConstraintSet = newHashSet(); for ( Member member : mappingParser.getCascadedMembersForClass( clazz ) ) { - theValue.add( new BeanConstraintLocation( member ) ); + cascadedConstraintSet.add( new BeanConstraintLocation( member ) ); } - return theValue; + return cascadedConstraintSet; } public AnnotationIgnores getAnnotationIgnores() { @@ -157,5 +158,4 @@ public ConstraintLocation getPartition(MetaConstraint constraint) { } }; } - } From 482d43dd855fb0d1aadee4c1775cec88a57abab0 Mon Sep 17 00:00:00 2001 From: Hardy Ferentschik Date: Tue, 27 Mar 2012 18:36:09 +0200 Subject: [PATCH 8/8] HV-563 Wrapping the provided stream into a BufferedInputStream in case that the stream does not support mark/reset --- .../validator/internal/engine/ConfigurationImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hibernate-validator/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java b/hibernate-validator/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java index 9eb7f2fa49..ec956b05cc 100644 --- a/hibernate-validator/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java +++ b/hibernate-validator/src/main/java/org/hibernate/validator/internal/engine/ConfigurationImpl.java @@ -16,6 +16,7 @@ */ package org.hibernate.validator.internal.engine; +import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; @@ -146,10 +147,9 @@ public final ConfigurationImpl constraintValidatorFactory(ConstraintValidatorFac */ public final HibernateValidatorConfiguration addMapping(InputStream stream) { - Contracts.assertNotNull( stream, MESSAGES.parameterMustNotBeNull( "stream" ) ); - validationBootstrapParameters.addMapping( stream ); + validationBootstrapParameters.addMapping( stream.markSupported() ? stream : new BufferedInputStream(stream) ); return this; }