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

org.testng.internal.ClassImpl Maven / Gradle / Ivy

There is a newer version: 7.10.2
Show newest version
package org.testng.internal;

import static org.testng.internal.Utils.isStringNotEmpty;

import com.google.inject.Injector;
import com.google.inject.Module;

import org.testng.IClass;
import org.testng.IModuleFactory;
import org.testng.ISuite;
import org.testng.ITest;
import org.testng.ITestContext;
import org.testng.ITestObjectFactory;
import org.testng.TestNGException;
import org.testng.annotations.Guice;
import org.testng.collections.Lists;
import org.testng.collections.Objects;
import org.testng.internal.annotations.AnnotationHelper;
import org.testng.internal.annotations.IAnnotationFinder;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlTest;

import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Map;

/**
 * Implementation of an IClass.
 *
 * @author Cedric Beust
 */
public class ClassImpl implements IClass {
  private static final long serialVersionUID = 1118178273317520344L;
  transient private Class m_class = null;
  transient private Object m_defaultInstance = null;
  private XmlTest m_xmlTest = null;
  transient private IAnnotationFinder m_annotationFinder = null;
  transient private List m_instances = Lists.newArrayList();
  transient private Map m_classes = null;
  private int m_instanceCount;
  private long[] m_instanceHashCodes;
  private transient Object m_instance;
  private ITestObjectFactory m_objectFactory;
  private String m_testName = null;
  private XmlClass m_xmlClass;
  private ITestContext m_testContext;
  private final boolean m_hasParentModule;

  public ClassImpl(ITestContext context, Class cls, XmlClass xmlClass, Object instance,
      Map classes, XmlTest xmlTest, IAnnotationFinder annotationFinder,
      ITestObjectFactory objectFactory) {
    m_testContext = context;
    m_class = cls;
    m_classes = classes;
    m_xmlClass = xmlClass;
    m_xmlTest = xmlTest;
    m_annotationFinder = annotationFinder;
    m_instance = instance;
    m_objectFactory = objectFactory;
    if (instance instanceof ITest) {
      m_testName = ((ITest) instance).getTestName();
    }
    m_hasParentModule = isStringNotEmpty(m_testContext.getSuite().getParentModule());
  }

  private static void ppp(String s) {
    System.out.println("[ClassImpl] " + s);
  }

  @Override
  public String getTestName() {
    return m_testName;
  }

  @Override
  public String getName() {
    return m_class.getName();
  }

  @Override
  public Class getRealClass() {
    return m_class;
  }

  @Override
  public int getInstanceCount() {
    return m_instanceCount;
  }

  @Override
  public long[] getInstanceHashCodes() {
    return m_instanceHashCodes;
  }

  @Override
  public XmlTest getXmlTest() {
    return m_xmlTest;
  }

  @Override
  public XmlClass getXmlClass() {
    return m_xmlClass;
  }

  private Object getDefaultInstance() {
    if (m_defaultInstance == null) {
      if (m_instance != null) {
        m_defaultInstance = m_instance;
      } else {
        Object instance = getInstanceFromGuice();

        if (instance != null) {
          m_defaultInstance = instance;
        } else {
          m_defaultInstance =
              ClassHelper.createInstance(m_class, m_classes, m_xmlTest,
                  m_annotationFinder, m_objectFactory);
        }
      }
    }

    return m_defaultInstance;
  }

  /**
   * @return an instance from Guice if @Test(guiceModule) attribute was found, null otherwise
   */
  @SuppressWarnings("unchecked")
  private Object getInstanceFromGuice() {
    Annotation annotation = AnnotationHelper.findAnnotationSuperClasses(Guice.class, m_class);
    if (annotation == null) return null;
    Injector parentInjector = getParentInjector();

    Guice guice = (Guice) annotation;
    List moduleInstances = Lists.newArrayList(getModules(guice, parentInjector, m_class));

    // Reuse the previous injector, if any
    Injector injector = m_testContext.getInjector(moduleInstances);
    if (injector == null) {
      injector = parentInjector.createChildInjector(moduleInstances);
      m_testContext.addInjector(moduleInstances, injector);
    }
    return injector.getInstance(m_class);
  }

  public Injector getParentInjector() {
    ISuite suite = m_testContext.getSuite();
    // Reuse the previous parent injector, if any
    Injector injector = suite.getParentInjector();
    if (injector == null) {
      if (m_hasParentModule) {
        Class parentModule = ClassHelper.forName(suite.getParentModule());
        if (parentModule == null) {
          throw new TestNGException("Cannot load parent Guice module class: " + parentModule);
        }
        Module module = (Module) ClassHelper.newInstance(parentModule);
        injector = com.google.inject.Guice.createInjector(module);
      } else {
        injector = com.google.inject.Guice.createInjector();
      }
      suite.setParentInjector(injector);
    }
    return injector;
  }

  private Module[] getModules(Guice guice, Injector parentInejctor, Class testClass) {
    List result = Lists.newArrayList();
    for (Class moduleClass : guice.modules()) {
      List modules = m_testContext.getGuiceModules(moduleClass);
      if (modules != null && modules.size() > 0) {
        result.addAll(modules);
      } else {
        Module instance = parentInejctor.getInstance(moduleClass);
        result.add(instance);
        m_testContext.addGuiceModule(moduleClass, instance);
      }
    }
    Class factory = guice.moduleFactory();
    if (factory != IModuleFactory.class) {
      IModuleFactory factoryInstance = parentInejctor.getInstance(factory);
      Module moduleClass = factoryInstance.createModule(m_testContext, testClass);
      if (moduleClass != null) {
        result.add(moduleClass);
      }
    }

    return result.toArray(new Module[result.size()]);
  }

  @Override
  public Object[] getInstances(boolean create) {
    Object[] result = {};

    if (m_xmlTest.isJUnit()) {
      if (create) {
        result = new Object[] { ClassHelper.createInstance(m_class, m_classes,
            m_xmlTest, m_annotationFinder, m_objectFactory) };
      }
    } else {
      result = new Object[] { getDefaultInstance() };
    }
    if (m_instances.size() > 0) {
      result = m_instances.toArray(new Object[m_instances.size()]);
    }

    m_instanceCount = m_instances.size();
    m_instanceHashCodes = new long[m_instanceCount];
    for (int i = 0; i < m_instanceCount; i++) {
      m_instanceHashCodes[i] = m_instances.get(i).hashCode();
    }
    return result;
  }

  @Override
  public String toString() {
    return Objects.toStringHelper(getClass())
        .add("class", m_class.getName())
        .toString();
  }

  @Override
  public void addInstance(Object instance) {
    m_instances.add(instance);
  }

}