Refactor to use the application context as the source of Validators. This is appropriate as manual control over Validator instance creation and wiring is often necessary (not autowiring). This is particularly the case when dealing with DefaultAdvisorAutoProxyCreator, which excludes collaborating beans from being advice candidates.

This commit is contained in:
Ben Alex 2005-04-19 01:04:47 +00:00
parent 018f625e85
commit 5fdcbe1ec4
1 changed files with 39 additions and 123 deletions

View File

@ -15,46 +15,24 @@
package net.sf.acegisecurity.domain.validation;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.validation.Validator;
import java.util.HashMap;
import java.util.Map;
/**
* A basic implementation of {@link ValidationRegistryManager}.
*
* <p>
* Like <a
* href="http://java.sun.com/j2se/1.4.2/docs/api/java/beans/PropertyEditorManager.html">PropertyEditorManager</a>,
* this implementation uses three techniques for locating a
* <code>Validator</code> for a given domain object class:
*
* <ol>
* <li>
* First, the {@link #registerValidator(Class, Class)} method allows a
* <code>Validator</code> to be expressly registered for a given domain object
* class.
* </li>
* <li>
* Second, an attempt will be made to find the <code>Validator</code> by
* concatenating "Validator" to the fully qualified domain object classname
* (eg "foo.bah.PersonValidator").
* </li>
* <li>
* Third, it takes the domain object's simple classname (without the package
* name), adds "Validator" to it, then looks in the {@link
* #validatorSearchPath} for the validator.
* </li>
* </ol>
* Locates <code>Validator</code>s registered in bean factory.
* </p>
*
* @author Matthew E. Porter
@ -65,115 +43,53 @@ public class ValidationRegistryManagerImpl implements ValidationRegistryManager,
BeanFactoryAware {
//~ Static fields/initializers =============================================
private static final String VALIDATOR_SUFFIX = "Validator";
//~ Instance fields ========================================================
private AutowireCapableBeanFactory acbf;
private ListableBeanFactory bf;
private Map validatorMap = new HashMap();
private String[] validatorSearchPath;
//~ Methods ================================================================
public void setBeanFactory(BeanFactory beanFactory)
throws BeansException {
Assert.isInstanceOf(AutowireCapableBeanFactory.class, beanFactory,
"BeanFactory must be AutowireCapableBeanFactory");
this.acbf = (AutowireCapableBeanFactory) beanFactory;
}
public void setValidatorSearchPath(String[] validatorSearchPath) {
this.validatorSearchPath = validatorSearchPath;
}
public String[] getValidatorSearchPath() {
return validatorSearchPath;
Assert.isInstanceOf(ListableBeanFactory.class, beanFactory,
"BeanFactory must be ListableBeanFactory");
this.bf = (ListableBeanFactory) beanFactory;
}
public Validator findValidator(Class domainClass) {
Assert.notNull(domainClass, "domainClass cannot be null");
Class validatorClass = null;
Validator validator = null;
if (validatorMap.containsKey(domainClass)) {
// already known to our Map
validatorClass = (Class) validatorMap.get(domainClass);
} else {
validatorClass = this.findValidatorClass(domainClass.getName()
+ VALIDATOR_SUFFIX);
if (validatorClass == null) {
String suffix = "." + ClassUtils.getShortName(domainClass)
+ VALIDATOR_SUFFIX;
if (validatorSearchPath != null) {
for (int i = 0;
(i < validatorSearchPath.length)
&& (validatorClass == null); i++) {
validatorClass = this.findValidatorClass(validatorSearchPath[i]
+ suffix);
}
}
}
// if we found a Validator, register it so we speed up future retrieval
if (validatorClass != null) {
this.registerValidator(domainClass, validatorClass);
}
}
// Attempt to create an instance of the Validator
if (validatorClass != null) {
validator = obtainWiredValidator(validatorClass);
}
return validator;
if (validatorMap.containsKey(domainClass)) {
if (validatorMap.get(domainClass) == null) {
return null;
}
return (Validator) this.bf.getBean((String)validatorMap.get(domainClass), Validator.class);
}
// Attempt to find Validator via introspection
Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(bf, Validator.class, true, true);
Iterator iter = beans.keySet().iterator();
while (iter.hasNext()) {
String beanName = (String) iter.next();
Validator validator = (Validator) beans.get(beanName);
if (validator.supports(domainClass)) {
this.validatorMap.put(domainClass, beanName);
return validator;
}
}
// No Validator found
this.validatorMap.put(domainClass, null);
return null;
}
public void registerValidator(Class domainClass, Class validatorClass) {
public void registerValidator(Class domainClass, String beanName) {
Assert.notNull(domainClass, "domainClass cannot be null");
Assert.notNull(validatorClass, "validatorClass cannot be null");
Assert.isTrue(Validator.class.isAssignableFrom(validatorClass),
"validatorClass must be an implementation of Validator");
this.validatorMap.put(domainClass, validatorClass);
}
/**
* Builds a new instance of the <code>Validator</code>.
*
* <p>
* By default, the <code>AutowireCapableBeanFactory</code> is used to build
* the instance, and autowire its bean properties. Specialised
* applications may wish to customise this behaviour, such as searching
* through the <code>ApplicationContext</code> for an existing singleton
* instance. This method is protected to enable such customisation.
* </p>
*
* @param clazz the represents the <code>Validator</code> instance required
*
* @return the requested <code>Validator</code>, fully wired with all
* dependencies, or <code>null</code> if the
* <code>Validator</code> could not be found or created
*/
protected Validator obtainWiredValidator(Class clazz) {
try {
return (Validator) this.acbf.autowire(clazz,
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
} catch (BeansException autowireFailure) {
return null;
}
}
private Class findValidatorClass(String validatorClassName) {
Class validatorClass = null;
try {
ClassLoader contextClassLoader = Thread.currentThread()
.getContextClassLoader();
validatorClass = Class.forName(validatorClassName);
} catch (ClassNotFoundException e) {}
return validatorClass;
Assert.notNull(beanName, "beanName cannot be null");
Assert.isTrue(this.bf.containsBean(beanName), "beanName not found in context");
Assert.isInstanceOf(Validator.class, this.bf.getBean(beanName), "beanName '" + beanName + "' must be a Validator");
Assert.isTrue(((Validator)this.bf.getBean(beanName)).supports(domainClass), "Validator does not support " + domainClass);
this.validatorMap.put(domainClass, beanName);
}
}