|
@@ -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);
|
|
|
}
|
|
|
}
|