All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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;
        }

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy