package cuke4duke.internal.jvmclass;
import cuke4duke.StepMother;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.StaticApplicationContext;
import java.util.ArrayList;
import java.util.List;
import java.lang.reflect.Modifier;
public class SpringFactory implements ObjectFactory {
private final List<Class<?>> classes = new ArrayList<Class<?>>();
private AbstractApplicationContext appContext;
private static ThreadLocal<StepMother> mother = new ThreadLocal<StepMother>();
public void createObjects() {
appContext.refresh();
}
public void disposeObjects() {
}
public boolean canHandle(Class<?> clazz) {
return true;
}
public void addClass(Class<?> clazz) {
classes.add(clazz);
}
public void addStepMother(StepMother instance) {
if (appContext == null) {
mother.set(instance);
StaticApplicationContext parent = new StaticApplicationContext();
parent.registerSingleton("stepMother", StepMotherFactory.class);
parent.refresh();
String springXml = System.getProperty("cuke4duke.springXml", "cucumber.xml");
appContext = new ClassPathXmlApplicationContext(new String[]{springXml}, parent);
if (mother.get() != null) {
throw new IllegalStateException("Expected ObjectMotherFactory to snatch up the thread local. Concurrent runs?");
}
}
}
@SuppressWarnings("unchecked")
public <T> T getComponent(Class<T> type) {
List beans = new ArrayList(appContext.getBeansOfType(type).values());
if (beans.size() == 1) {
return (T) beans.get(0);
} else {
throw new RuntimeException("Found " + beans.size() + " Beans for class " + type + ". Expected exactly 1.");
}
}
public List<Class<?>> getClasses() {
return classes;
}
static class StepMotherFactory implements FactoryBean, InitializingBean {
private StepMother mother;
public void afterPropertiesSet() throws Exception {
this.mother = SpringFactory.mother.get();
SpringFactory.mother.set(null);
}
public Object getObject() throws Exception {
return mother;
}
public Class<StepMother> getObjectType() {
return StepMother.class;
}
public boolean isSingleton() {
return true;
}
}
}