com.mycila.testing.plugin.atunit.container.SpringContainer Maven / Gradle / Ivy
/**
* Copyright (C) 2008 Mathieu Carbou
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mycila.testing.plugin.atunit.container;
import atunit.core.Container;
import atunit.spring.Bean;
import atunit.spring.Context;
import com.mycila.testing.core.Mycila;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.FactoryBean;
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.BeanDefinitionRegistry;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContextException;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.UrlResource;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Map;
public class SpringContainer implements Container {
public Object createTest(Class> testClass, Map fieldValues) throws Exception {
GenericApplicationContext ctx = new GenericApplicationContext();
for (Field field : fieldValues.keySet()) {
Bean beanAnno = field.getAnnotation(Bean.class);
AbstractBeanDefinition beandef = defineInstanceHolderFactoryBean(field.getType(), fieldValues.get(field));
if ((beanAnno != null) && !beanAnno.value().equals("")) {
ctx.registerBeanDefinition(beanAnno.value(), beandef);
} else {
BeanDefinitionReaderUtils.registerWithGeneratedName(beandef, ctx);
}
}
loadBeanDefinitions(testClass, ctx);
fillInMissingFieldBeans(testClass, ctx);
ctx.refresh();
for (Field field : testClass.getDeclaredFields()) {
field.setAccessible(true);
Bean beanAnno = field.getAnnotation(Bean.class);
if (beanAnno == null) {
if (fieldValues.containsKey(field)) {
field.set(Mycila.currentExecution().context().introspector().instance(), fieldValues.get(field));
}
} else {
if (!beanAnno.value().equals("")) {
field.set(Mycila.currentExecution().context().introspector().instance(), ctx.getBean(beanAnno.value()));
} else {
String[] beanNames = ctx.getBeanNamesForType(field.getType());
if (beanNames.length < 1) {
throw new BeanCreationException("There are no beans defined with type " + field.getType());
}
if (beanNames.length > 1) {
throw new BeanCreationException("There are " + beanNames.length + " beans defined with type " + field.getType()
+ "; consider wiring by name instead");
}
field.set(Mycila.currentExecution().context().introspector().instance(), ctx.getBean(beanNames[0]));
}
}
}
return null;
}
protected void loadBeanDefinitions(Class> testClass, BeanDefinitionRegistry registry) {
XmlBeanDefinitionReader xml = new XmlBeanDefinitionReader(registry);
String resourceName = testClass.getSimpleName() + ".xml";
Context ctxAnno = testClass.getAnnotation(Context.class);
if (ctxAnno != null) {
resourceName = ctxAnno.value();
}
URL xmlUrl = testClass.getResource(resourceName);
if (xmlUrl != null) {
xml.loadBeanDefinitions(new UrlResource(xmlUrl));
} else if (ctxAnno != null) {
// is this the appropriate exception here?
throw new ApplicationContextException("Could not find context file named " + resourceName);
}
}
protected void fillInMissingFieldBeans(Class> testClass, GenericApplicationContext ctx) throws Exception {
for (Field field : testClass.getDeclaredFields()) {
Bean beanAnno = field.getAnnotation(Bean.class);
if (beanAnno == null) continue;
String name = beanAnno.value();
if (!name.equals("") && !ctx.containsBean(name)) {
ctx.registerBeanDefinition(name, defineAutowireBean(field.getType()));
} else if (ctx.getBeansOfType(field.getType()).isEmpty()) {
BeanDefinitionReaderUtils.registerWithGeneratedName(defineAutowireBean(field.getType()), ctx);
}
}
}
protected AbstractBeanDefinition defineAutowireBean(Class> type) throws Exception {
AbstractBeanDefinition beandef = BeanDefinitionReaderUtils.createBeanDefinition(null, type.getName(), type.getClassLoader());
beandef.setAutowireCandidate(true);
beandef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_AUTODETECT);
return beandef;
}
protected AbstractBeanDefinition defineInstanceHolderFactoryBean(Class> type, Object instance) throws Exception {
ConstructorArgumentValues args = new ConstructorArgumentValues();
args.addIndexedArgumentValue(0, type);
args.addIndexedArgumentValue(1, instance);
AbstractBeanDefinition beandef = BeanDefinitionReaderUtils.createBeanDefinition(null, InstanceHolderFactoryBean.class.getName(), getClass().getClassLoader());
beandef.setConstructorArgumentValues(args);
beandef.setAutowireCandidate(true);
return beandef;
}
protected static class InstanceHolderFactoryBean implements FactoryBean {
final Class> type;
final Object instance;
public InstanceHolderFactoryBean(Class> type, Object instance) {
this.type = type;
this.instance = instance;
}
public Object getObject() throws Exception {
return instance;
}
public Class> getObjectType() {
return type;
}
public boolean isSingleton() {
return true;
}
}
}