Author: hardy.ferentschik
Date: 2010-05-21 06:31:30 -0400 (Fri, 21 May 2010)
New Revision: 19581
Added:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validator/util/privilegedactions/package.html
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validator/engine/ValidatorFactoryImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validator/util/ReflectionHelper.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java
Log:
HV-274 made sure inherited constraints configured via api get picked up
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validator/engine/ValidatorFactoryImpl.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validator/engine/ValidatorFactoryImpl.java 2010-05-21
06:56:48 UTC (rev 19580)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validator/engine/ValidatorFactoryImpl.java 2010-05-21
10:31:30 UTC (rev 19581)
@@ -49,7 +49,7 @@
import org.hibernate.validator.xml.XmlMappingParser;
/**
- * Factory returning initialized <code>Validator</code> instances. This is
Hibernate Validator's default
+ * Factory returning initialized {@code Validator} instances. This is Hibernate
Validator's default
* implementation of the {@code ValidatorFactory} interface.
*
* @author Emmanuel Bernard
@@ -125,54 +125,38 @@
*/
private <A extends Annotation, T> void
initProgrammaticConfiguration(ConstraintMapping mapping) {
Map<Class<?>, List<ConstraintDefinition<?>>> configData =
mapping.getConfigData();
- for ( Map.Entry<Class<?>, List<ConstraintDefinition<?>>> entry
: configData.entrySet() ) {
- Map<Class<?>, List<MetaConstraint<T, ?>>> constraints = new
HashMap<Class<?>, List<MetaConstraint<T, ?>>>();
- for ( ConstraintDefinition<?> config : entry.getValue() ) {
- AnnotationDescriptor<A> annotationDescriptor = new
AnnotationDescriptor<A>(
- ( Class<A> ) config.getConstraintType()
- );
- for ( Map.Entry<String, Object> parameter : config.getParameters().entrySet() )
{
- annotationDescriptor.setValue( parameter.getKey(), parameter.getValue() );
- }
- A annotation;
- try {
- annotation = AnnotationFactory.create( annotationDescriptor );
- }
- catch ( RuntimeException e ) {
- throw new ValidationException(
- "Unable to create annotation for configured constraint: " +
e.getMessage(), e
- );
- }
+ for ( Class<?> clazz : mapping.getConfigData().keySet() ) {
+ @SuppressWarnings("unchecked")
+ Class<T> beanClass = ( Class<T> ) clazz;
- ConstraintDescriptorImpl<A> constraintDescriptor = new
ConstraintDescriptorImpl<A>(
- annotation, constraintHelper, config.getElementType(),
ConstraintOrigin.DEFINED_LOCALLY
- );
+ // for each configured entity we have to check whether any of the interfaces or super
classes is configured
+ // vua the programmatic api as well
+ List<Class<?>> classes = ReflectionHelper.computeClassHierarchy( beanClass
);
- final Member member = ReflectionHelper.getMember(
- config.getBeanType(), config.getProperty(), config.getElementType()
- );
+ Map<Class<?>, List<MetaConstraint<T, ?>>> constraints =
createEmptyConstraintMap();
+ List<Member> cascadedMembers = new ArrayList<Member>();
- MetaConstraint<T, ?> metaConstraint = new MetaConstraint(
- config.getBeanType(), member, constraintDescriptor
- );
- List<MetaConstraint<T, ?>> constraintList = new
ArrayList<MetaConstraint<T, ?>>();
- constraintList.add( metaConstraint );
- constraints.put( config.getBeanType(), constraintList );
+ for ( Class<?> classInHierarchy : classes ) {
+ // if the programmatic config contains constraints for the class in the hierarchy
create a meta constraint
+ if ( mapping.getConfigData().keySet().contains( classInHierarchy ) ) {
+ addProgrammaticConfiguredConstraints(
+ mapping.getConfigData().get( classInHierarchy ), beanClass, classInHierarchy,
constraints
+ );
+ }
+ }
+ BeanMetaDataImpl<T> metaData = new BeanMetaDataImpl<T>(
+ beanClass,
+ constraintHelper,
+ new ArrayList<Class<?>>(),
+ constraints,
+ new ArrayList<Member>(),
+ new AnnotationIgnores(),
+ beanMetaDataCache
+ );
- BeanMetaDataImpl<T> metaData = new BeanMetaDataImpl<T>(
- ( Class<T> ) config.getBeanType(),
- constraintHelper,
- new ArrayList<Class<?>>(),
- constraints,
- new ArrayList<Member>(),
- new AnnotationIgnores(),
- beanMetaDataCache
- );
-
- beanMetaDataCache.addBeanMetaData( ( Class<T> ) config.getBeanType(), metaData
);
- }
+ beanMetaDataCache.addBeanMetaData( beanClass, metaData );
}
}
@@ -188,7 +172,7 @@
Class<T> beanClass = ( Class<T> ) clazz;
List<Class<?>> classes = ReflectionHelper.computeClassHierarchy( beanClass
);
- Map<Class<?>, List<MetaConstraint<T, ?>>> constraints = new
HashMap<Class<?>, List<MetaConstraint<T, ?>>>();
+ Map<Class<?>, List<MetaConstraint<T, ?>>> constraints =
createEmptyConstraintMap();
List<Member> cascadedMembers = new ArrayList<Member>();
// we need to collect all constraints which apply for a single class. Due to
constraint inheritance
// some constraints might be configured in super classes or interfaces. The xml
configuration does not
@@ -216,7 +200,9 @@
}
@SuppressWarnings("unchecked")
- private <T, A extends Annotation> void
addXmlConfiguredConstraints(XmlMappingParser mappingParser, Class<T> rootClass,
Class<?> hierarchyClass, Map<Class<?>, List<MetaConstraint<T,
?>>> constraints) {
+ private <T, A extends Annotation> void
addXmlConfiguredConstraints(XmlMappingParser mappingParser,
+ Class<T> rootClass,
+ Class<?> hierarchyClass, Map<Class<?>,
List<MetaConstraint<T, ?>>> constraints) {
for ( MetaConstraint<?, ? extends Annotation> constraint :
mappingParser.getConstraintsForClass( hierarchyClass ) ) {
ConstraintOrigin definedIn = definedIn( rootClass, hierarchyClass );
ConstraintDescriptorImpl<A> descriptor = new ConstraintDescriptorImpl<A>(
@@ -228,21 +214,60 @@
MetaConstraint<T, A> newMetaConstraint = new MetaConstraint<T, A>(
rootClass, constraint.getMember(), descriptor
);
- List<MetaConstraint<T, ?>> constraintList = constraints.get(
hierarchyClass );
- if ( constraintList == null ) {
- constraintList = new ArrayList<MetaConstraint<T, ?>>();
- constraints.put( hierarchyClass, constraintList );
- }
- constraintList.add( newMetaConstraint );
+
+ addConstraintToMap( hierarchyClass, newMetaConstraint, constraints );
}
}
- private void addXmlCascadedMember(XmlMappingParser mappingParser, Class<?>
hierarchyClass, List<Member> cascadedMembers) {
+ @SuppressWarnings("unchecked")
+ private <T, A extends Annotation> void
addProgrammaticConfiguredConstraints(List<ConstraintDefinition<?>>
definitions,
+ Class<T> rootClass, Class<?> hierarchyClass,
+ Map<Class<?>, List<MetaConstraint<T, ?>>>
constraints) {
+ for ( ConstraintDefinition<?> config : definitions ) {
+ A annotation = (A) createAnnotationProxy( config );
+ ConstraintOrigin definedIn = definedIn( rootClass, hierarchyClass );
+ ConstraintDescriptorImpl<A> constraintDescriptor = new
ConstraintDescriptorImpl<A>(
+ annotation, constraintHelper, config.getElementType(), definedIn
+ );
+
+ Member member = ReflectionHelper.getMember(
+ config.getBeanType(), config.getProperty(), config.getElementType()
+ );
+
+ MetaConstraint<T, ?> metaConstraint = new MetaConstraint(
+ config.getBeanType(), member, constraintDescriptor
+ );
+ addConstraintToMap( hierarchyClass, metaConstraint, constraints );
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T, A extends Annotation> void addConstraintToMap(Class<?>
hierarchyClass,
+ MetaConstraint<T, A> constraint,
+ Map<Class<?>, List<MetaConstraint<T, ?>>>
constraints) {
+ List<MetaConstraint<T, ?>> constraintList = constraints.get( hierarchyClass
);
+ if ( constraintList == null ) {
+ constraintList = new ArrayList<MetaConstraint<T, ?>>();
+ constraints.put( hierarchyClass, constraintList );
+ }
+ constraintList.add( constraint );
+ }
+
+ private void addXmlCascadedMember(XmlMappingParser mappingParser,
+ Class<?> hierarchyClass,
+ List<Member> cascadedMembers) {
for ( Member m : mappingParser.getCascadedMembersForClass( hierarchyClass ) ) {
cascadedMembers.add( m );
}
}
+ /**
+ * @param rootClass The root class. That is the class for which we currently create a
{@code BeanMetaData}
+ * @param hierarchyClass The class on which the current constraint is defined on
+ *
+ * @return Returns {@code ConstraintOrigin.DEFINED_LOCALLY} if the constraint was
defined on the root bean,
+ * {@code ConstraintOrigin.DEFINED_IN_HIERARCHY} otherwise.
+ */
private ConstraintOrigin definedIn(Class<?> rootClass, Class<?>
hierarchyClass) {
if ( hierarchyClass.equals( rootClass ) ) {
return ConstraintOrigin.DEFINED_LOCALLY;
@@ -251,4 +276,28 @@
return ConstraintOrigin.DEFINED_IN_HIERARCHY;
}
}
+
+ @SuppressWarnings("unchecked")
+ private <A extends Annotation> Annotation
createAnnotationProxy(ConstraintDefinition<?> config) {
+ Class<A> constraintType = (Class<A>) config.getConstraintType();
+ AnnotationDescriptor<A> annotationDescriptor = new AnnotationDescriptor<A>(
constraintType );
+ for ( Map.Entry<String, Object> parameter : config.getParameters().entrySet() )
{
+ annotationDescriptor.setValue( parameter.getKey(), parameter.getValue() );
+ }
+
+ A annotation;
+ try {
+ annotation = AnnotationFactory.create( annotationDescriptor );
+ }
+ catch ( RuntimeException e ) {
+ throw new ValidationException(
+ "Unable to create annotation for configured constraint: " +
e.getMessage(), e
+ );
+ }
+ return annotation;
+ }
+
+ private <T> Map<Class<?>, List<MetaConstraint<T, ?>>>
createEmptyConstraintMap() {
+ return new HashMap<Class<?>, List<MetaConstraint<T, ?>>>();
+ }
}
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validator/util/ReflectionHelper.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validator/util/ReflectionHelper.java 2010-05-21
06:56:48 UTC (rev 19580)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validator/util/ReflectionHelper.java 2010-05-21
10:31:30 UTC (rev 19581)
@@ -650,7 +650,8 @@
*
* @param clazz The class to start the search with.
*
- * @return List of all super classes and interfaces of {@code clazz}.
+ * @return List of all super classes and interfaces of {@code clazz}. The list contains
the class itself! The empty
+ * list is returned if {@code clazz} is {@code null}.
*/
public static List<Class<?>> computeClassHierarchy(Class<?> clazz) {
List<Class<?>> classes = new ArrayList<Class<?>>();
Copied:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validator/util/privilegedactions/package.html
(from rev 19558,
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validator/util/package.html)
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validator/util/privilegedactions/package.html
(rev 0)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validator/util/privilegedactions/package.html 2010-05-21
10:31:30 UTC (rev 19581)
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+ <!--
+
+ JBoss, Home of Professional Open Source
+ Copyright 2010, 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.
+
+-->
+</head>
+<body>
+Implementations of {@code PrivilegedAction} in order to execute reflection operations in
a security manager.
+</body>
+</html>
Modified:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java
===================================================================
---
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java 2010-05-21
06:56:48 UTC (rev 19580)
+++
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validator/test/cfg/ConstraintMappingTest.java 2010-05-21
10:31:30 UTC (rev 19581)
@@ -92,7 +92,7 @@
assertConstraintViolation( violations.iterator().next(), "may not be null"
);
}
- @Test(enabled = false)
+ @Test
public void testInheritedConstraint() {
HibernateValidatorConfiguration config = TestUtil.getConfiguration(
HibernateValidator.class );
@@ -117,7 +117,7 @@
Set<ConstraintViolation<Marathon>> violations = validator.validate(
marathon );
assertNumberOfViolations( violations, 1 );
- assertConstraintViolation( violations.iterator().next(), "may not be null"
);
+ assertConstraintViolation( violations.iterator().next(), "must be in the
future" );
}
@Test