1336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beustpackage org.testng.internal.annotations;
2336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
3c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beustimport java.lang.annotation.Annotation;
4c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beustimport java.lang.reflect.Constructor;
5c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beustimport java.lang.reflect.Method;
6c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beustimport java.lang.reflect.Modifier;
7c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beustimport java.util.Map;
8c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beust
9336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beustimport org.testng.ITestNGMethod;
10c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beustimport org.testng.annotations.IAnnotation;
112d568355761a9632bf24a87984e241f8a079d724Cédric Beustimport org.testng.annotations.IConfigurationAnnotation;
122d568355761a9632bf24a87984e241f8a079d724Cédric Beustimport org.testng.annotations.IDataProviderAnnotation;
132d568355761a9632bf24a87984e241f8a079d724Cédric Beustimport org.testng.annotations.IExpectedExceptionsAnnotation;
142d568355761a9632bf24a87984e241f8a079d724Cédric Beustimport org.testng.annotations.IFactoryAnnotation;
152d568355761a9632bf24a87984e241f8a079d724Cédric Beustimport org.testng.annotations.IParametersAnnotation;
162d568355761a9632bf24a87984e241f8a079d724Cédric Beustimport org.testng.annotations.ITestAnnotation;
170f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beustimport org.testng.collections.Maps;
18336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beustimport org.testng.internal.TestNGMethod;
19336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beustimport org.testng.internal.Utils;
206bf0a7dfff25a8fecd8b57577d5f244ae5eb8003Cédric Beustimport org.testng.xml.XmlTest;
21336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
22336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust/**
23336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust * Helper methods to find @Test and @Configuration tags.  They minimize
24336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust * the amount of casting we need to do.
250f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin *
26336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust * Created on Dec 20, 2005
27336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust * @author cbeust
28336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust */
29336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beustpublic class AnnotationHelper {
30336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
31c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beust  public static ITestAnnotation findTest(IAnnotationFinder finder, Class<?> cls) {
325153b6767f7cafe0916e73eac9a6d31838e7592aVladislav Rassokhin    return finder.findAnnotation(cls, ITestAnnotation.class);
33336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
340f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
352d568355761a9632bf24a87984e241f8a079d724Cédric Beust  public static ITestAnnotation findTest(IAnnotationFinder finder, Method m) {
365153b6767f7cafe0916e73eac9a6d31838e7592aVladislav Rassokhin    return finder.findAnnotation(m, ITestAnnotation.class);
37336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
380f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
39e7eac6a771d8258a000d5f6e75145bbd48a128daJulien Herr  public static ITestAnnotation findTest(IAnnotationFinder finder, ITestNGMethod m) {
40e7eac6a771d8258a000d5f6e75145bbd48a128daJulien Herr    return finder.findAnnotation(m, ITestAnnotation.class);
41e7eac6a771d8258a000d5f6e75145bbd48a128daJulien Herr  }
42e7eac6a771d8258a000d5f6e75145bbd48a128daJulien Herr
432d568355761a9632bf24a87984e241f8a079d724Cédric Beust  public static IFactoryAnnotation findFactory(IAnnotationFinder finder, Method m) {
445153b6767f7cafe0916e73eac9a6d31838e7592aVladislav Rassokhin    return finder.findAnnotation(m, IFactoryAnnotation.class);
4591f466b758dee3e1ab412f836641761181531a9eCédric Beust  }
4691f466b758dee3e1ab412f836641761181531a9eCédric Beust
470e8453d55f6a2308f0b097b3ca0a43afb792f864Cédric Beust  public static IFactoryAnnotation findFactory(IAnnotationFinder finder, Constructor c) {
485153b6767f7cafe0916e73eac9a6d31838e7592aVladislav Rassokhin    return finder.findAnnotation(c, IFactoryAnnotation.class);
490e8453d55f6a2308f0b097b3ca0a43afb792f864Cédric Beust  }
500e8453d55f6a2308f0b097b3ca0a43afb792f864Cédric Beust
512d568355761a9632bf24a87984e241f8a079d724Cédric Beust  public static ITestAnnotation findTest(IAnnotationFinder finder, Constructor ctor) {
525153b6767f7cafe0916e73eac9a6d31838e7592aVladislav Rassokhin    return finder.findAnnotation(ctor, ITestAnnotation.class);
53336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
54336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
552d568355761a9632bf24a87984e241f8a079d724Cédric Beust  public static IConfigurationAnnotation findConfiguration(IAnnotationFinder finder, Constructor ctor) {
565153b6767f7cafe0916e73eac9a6d31838e7592aVladislav Rassokhin    IConfigurationAnnotation result = finder.findAnnotation(ctor, IConfigurationAnnotation.class);
57336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if (result == null) {
582d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation bs = (IConfigurationAnnotation) finder.findAnnotation(ctor, IBeforeSuite.class);
592d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation as = (IConfigurationAnnotation) finder.findAnnotation(ctor, IAfterSuite.class);
602d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation bt = (IConfigurationAnnotation) finder.findAnnotation(ctor, IBeforeTest.class);
612d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation at = (IConfigurationAnnotation) finder.findAnnotation(ctor, IAfterTest.class);
622d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation bg = (IConfigurationAnnotation) finder.findAnnotation(ctor, IBeforeGroups.class);
632d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation ag = (IConfigurationAnnotation) finder.findAnnotation(ctor, IAfterGroups.class);
642d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation bc = (IConfigurationAnnotation) finder.findAnnotation(ctor, IBeforeClass.class);
652d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation ac = (IConfigurationAnnotation) finder.findAnnotation(ctor, IAfterClass.class);
662d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation bm = (IConfigurationAnnotation) finder.findAnnotation(ctor, IBeforeMethod.class);
672d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation am = (IConfigurationAnnotation) finder.findAnnotation(ctor, IAfterMethod.class);
680f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
69336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      if (bs != null || as != null || bt != null || at != null || bg != null || ag != null
700f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin          || bc != null || ac != null || bm != null || am != null)
71336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      {
72336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        result = createConfiguration(bs, as, bt, at, bg, ag, bc, ac, bm, am);
730f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      }
74336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
750f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
76336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return result;
77336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
78336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
792d568355761a9632bf24a87984e241f8a079d724Cédric Beust  public static IConfigurationAnnotation findConfiguration(IAnnotationFinder finder, Method m) {
80c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beust    IConfigurationAnnotation result = finder.findAnnotation(m, IConfigurationAnnotation.class);
81336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if (result == null) {
822d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation bs = (IConfigurationAnnotation) finder.findAnnotation(m, IBeforeSuite.class);
832d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation as = (IConfigurationAnnotation) finder.findAnnotation(m, IAfterSuite.class);
842d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation bt = (IConfigurationAnnotation) finder.findAnnotation(m, IBeforeTest.class);
852d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation at = (IConfigurationAnnotation) finder.findAnnotation(m, IAfterTest.class);
862d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation bg = (IConfigurationAnnotation) finder.findAnnotation(m, IBeforeGroups.class);
872d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation ag = (IConfigurationAnnotation) finder.findAnnotation(m, IAfterGroups.class);
882d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation bc = (IConfigurationAnnotation) finder.findAnnotation(m, IBeforeClass.class);
892d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation ac = (IConfigurationAnnotation) finder.findAnnotation(m, IAfterClass.class);
902d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation bm = (IConfigurationAnnotation) finder.findAnnotation(m, IBeforeMethod.class);
912d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation am = (IConfigurationAnnotation) finder.findAnnotation(m, IAfterMethod.class);
920f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
93336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      if (bs != null || as != null || bt != null || at != null || bg != null || ag != null
940f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin          || bc != null || ac != null || bm != null || am != null)
95336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      {
96336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        result = createConfiguration(bs, as, bt, at, bg, ag, bc, ac, bm, am);
970f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      }
98336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
990f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
100336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return result;
101336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
1020f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
1030f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin  private static IConfigurationAnnotation createConfiguration(IConfigurationAnnotation bs, IConfigurationAnnotation as,
1040f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      IConfigurationAnnotation bt, IConfigurationAnnotation at, IConfigurationAnnotation bg, IConfigurationAnnotation ag,
1050f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      IConfigurationAnnotation bc, IConfigurationAnnotation ac, IConfigurationAnnotation bm, IConfigurationAnnotation am)
106336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  {
107336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    ConfigurationAnnotation result = new ConfigurationAnnotation();
1080f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
109336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if (bs != null) {
110336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      result.setBeforeSuite(true);
111336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      finishInitialize(result, bs);
112336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
113336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if (as != null) {
114336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      result.setAfterSuite(true);
115336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      finishInitialize(result, as);
116336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
117336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if (bt != null) {
118336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      result.setBeforeTest(true);
119336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      finishInitialize(result, bt);
120336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
121336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if (at != null) {
122336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      result.setAfterTest(true);
123336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      finishInitialize(result, at);
124336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
125336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if (bg != null) {
126336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      result.setBeforeGroups(bg.getBeforeGroups());
127336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      finishInitialize(result, bg);
128336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
129336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if (ag != null) {
130336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      result.setAfterGroups(ag.getAfterGroups());
131336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      finishInitialize(result, ag);
132336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
133336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if (bc != null) {
134336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      result.setBeforeTestClass(true);
135336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      finishInitialize(result, bc);
136336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
137336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if (ac != null) {
138336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      result.setAfterTestClass(true);
139336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      finishInitialize(result, ac);
140336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
141336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if (bm != null) {
142336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      result.setBeforeTestMethod(true);
143336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      finishInitialize(result, bm);
144336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
145336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if (am != null) {
146336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      result.setAfterTestMethod(true);
147336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      finishInitialize(result, am);
148336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
149336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
150336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return result;
151336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
1520f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
1536227fbd5182d211f7c1333ca253eee54fbf7c3b2the.mindstorm  @SuppressWarnings({"deprecation"})
1542d568355761a9632bf24a87984e241f8a079d724Cédric Beust  private static void finishInitialize(ConfigurationAnnotation result, IConfigurationAnnotation bs) {
155336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    result.setFakeConfiguration(true);
156336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    result.setAlwaysRun(bs.getAlwaysRun());
157336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    result.setDependsOnGroups(bs.getDependsOnGroups());
1580eba9d8976a74dd25eba41acc1fda02574b07199DanFabulich    result.setDependsOnMethods(bs.getDependsOnMethods());
159336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    result.setDescription(bs.getDescription());
160336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    result.setEnabled(bs.getEnabled());
161336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    result.setGroups(bs.getGroups());
162336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    result.setInheritGroups(bs.getInheritGroups());
163336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    result.setParameters(bs.getParameters());
164830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust    result.setTimeOut(bs.getTimeOut());
165336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
166336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
1676e714088ed5ccb46e3f204b5048c7527729e38cdTesto Nakada  private static final Class[] ALL_ANNOTATIONS = new Class[] {
1680f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    ITestAnnotation.class, IConfigurationAnnotation.class,
169dc1870ef024349e3374ed1fe8c28d756a13ca5b1the.mindstorm    IBeforeClass.class, IAfterClass.class,
170dc1870ef024349e3374ed1fe8c28d756a13ca5b1the.mindstorm    IBeforeMethod.class, IAfterMethod.class,
1710f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    IDataProviderAnnotation.class, IExpectedExceptionsAnnotation.class,
1720f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    IFactoryAnnotation.class, IParametersAnnotation.class,
173336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    IBeforeSuite.class, IAfterSuite.class,
174336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    IBeforeTest.class, IAfterTest.class,
175df7f78b6a19dcc515afbb928a22e0de6295eefadbileblog    IBeforeGroups.class, IAfterGroups.class
176336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  };
1770f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
1786e714088ed5ccb46e3f204b5048c7527729e38cdTesto Nakada  public static final Class[] CONFIGURATION_CLASSES = new Class[] {
1792d568355761a9632bf24a87984e241f8a079d724Cédric Beust    IConfigurationAnnotation.class,
1800f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    IBeforeSuite.class, IAfterSuite.class,
1810f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    IBeforeTest.class, IAfterTest.class,
1820f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    IBeforeGroups.class, IAfterGroups.class,
1830f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    IBeforeClass.class, IAfterClass.class,
184336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    IBeforeMethod.class, IAfterMethod.class
185336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  };
186336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
187336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  public static Class[] getAllAnnotations() {
188336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return ALL_ANNOTATIONS;
189df7f78b6a19dcc515afbb928a22e0de6295eefadbileblog  }
190df7f78b6a19dcc515afbb928a22e0de6295eefadbileblog
191336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  /**
192336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust   * Delegation method for creating the list of <CODE>ITestMethod</CODE>s to be
193336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust   * analysed.
194336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust   */
195c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beust  public static ITestNGMethod[] findMethodsWithAnnotation(Class<?> rootClass,
196c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beust      Class<? extends IAnnotation> annotationClass, IAnnotationFinder annotationFinder,
197c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beust      XmlTest xmlTest)
198336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  {
199336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    // Keep a map of the methods we saw so that we ignore a method in a superclass if it's
200336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    // already been seen in a child class
2010f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust    Map<String, ITestNGMethod> vResult = Maps.newHashMap();
2020f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
203336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    try {
2040f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust      vResult = Maps.newHashMap();
205336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust//    Class[] classes = rootClass.getTestClasses();
206c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beust      Class<?> cls = rootClass;
2070f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
208336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      //
209336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      // If the annotation is on the class or superclass, it applies to all public methods
210336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      // except methods marked with @Configuration
211336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      //
212336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
213336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      //
214336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      // Otherwise walk through all the methods and keep those
215336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      // that have the annotation
216336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      //
217c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beust//    for (Class<?> cls : classes) {
218336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        while (null != cls) {
219336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          boolean hasClassAnnotation = isAnnotationPresent(annotationFinder, cls, annotationClass);
220336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          Method[] methods = cls.getDeclaredMethods();
2210f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin          for (Method m : methods) {
222336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust            boolean hasMethodAnnotation = isAnnotationPresent(annotationFinder, m, annotationClass);
223336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust            boolean hasTestNGAnnotation =
2242d568355761a9632bf24a87984e241f8a079d724Cédric Beust              isAnnotationPresent(annotationFinder, m, IFactoryAnnotation.class) ||
2252d568355761a9632bf24a87984e241f8a079d724Cédric Beust              isAnnotationPresent(annotationFinder, m, ITestAnnotation.class) ||
226336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust              isAnnotationPresent(annotationFinder, m, CONFIGURATION_CLASSES);
227336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust            boolean isPublic = Modifier.isPublic(m.getModifiers());
2280e80cdf1facd9b83cabe2ad04db8c03adce362b9Valdis Rigdon            boolean isSynthetic = m.isSynthetic();
2290e80cdf1facd9b83cabe2ad04db8c03adce362b9Valdis Rigdon            if ((isPublic && hasClassAnnotation && !isSynthetic && (! hasTestNGAnnotation)) || hasMethodAnnotation) {
2300f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
231336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust              // Small hack to allow users to specify @Configuration classes even though
232336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust              // a class-level @Test annotation is present.  In this case, don't count
233336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust              // that method as a @Test
2342d568355761a9632bf24a87984e241f8a079d724Cédric Beust              if (isAnnotationPresent(annotationFinder, m, IConfigurationAnnotation.class) &&
2350f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin                  isAnnotationPresent(annotationFinder, cls, ITestAnnotation.class))
236336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust              {
237161d9860588ad89389848d70eb0a2f6f0cb46d1bCédric Beust                Utils.log("", 3, "Method " + m + " has a configuration annotation"
238161d9860588ad89389848d70eb0a2f6f0cb46d1bCédric Beust                    + " and a class-level @Test. This method will only be kept as a"
239161d9860588ad89389848d70eb0a2f6f0cb46d1bCédric Beust                    + " configuration method.");
2400f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
241336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust                continue;
242336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust              }
2430f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
24461e3a3733701551995e8330db1db52a53a185404Cédric Beust              // Skip the method if it has a return type
2455ccc31db8bf8ef85881f7ceaaa19dc7cfd3a32d8Cédric Beust              if (m.getReturnType() != void.class && ! xmlTest.getAllowReturnValues()) {
2465ccc31db8bf8ef85881f7ceaaa19dc7cfd3a32d8Cédric Beust                Utils.log("", 2, "Method " + m + " has a @Test annotation"
2475ccc31db8bf8ef85881f7ceaaa19dc7cfd3a32d8Cédric Beust                    + " but also a return value:"
2485ccc31db8bf8ef85881f7ceaaa19dc7cfd3a32d8Cédric Beust                    + " ignoring it. Use <suite allow-return-values=\"true\"> to fix this");
24961e3a3733701551995e8330db1db52a53a185404Cédric Beust                continue;
25061e3a3733701551995e8330db1db52a53a185404Cédric Beust              }
2510f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
252336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust              String key = createMethodKey(m);
253336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust              if (null == vResult.get(key)) {
2546bf0a7dfff25a8fecd8b57577d5f244ae5eb8003Cédric Beust                ITestNGMethod tm = new TestNGMethod(/* m.getDeclaringClass(), */ m,
255d2cb0ebdfecac643c380d1e84f273f5ba92374a4Cédric Beust                    annotationFinder, xmlTest, null); /* @@@ */
256336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust                vResult.put(key,tm);
257336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust              }
258336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust            }
259336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          } // for
260336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          // Now explore the superclass
261336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          cls = cls.getSuperclass();
262336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        } // while
263336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
264336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
265336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    catch (SecurityException e) {
266336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      e.printStackTrace();
267336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
268df7f78b6a19dcc515afbb928a22e0de6295eefadbileblog    ITestNGMethod[] result = vResult.values().toArray(new ITestNGMethod[vResult.size()]);
2690f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
270336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  //    for (Method m : result) {
271336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  //      ppp("   METHOD FOUND: " + m);
272336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  //    }
2730f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
274336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      return result;
275336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
276336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
277c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beust  public static Annotation findAnnotationSuperClasses(Class<?> annotationClass, Class c) {
278d001f3960f66312b94dcb7bae88c92158eb38a75Cédric Beust    while (c != null) {
279d001f3960f66312b94dcb7bae88c92158eb38a75Cédric Beust      Annotation result = c.getAnnotation(annotationClass);
280d001f3960f66312b94dcb7bae88c92158eb38a75Cédric Beust      if (result != null) return result;
281d001f3960f66312b94dcb7bae88c92158eb38a75Cédric Beust      else c = c.getSuperclass();
282d001f3960f66312b94dcb7bae88c92158eb38a75Cédric Beust    }
283d001f3960f66312b94dcb7bae88c92158eb38a75Cédric Beust    return null;
284d001f3960f66312b94dcb7bae88c92158eb38a75Cédric Beust  }
285d001f3960f66312b94dcb7bae88c92158eb38a75Cédric Beust
2860f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin  private static boolean isAnnotationPresent(IAnnotationFinder annotationFinder,
2870f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      Method m, Class[] annotationClasses)
288336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  {
289336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    for (Class a : annotationClasses) {
290336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      if (annotationFinder.findAnnotation(m, a) != null) {
291336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        return true;
292336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      }
293336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
2940f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
295336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return false;
296336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
297336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
298c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beust  private static boolean isAnnotationPresent(IAnnotationFinder annotationFinder, Method m,
299c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beust      Class<? extends IAnnotation> annotationClass) {
300336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return annotationFinder.findAnnotation(m, annotationClass) != null;
301336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
302336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
303c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beust  private static boolean isAnnotationPresent(IAnnotationFinder annotationFinder, Class<?> cls,
304c4c903b5a66381c5b2d1212d9f980e7131426ae4Cédric Beust      Class<? extends IAnnotation> annotationClass) {
305336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return annotationFinder.findAnnotation(cls, annotationClass) != null;
306336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
307336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
308336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  /**
309336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust   * @return A hashcode representing the name of this method and its parameters,
310336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust   * but without its class
311336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust   */
312336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private static String createMethodKey(Method m) {
313336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    StringBuffer result = new StringBuffer(m.getName());
314336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    for (Class paramClass : m.getParameterTypes()) {
315df7f78b6a19dcc515afbb928a22e0de6295eefadbileblog      result.append(' ').append(paramClass.toString());
316336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
3170f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
318336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return result.toString();
319336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
3200f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin
321336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust}
322