1package org.testng.internal; 2 3import java.lang.reflect.Modifier; 4import java.util.Iterator; 5import java.util.List; 6import java.util.Map; 7 8import org.testng.IInstanceInfo; 9import org.testng.ITestContext; 10import org.testng.ITestNGMethod; 11import org.testng.TestNGException; 12import org.testng.collections.Lists; 13import org.testng.collections.Maps; 14import org.testng.internal.annotations.IAnnotationFinder; 15import org.testng.xml.XmlTest; 16 17/** 18 * This class represents a method annotated with @Factory 19 * 20 * @author <a href="mailto:cedric@beust.com">Cedric Beust</a> 21 */ 22public class FactoryMethod extends BaseTestMethod { 23 /** 24 * 25 */ 26 private static final long serialVersionUID = -7329918821346197099L; 27 private Object m_instance = null; 28 private XmlTest m_xmlTest = null; 29 private ITestContext m_testContext = null; 30 31 public FactoryMethod(ConstructorOrMethod com, 32 Object instance, 33 XmlTest xmlTest, 34 IAnnotationFinder annotationFinder, 35 ITestContext testContext) 36 { 37 super(com.getName(), com, annotationFinder, instance); 38 Utils.checkInstanceOrStatic(instance, com.getMethod()); 39 Utils.checkReturnType(com.getMethod(), Object[].class, IInstanceInfo[].class); 40 Class<?> declaringClass = com.getDeclaringClass(); 41 if (instance != null && ! declaringClass.isAssignableFrom(instance.getClass())) { 42 throw new TestNGException("Mismatch between instance/method classes:" 43 + instance.getClass() + " " + declaringClass); 44 } 45 if (instance == null && com.getMethod() != null && !Modifier.isStatic(com.getMethod().getModifiers())) { 46 throw new TestNGException("An inner factory method MUST be static. But '" + com.getMethod().getName() + "' from '" + declaringClass.getName() + "' is not."); 47 } 48 if (com.getMethod() != null && !Modifier.isPublic(com.getMethod().getModifiers())) { 49 try { 50 com.getMethod().setAccessible(true); 51 } catch (SecurityException e) { 52 throw new TestNGException(e); 53 } 54 } 55 56 m_instance = instance; 57 m_xmlTest = xmlTest; 58 m_testContext = testContext; 59 NoOpTestClass tc = new NoOpTestClass(); 60 tc.setTestClass(declaringClass); 61 m_testClass = tc; 62 } 63 64 private static void ppp(String s) { 65 System.out.println("[FactoryMethod] " + s); 66 } 67 68 public Object[] invoke() { 69 List<Object> result = Lists.newArrayList(); 70 71 Map<String, String> allParameterNames = Maps.newHashMap(); 72 Iterator<Object[]> parameterIterator = 73 Parameters.handleParameters(this, 74 allParameterNames, 75 m_instance, 76 new Parameters.MethodParameters(m_xmlTest.getAllParameters(), 77 findMethodParameters(m_xmlTest), 78 null, null, m_testContext, 79 null /* testResult */), 80 m_xmlTest.getSuite(), 81 m_annotationFinder, 82 null /* fedInstance */).parameters; 83 84 try { 85 while (parameterIterator.hasNext()) { 86 Object[] parameters = parameterIterator.next(); 87 Object[] testInstances; 88 ConstructorOrMethod com = getConstructorOrMethod(); 89 if (com.getMethod() != null) { 90 testInstances = (Object[]) getMethod().invoke(m_instance, parameters); 91 for (Object testInstance : testInstances) { 92 result.add(testInstance); 93 } 94 } else { 95 Object instance = com.getConstructor().newInstance(parameters); 96 result.add(instance); 97 } 98 } 99 } 100 catch (Throwable t) { 101 ConstructorOrMethod com = getConstructorOrMethod(); 102 throw new TestNGException("The factory method " 103 + com.getDeclaringClass() + "." + com.getName() 104 + "() threw an exception", t); 105 } 106 107 return result.toArray(new Object[result.size()]); 108 } 109 110 @Override 111 public ITestNGMethod clone() { 112 throw new IllegalStateException("clone is not supported for FactoryMethod"); 113 } 114} 115