atunit.spring.SpringContainer.java Source code

Java tutorial

Introduction

Here is the source code for atunit.spring.SpringContainer.java

Source

/**
 * Copyright (C) 2007 Logan Johnson
 *
 * 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 atunit.spring;

import java.lang.reflect.Field;
import java.net.URL;
import java.util.Map;

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 atunit.core.Container;

public class SpringContainer implements Container {

    public Object createTest(Class<?> testClass, Map<Field, Object> 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();

        Object test = testClass.newInstance();
        for (Field field : testClass.getDeclaredFields()) {
            field.setAccessible(true);
            Bean beanAnno = field.getAnnotation(Bean.class);
            if (beanAnno == null) {
                if (fieldValues.containsKey(field)) {
                    field.set(test, fieldValues.get(field));
                }
            } else {
                if (!beanAnno.value().equals("")) {
                    field.set(test, 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(test, ctx.getBean(beanNames[0]));
                }
            }
        }

        return test;
    }

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

    }
}