package org.jibeframework.core.util;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jibeframework.core.annotation.UIComponent;
import org.jibeframework.core.annotation.UIController;
import org.jibeframework.core.app.Application;
import org.jibeframework.core.app.ApplicationInitializedListener;
import org.jibeframework.core.app.Reloadable;
import org.jibeframework.core.app.bootstrap.Bootstrapable;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ResourceUtils;
public class GroovyBeanFactory implements ApplicationInitializedListener, ApplicationContextAware, Reloadable,
Bootstrapable<String> {
public static final String BEAN_ID = "jibe.GroovyBeanFactory";
private List<String> groovyLocations = new ArrayList<String>();
private List<String> scripts = new ArrayList<String>();
private List<String> beans = new ArrayList<String>();
private static final Log log = LogFactory.getLog(GroovyBeanFactory.class);
private ApplicationContext applicationContext;
private static GroovyBeanFactory instance;
public void reloadIfRequired() {
if (Application.isInitialized()) {
loadBeans();
}
}
public void onApplicationInitialized() {
loadBeans();
}
public GroovyBeanFactory() {
super();
instance = this;
}
public static GroovyBeanFactory getInstance() {
return instance;
}
public List<String> getBeans() {
return beans;
}
private void loadBeans() {
for (String location : groovyLocations) {
try {
File root = ResourceUtils.getFile(location);
String p = root.getAbsolutePath();
String separator = System.getProperty("file.separator");
for (File f : listFiles(root, new ArrayList<File>())) {
String path = f.getAbsolutePath();
if (!scripts.contains(path)) {
String className = StringUtils.substringBeforeLast(StringUtils.substringAfter(path,
p + separator).replace(separator.charAt(0), '.'), ".");
Class<?> clazz = Class.forName(className);
UIComponent uiAnn = AnnotationUtils.findAnnotation(clazz, UIComponent.class);
if (uiAnn != null) {
String beanName = uiAnn.value();
scripts.add(f.getAbsolutePath());
registerBean(beanName, f, "conversation");
}
UIController cntAnn = AnnotationUtils.findAnnotation(clazz, UIController.class);
if (cntAnn != null) {
String beanName = cntAnn.value();
scripts.add(f.getAbsolutePath());
registerBean(beanName, f, "conversation");
}
}
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
private void registerBean(String beanName, File file, String scope) throws IOException {
log.info("Registering groovy bean:" + beanName);
beans.add(beanName);
DefaultListableBeanFactory fact = (DefaultListableBeanFactory) applicationContext
.getAutowireCapableBeanFactory();
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setBeanClassName("org.jibeframework.core.util.ViewComponentFactory");
bd.setScope(scope);
bd.setAutowireMode(GenericBeanDefinition.AUTOWIRE_NO);
bd.setDependencyCheck(AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
ConstructorArgumentValues cav = bd.getConstructorArgumentValues();
cav.addIndexedArgumentValue(0, file);
BeanDefinitionHolder holder = new BeanDefinitionHolder(bd, beanName, new String[] {});
BeanDefinitionReaderUtils.registerBeanDefinition(holder, fact);
}
public void bootstrap(String data) {
if (data.startsWith("file:")) {
groovyLocations.add(data);
} else {
groovyLocations.add(Application.getClasspathPrefix() + data);
}
}
private List<File> listFiles(File folder, List<File> files) {
for (File f : folder.listFiles()) {
if (f.isDirectory()) {
listFiles(f, files);
} else {
if (f.getName().endsWith(".groovy")) {
files.add(f);
}
}
}
return files;
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}