![JAR search and dependency download from the Maven repository](/logo.png)
org.hibernate.validator.ClassValidator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate-annotations
Show all versions of hibernate-annotations
Annotations metadata for Hibernate
//$Id: ClassValidator.java 10650 2006-10-25 01:18:29Z epbernard $
package org.hibernate.validator;
import java.beans.Introspector;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.StringTokenizer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.AssertionFailure;
import org.hibernate.Hibernate;
import org.hibernate.MappingException;
import org.hibernate.validator.interpolator.DefaultMessageInterpolatorAggerator;
import org.hibernate.cfg.annotations.Version;
import org.hibernate.cfg.BinderHelper;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.reflection.Filter;
import org.hibernate.reflection.ReflectionManager;
import org.hibernate.reflection.XClass;
import org.hibernate.reflection.XMember;
import org.hibernate.reflection.XMethod;
import org.hibernate.reflection.XProperty;
import org.hibernate.reflection.java.JavaXFactory;
import org.hibernate.util.IdentitySet;
/**
* Engine that take a bean and check every expressed annotation restrictions
*
* @author Gavin King
* @author Emmanuel Bernard
*/
public class ClassValidator implements Serializable {
//TODO Define magic number
private static Log log = LogFactory.getLog( ClassValidator.class );
private static final InvalidValue[] EMPTY_INVALID_VALUE_ARRAY = new InvalidValue[]{};
private static final String DEFAULT_VALIDATOR_MESSAGE = "org.hibernate.validator.resources.DefaultValidatorMessages";
private static final String VALIDATOR_MESSAGE = "ValidatorMessages";
private static final Set INDEXABLE_CLASS = new HashSet();
static {
INDEXABLE_CLASS.add( Integer.class );
INDEXABLE_CLASS.add( Long.class );
INDEXABLE_CLASS.add( String.class );
}
static {
Version.touch(); //touch version
}
private final Class beanClass;
private transient ResourceBundle messageBundle;
private transient ResourceBundle defaultMessageBundle;
private transient boolean isUserProvidedResourceBundle;
private transient ReflectionManager reflectionManager;
private final transient Map childClassValidators;
private transient List beanValidators;
private transient List memberValidators;
private transient List memberGetters;
private transient List childGetters;
private transient DefaultMessageInterpolatorAggerator defaultInterpolator;
private transient MessageInterpolator userInterpolator;
private static final Filter GET_ALL_FILTER = new Filter() {
public boolean returnStatic() {
return true;
}
public boolean returnTransient() {
return true;
}
};
/**
* create the validator engine for this bean type
*/
public ClassValidator(Class beanClass) {
this( beanClass, (ResourceBundle) null );
}
/**
* create the validator engine for a particular bean class, using a resource bundle
* for message rendering on violation
*/
public ClassValidator(Class beanClass, ResourceBundle resourceBundle) {
this( beanClass, resourceBundle, null, new HashMap(), null );
}
/**
* create the validator engine for a particular bean class, using a custom message interpolator
* for message rendering on violation
*/
public ClassValidator(Class beanClass, MessageInterpolator interpolator) {
this( beanClass, null, interpolator, new HashMap(), null );
}
/**
* Not a public API
*/
public ClassValidator(
Class beanClass, ResourceBundle resourceBundle, MessageInterpolator interpolator,
Map childClassValidators, ReflectionManager reflectionManager
) {
this.reflectionManager = reflectionManager != null ? reflectionManager : new JavaXFactory();
XClass beanXClass = this.reflectionManager.toXClass( beanClass );
this.beanClass = beanClass;
this.messageBundle = resourceBundle == null ?
getDefaultResourceBundle() :
resourceBundle;
this.defaultMessageBundle = ResourceBundle.getBundle( DEFAULT_VALIDATOR_MESSAGE );
this.userInterpolator = interpolator;
this.childClassValidators = childClassValidators != null ?
childClassValidators :
new HashMap();
initValidator( beanXClass, this.childClassValidators );
}
@SuppressWarnings("unchecked")
protected ClassValidator(
XClass beanXClass, ResourceBundle resourceBundle, MessageInterpolator userInterpolator,
Map childClassValidators, ReflectionManager reflectionManager
) {
this.beanClass = reflectionManager.toClass( beanXClass );
this.messageBundle = resourceBundle == null ?
getDefaultResourceBundle() :
resourceBundle;
this.defaultMessageBundle = ResourceBundle.getBundle( DEFAULT_VALIDATOR_MESSAGE );
this.userInterpolator = userInterpolator;
this.childClassValidators = childClassValidators;
initValidator( beanXClass, childClassValidators );
}
private ResourceBundle getDefaultResourceBundle() {
ResourceBundle rb;
try {
//use context class loader as a first citizen
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
if ( contextClassLoader == null ) {
throw new MissingResourceException( "No context classloader", null, VALIDATOR_MESSAGE );
}
rb = ResourceBundle.getBundle(
VALIDATOR_MESSAGE,
Locale.getDefault(),
contextClassLoader
);
}
catch (MissingResourceException e) {
log.trace( "ResourceBundle " + VALIDATOR_MESSAGE + " not found in thread context classloader" );
//then use the Validator Framework classloader
try {
rb = ResourceBundle.getBundle(
VALIDATOR_MESSAGE,
Locale.getDefault(),
this.getClass().getClassLoader()
);
}
catch (MissingResourceException ee) {
log.debug(
"ResourceBundle ValidatorMessages not found in Validator classloader. Delegate to " + DEFAULT_VALIDATOR_MESSAGE
);
//the user did not override the default ValidatorMessages
rb = null;
}
}
isUserProvidedResourceBundle = true;
return rb;
}
private void initValidator(
XClass xClass, Map childClassValidators
) {
beanValidators = new ArrayList();
memberValidators = new ArrayList();
memberGetters = new ArrayList();
childGetters = new ArrayList();
defaultInterpolator = new DefaultMessageInterpolatorAggerator();
defaultInterpolator.initialize( messageBundle, defaultMessageBundle );
//build the class hierarchy to look for members in
childClassValidators.put( xClass, this );
Collection classes = new HashSet();
addSuperClassesAndInterfaces( xClass, classes );
for ( XClass currentClass : classes ) {
Annotation[] classAnnotations = currentClass.getAnnotations();
for ( int i = 0; i < classAnnotations.length ; i++ ) {
Annotation classAnnotation = classAnnotations[i];
Validator beanValidator = createValidator( classAnnotation );
if ( beanValidator != null ) beanValidators.add( beanValidator );
}
}
//Check on all selected classes
for ( XClass currClass : classes ) {
List methods = currClass.getDeclaredMethods();
for ( XMethod method : methods ) {
createMemberValidator( method );
createChildValidator( method );
}
List fields = currClass.getDeclaredProperties(
"field", GET_ALL_FILTER
);
for ( XProperty field : fields ) {
createMemberValidator( field );
createChildValidator( field );
}
}
}
private void addSuperClassesAndInterfaces(XClass clazz, Collection classes) {
for ( XClass currClass = clazz; currClass != null ; currClass = currClass.getSuperclass() ) {
if ( ! classes.add( currClass ) ) return;
XClass[] interfaces = currClass.getInterfaces();
for ( XClass interf : interfaces ) {
addSuperClassesAndInterfaces( interf, classes );
}
}
}
@SuppressWarnings("unchecked")
private void createChildValidator( XMember member) {
if ( member.isAnnotationPresent( Valid.class ) ) {
setAccessible( member );
childGetters.add( member );
XClass clazz;
if ( member.isCollection() || member.isArray() ) {
clazz = member.getElementClass();
}
else {
clazz = member.getType();
}
if ( !childClassValidators.containsKey( clazz ) ) {
new ClassValidator( clazz, messageBundle, userInterpolator, childClassValidators, reflectionManager );
}
}
}
private void createMemberValidator(XMember member) {
boolean validatorPresent = false;
Annotation[] memberAnnotations = member.getAnnotations();
for ( int j = 0; j < memberAnnotations.length ; j++ ) {
Annotation methodAnnotation = memberAnnotations[j];
Validator propertyValidator = createValidator( methodAnnotation );
if ( propertyValidator != null ) {
memberValidators.add( propertyValidator );
setAccessible( member );
memberGetters.add( member );
validatorPresent = true;
}
}
if ( validatorPresent && !member.isTypeResolved() ) {
log.warn( "Original type of property " + member + " is unbound and has been approximated." );
}
}
private static void setAccessible(XMember member) {
if ( !Modifier.isPublic( member.getModifiers() ) ) {
member.setAccessible( true );
}
}
@SuppressWarnings("unchecked")
private Validator createValidator(Annotation annotation) {
try {
ValidatorClass validatorClass = annotation.annotationType().getAnnotation( ValidatorClass.class );
if ( validatorClass == null ) {
return null;
}
Validator beanValidator = validatorClass.value().newInstance();
beanValidator.initialize( annotation );
defaultInterpolator.addInterpolator( annotation, beanValidator );
return beanValidator;
}
catch (Exception e) {
throw new IllegalArgumentException( "could not instantiate ClassValidator", e );
}
}
public boolean hasValidationRules() {
return beanValidators.size() != 0 || memberValidators.size() != 0;
}
/**
* apply constraints on a bean instance and return all the failures.
* if bean
is null, an empty array is returned
*/
public InvalidValue[] getInvalidValues(T bean) {
return this.getInvalidValues( bean, new IdentitySet() );
}
/**
* apply constraints on a bean instance and return all the failures.
* if bean
is null, an empty array is returned
*/
@SuppressWarnings("unchecked")
protected InvalidValue[] getInvalidValues(T bean, Set
© 2015 - 2025 Weber Informatics LLC | Privacy Policy