Package com.mycila.testing.plugin.atunit.container

Source Code of com.mycila.testing.plugin.atunit.container.SpringContainer$InstanceHolderFactoryBean

/**
* Copyright (C) 2008 Mathieu Carbou <mathieu.carbou@gmail.com>
*
* 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.ContextHolder;
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<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();

    for ( Field field : testClass.getDeclaredFields() ) {
      field.setAccessible(true);
      Bean beanAnno = field.getAnnotation(Bean.class);
      if ( beanAnno == null ) {
        if ( fieldValues.containsKey(field) ) {
          field.set(ContextHolder.get().getTest().getTarget(), fieldValues.get(field));
        }
      } else {
        if ( ! beanAnno.value().equals("") ) {
          field.set(ContextHolder.get().getTest().getTarget(), 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(ContextHolder.get().getTest().getTarget(), 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;
    }

  }
}
TOP

Related Classes of com.mycila.testing.plugin.atunit.container.SpringContainer$InstanceHolderFactoryBean

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.