SpringStepsFactory.java

  1. package org.jbehave.core.steps.spring;

  2. import java.lang.reflect.Modifier;
  3. import java.util.ArrayList;
  4. import java.util.HashSet;
  5. import java.util.List;
  6. import java.util.Set;

  7. import org.jbehave.core.configuration.Configuration;
  8. import org.jbehave.core.steps.AbstractStepsFactory;
  9. import org.jbehave.core.steps.InjectableStepsFactory;
  10. import org.springframework.aop.framework.AopProxyUtils;
  11. import org.springframework.context.ApplicationContext;
  12. import org.springframework.util.ClassUtils;

  13. /**
  14.  * An {@link InjectableStepsFactory} that uses Spring's
  15.  * {@link ApplicationContext} for the composition and instantiation of all
  16.  * components that contain JBehave annotated methods.
  17.  *
  18.  * @author Paul Hammant
  19.  * @author Mauro Talevi
  20.  */
  21. public class SpringStepsFactory extends AbstractStepsFactory {

  22.     private final ApplicationContext context;

  23.     public SpringStepsFactory(Configuration configuration,
  24.             ApplicationContext context) {
  25.         super(configuration);
  26.         this.context = context;
  27.     }

  28.     @Override
  29.     protected List<Class<?>> stepsTypes() {
  30.         // Using set because in some cases (eg: scoped proxies),
  31.         // there may be two actual beans for each defined bean).
  32.         Set<Class<?>> types = new HashSet<>();
  33.         for (String name : context.getBeanDefinitionNames()) {
  34.             Class<?> type = beanType(name);
  35.             if (isAllowed(type) && hasAnnotatedMethods(type)) {
  36.                 types.add(type);
  37.             }
  38.         }
  39.         return new ArrayList<>(types);
  40.     }

  41.     /**
  42.      * Checks if type returned from context is allowed, i.e. not null and not
  43.      * abstract.
  44.      *
  45.      * @param type
  46.      *            the Class of the bean
  47.      * @return A boolean, <code>true</code> if allowed
  48.      */
  49.     protected boolean isAllowed(Class<?> type) {
  50.         return type != null && !Modifier.isAbstract(type.getModifiers());
  51.     }

  52.     @Override
  53.     public Object createInstanceOfType(Class<?> type) {
  54.         for (String name : context.getBeanDefinitionNames()) {
  55.             Class<?> beanType = beanType(name);
  56.             if (type.equals(beanType)) {
  57.                 return context.getBean(name);
  58.             }
  59.         }
  60.         throw new StepsInstanceNotFound(type, this);
  61.     }

  62.     /**
  63.      * Return the bean type, untangling the proxy if needed
  64.      *
  65.      * @param name
  66.      *            the bean name
  67.      * @return The Class of the bean
  68.      */
  69.     private Class<?> beanType(String name) {
  70.         Class<?> type = context.getType(name);
  71.         if (ClassUtils.isCglibProxyClass(type)) {
  72.             return AopProxyUtils.ultimateTargetClass(context.getBean(name));
  73.         }
  74.         return type;
  75.     }

  76. }