From 5fdcbe1ec443ac604288b6cdcebb6414a1881651 Mon Sep 17 00:00:00 2001 From: Ben Alex Date: Tue, 19 Apr 2005 01:04:47 +0000 Subject: [PATCH] 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. --- .../ValidationRegistryManagerImpl.java | 162 +++++------------- 1 file changed, 39 insertions(+), 123 deletions(-) diff --git a/domain/src/main/java/org/acegisecurity/domain/validation/ValidationRegistryManagerImpl.java b/domain/src/main/java/org/acegisecurity/domain/validation/ValidationRegistryManagerImpl.java index be79745ea5..d639a020d6 100644 --- a/domain/src/main/java/org/acegisecurity/domain/validation/ValidationRegistryManagerImpl.java +++ b/domain/src/main/java/org/acegisecurity/domain/validation/ValidationRegistryManagerImpl.java @@ -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}. * *

- * Like PropertyEditorManager, - * this implementation uses three techniques for locating a - * Validator for a given domain object class: - * - *

    - *
  1. - * First, the {@link #registerValidator(Class, Class)} method allows a - * Validator to be expressly registered for a given domain object - * class. - *
  2. - *
  3. - * Second, an attempt will be made to find the Validator by - * concatenating "Validator" to the fully qualified domain object classname - * (eg "foo.bah.PersonValidator"). - *
  4. - *
  5. - * 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. - *
  6. - *
+ * Locates Validators registered in bean factory. *

* * @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 Validator. - * - *

- * By default, the AutowireCapableBeanFactory is used to build - * the instance, and autowire its bean properties. Specialised - * applications may wish to customise this behaviour, such as searching - * through the ApplicationContext for an existing singleton - * instance. This method is protected to enable such customisation. - *

- * - * @param clazz the represents the Validator instance required - * - * @return the requested Validator, fully wired with all - * dependencies, or null if the - * Validator 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); } }