package es.internna.spring.context;
import es.internna.spring.annotations.Bean;
import java.io.IOException;
import java.net.URL;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.Resource;
/**
*
* @author Jose Noheda
*/
public class AnnotatedBeanRegistry implements BeanFactoryPostProcessor, ApplicationContextAware {
private Log log = LogFactory.getLog(AnnotatedBeanRegistry.class);
private Set<String> includePath = null;
private ApplicationContext applicationContext = null;
public void setIncludePath(Set<String> includePath) {
this.includePath = includePath;
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
private String URLToClassname(final String packagedPattern, final URL fileURL) {
if ((fileURL == null) | (packagedPattern == null)) return null;
String fixedPackage = packagedPattern;
int indexOf = packagedPattern.indexOf("classpath*:");
if ( indexOf >= 0) fixedPackage = fixedPackage.substring(11);
indexOf = fixedPackage.indexOf("*");
if (indexOf >= 0) fixedPackage = fixedPackage.substring(0, indexOf);
String className = fileURL.getFile();
className = className.substring(className.indexOf(fixedPackage));
return className.substring(0, className.indexOf(".class")).replace("/", ".");
}
private Class loadClass(ClassLoader classLoader, String packagePattern, Resource resource) {
Class clazz = null;
try {
clazz = classLoader.loadClass(URLToClassname(packagePattern, resource.getURL()));
} catch (Exception ex) {
if (log.isWarnEnabled()) log.warn(ex.getMessage());
}
return clazz;
}
private void createAndRegisterBean(BeanDefinitionRegistry registry, Class clazz, Bean bean) {
RootBeanDefinition rbd = new RootBeanDefinition();
rbd.setAbstract(false);
rbd.setBeanClass(clazz);
rbd.setLazyInit(bean.lazy());
if (bean.initMethod().length() > 0) rbd.setInitMethodName(bean.initMethod());
if (bean.destroyMethod().length() > 0) rbd.setDestroyMethodName(bean.destroyMethod());
rbd.setAutowireCandidate(true);
rbd.setScope(bean.scope().getScopeName());
if (log.isInfoEnabled()) log.info("Registering.." + rbd);
registry.registerBeanDefinition(bean.name(), rbd);
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
if (BeanDefinitionRegistry.class.isInstance(configurableListableBeanFactory)) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) configurableListableBeanFactory;
if ((includePath != null) && (!includePath.isEmpty())) {
for (String packagePattern : includePath) {
try {
Resource[] resources = this.applicationContext.getResources(packagePattern);
for (Resource resource : resources) {
Class<?> clazz = loadClass(configurableListableBeanFactory.getBeanClassLoader(), packagePattern, resource);
if (log.isDebugEnabled()) log.debug("Scanned " + clazz.getName());
Bean bean = clazz.getAnnotation(Bean.class);
if (bean != null) {
if (log.isInfoEnabled()) log.info("Detected @Bean annotation in " + resource.getFilename());
createAndRegisterBean(registry, clazz, bean);
}
}
} catch (IOException ex) {
if (log.isErrorEnabled()) log.error("Error retrieving " + packagePattern + " resources");
}
}
} else {
log.info("No packages should be included. No @Bean annotations will be searched.");
}
} else {
if (log.isErrorEnabled()) {
log.error("AnnotatedBeanRegistry cannot process bean factories of this class: " + configurableListableBeanFactory.getClass().getSimpleName());
log.error("@Bean annotations will not be parsed.");
}
}
}
}