Home | History | Annotate | Download | only in annotations
      1 package org.testng.internal.annotations;
      2 
      3 import java.lang.annotation.Annotation;
      4 import java.lang.reflect.Method;
      5 import java.util.HashSet;
      6 import java.util.List;
      7 import java.util.Set;
      8 
      9 import org.testng.IAnnotationTransformer;
     10 import org.testng.TestNGException;
     11 import org.testng.annotations.AfterClass;
     12 import org.testng.annotations.AfterGroups;
     13 import org.testng.annotations.AfterMethod;
     14 import org.testng.annotations.AfterSuite;
     15 import org.testng.annotations.AfterTest;
     16 import org.testng.annotations.BeforeClass;
     17 import org.testng.annotations.BeforeGroups;
     18 import org.testng.annotations.BeforeMethod;
     19 import org.testng.annotations.BeforeSuite;
     20 import org.testng.annotations.BeforeTest;
     21 import org.testng.annotations.Configuration;
     22 import org.testng.annotations.DataProvider;
     23 import org.testng.annotations.ExpectedExceptions;
     24 import org.testng.annotations.Factory;
     25 import org.testng.annotations.IAnnotation;
     26 import org.testng.annotations.IConfigurationAnnotation;
     27 import org.testng.annotations.IDataProviderAnnotation;
     28 import org.testng.annotations.IExpectedExceptionsAnnotation;
     29 import org.testng.annotations.IFactoryAnnotation;
     30 import org.testng.annotations.IListenersAnnotation;
     31 import org.testng.annotations.IObjectFactoryAnnotation;
     32 import org.testng.annotations.IParametersAnnotation;
     33 import org.testng.annotations.ITestAnnotation;
     34 import org.testng.annotations.Listeners;
     35 import org.testng.annotations.Parameters;
     36 import org.testng.annotations.Test;
     37 import org.testng.collections.Lists;
     38 import org.testng.internal.Utils;
     39 
     40 /**
     41  * This class creates implementations of IAnnotations based on the JDK5
     42  * annotation that was found on the Java element.
     43  *
     44  * Created on Dec 20, 2005
     45  * @author <a href="mailto:cedric (at) beust.com">Cedric Beust</a>
     46  */
     47 public class JDK15TagFactory {
     48 
     49   public <A extends IAnnotation> A createTag(Class<?> cls, Annotation a,
     50                                              Class<A> annotationClass, IAnnotationTransformer transformer) {
     51     IAnnotation result = null;
     52 
     53     if (a != null) {
     54       if (annotationClass == IConfigurationAnnotation.class) {
     55         result = createConfigurationTag(cls, a);
     56       }
     57       else if (annotationClass == IDataProviderAnnotation.class) {
     58         result = createDataProviderTag(a);
     59       }
     60       else if (annotationClass == IExpectedExceptionsAnnotation.class) {
     61         result = createExpectedExceptionsTag(a);
     62       }
     63       else if (annotationClass == IFactoryAnnotation.class) {
     64         result = createFactoryTag(cls, a);
     65       }
     66       else if (annotationClass == IParametersAnnotation.class) {
     67         result = createParametersTag(a);
     68       }
     69       else if (annotationClass == IObjectFactoryAnnotation.class) {
     70         result = createObjectFactoryTag(a);
     71       }
     72       else if (annotationClass == ITestAnnotation.class) {
     73         result = createTestTag(cls, a, transformer);
     74       }
     75       else if (annotationClass == IListenersAnnotation.class) {
     76         result = createListenersTag(cls, a, transformer);
     77       }
     78       else if (annotationClass == IBeforeSuite.class || annotationClass == IAfterSuite.class ||
     79           annotationClass == IBeforeTest.class || annotationClass == IAfterTest.class ||
     80           annotationClass == IBeforeGroups.class || annotationClass == IAfterGroups.class ||
     81           annotationClass == IBeforeClass.class || annotationClass == IAfterClass.class ||
     82           annotationClass == IBeforeMethod.class || annotationClass == IAfterMethod.class)
     83       {
     84         result = maybeCreateNewConfigurationTag(cls, a, annotationClass);
     85       }
     86 
     87       else {
     88         throw new TestNGException("Unknown annotation requested:" + annotationClass);
     89       }
     90     }
     91 
     92     //noinspection unchecked
     93     return (A) result;
     94   }
     95 
     96   private IAnnotation maybeCreateNewConfigurationTag(Class<?> cls, Annotation a,
     97       Class<?> annotationClass)
     98   {
     99     IAnnotation result = null;
    100 
    101     if (annotationClass == IBeforeSuite.class) {
    102       BeforeSuite bs = (BeforeSuite) a;
    103       result = createConfigurationTag(cls, a,
    104           true, false,
    105           false, false,
    106           new String[0], new String[0],
    107           false, false,
    108           false, false,
    109           bs.alwaysRun(),
    110           bs.dependsOnGroups(), bs.dependsOnMethods(),
    111           bs.description(), bs.enabled(), bs.groups(),
    112           bs.inheritGroups(), null,
    113           false, false,
    114           bs.timeOut());
    115     }
    116     else if (annotationClass == IAfterSuite.class) {
    117       AfterSuite bs = (AfterSuite) a;
    118       result = createConfigurationTag(cls, a,
    119           false, true,
    120           false, false,
    121           new String[0], new String[0],
    122           false, false,
    123           false, false,
    124           bs.alwaysRun(),
    125           bs.dependsOnGroups(), bs.dependsOnMethods(),
    126           bs.description(), bs.enabled(), bs.groups(),
    127           bs.inheritGroups(), null,
    128           false, false,
    129           bs.timeOut());
    130     }
    131     else if (annotationClass == IBeforeTest.class) {
    132       BeforeTest bs = (BeforeTest) a;
    133       result = createConfigurationTag(cls, a,
    134           false, false,
    135           true, false,
    136           new String[0], new String[0],
    137           false, false,
    138           false, false,
    139           bs.alwaysRun(),
    140           bs.dependsOnGroups(), bs.dependsOnMethods(),
    141           bs.description(), bs.enabled(), bs.groups(),
    142           bs.inheritGroups(), null,
    143           false, false,
    144           bs.timeOut());
    145     }
    146     else if (annotationClass == IAfterTest.class) {
    147       AfterTest bs = (AfterTest) a;
    148       result = createConfigurationTag(cls, a,
    149           false, false,
    150           false, true,
    151           new String[0], new String[0],
    152           false, false,
    153           false, false,
    154           bs.alwaysRun(),
    155           bs.dependsOnGroups(), bs.dependsOnMethods(),
    156           bs.description(), bs.enabled(), bs.groups(),
    157           bs.inheritGroups(), null,
    158           false, false,
    159           bs.timeOut());
    160     }
    161     else if (annotationClass == IBeforeGroups.class) {
    162       BeforeGroups bs = (BeforeGroups) a;
    163       final String[] groups= bs.value().length > 0 ? bs.value() : bs.groups();
    164       result = createConfigurationTag(cls, a,
    165           false, false,
    166           false, false,
    167           groups, new String[0],
    168           false, false,
    169           false, false,
    170           bs.alwaysRun(),
    171           bs.dependsOnGroups(), bs.dependsOnMethods(),
    172           bs.description(), bs.enabled(), bs.groups(),
    173           bs.inheritGroups(), null,
    174           false, false,
    175           bs.timeOut());
    176     }
    177     else if (annotationClass == IAfterGroups.class) {
    178       AfterGroups bs = (AfterGroups) a;
    179       final String[] groups= bs.value().length > 0 ? bs.value() : bs.groups();
    180       result = createConfigurationTag(cls, a,
    181           false, false,
    182           false, false,
    183           new String[0], groups,
    184           false, false,
    185           false, false,
    186           bs.alwaysRun(),
    187           bs.dependsOnGroups(), bs.dependsOnMethods(),
    188           bs.description(), bs.enabled(), bs.groups(),
    189           bs.inheritGroups(), null,
    190           false, false,
    191           bs.timeOut());
    192     }
    193     else if (annotationClass == IBeforeClass.class) {
    194       BeforeClass bs = (BeforeClass) a;
    195       result = createConfigurationTag(cls, a,
    196           false, false,
    197           false, false,
    198           new String[0], new String[0],
    199           true, false,
    200           false, false,
    201           bs.alwaysRun(),
    202           bs.dependsOnGroups(), bs.dependsOnMethods(),
    203           bs.description(), bs.enabled(), bs.groups(),
    204           bs.inheritGroups(), null,
    205           false, false,
    206           bs.timeOut());
    207     }
    208     else if (annotationClass == IAfterClass.class) {
    209       AfterClass bs = (AfterClass) a;
    210       result = createConfigurationTag(cls, a,
    211           false, false,
    212           false, false,
    213           new String[0], new String[0],
    214           false, true,
    215           false, false,
    216           bs.alwaysRun(),
    217           bs.dependsOnGroups(), bs.dependsOnMethods(),
    218           bs.description(), bs.enabled(), bs.groups(),
    219           bs.inheritGroups(), null,
    220           false, false,
    221           bs.timeOut());
    222     }
    223     else if (annotationClass == IBeforeMethod.class) {
    224       BeforeMethod bs = (BeforeMethod) a;
    225       result = createConfigurationTag(cls, a,
    226           false, false,
    227           false, false,
    228           new String[0], new String[0],
    229           false, false,
    230           true, false,
    231           bs.alwaysRun(),
    232           bs.dependsOnGroups(), bs.dependsOnMethods(),
    233           bs.description(), bs.enabled(), bs.groups(),
    234           bs.inheritGroups(), null,
    235           bs.firstTimeOnly(), false,
    236           bs.timeOut());
    237     }
    238     else if (annotationClass == IAfterMethod.class) {
    239       AfterMethod bs = (AfterMethod) a;
    240       result = createConfigurationTag(cls, a,
    241           false, false,
    242           false, false,
    243           new String[0], new String[0],
    244           false, false,
    245           false, true,
    246           bs.alwaysRun(),
    247           bs.dependsOnGroups(), bs.dependsOnMethods(),
    248           bs.description(), bs.enabled(), bs.groups(),
    249           bs.inheritGroups(), null,
    250           false, bs.lastTimeOnly(),
    251           bs.timeOut());
    252     }
    253 
    254     return result;
    255   }
    256 
    257   @SuppressWarnings({"deprecation"})
    258   private ConfigurationAnnotation createConfigurationTag(Class<?> cls, Annotation a) {
    259     ConfigurationAnnotation result = new ConfigurationAnnotation();
    260     Configuration c = (Configuration) a;
    261     result.setBeforeTestClass(c.beforeTestClass());
    262     result.setAfterTestClass(c.afterTestClass());
    263     result.setBeforeTestMethod(c.beforeTestMethod());
    264     result.setAfterTestMethod(c.afterTestMethod());
    265     result.setBeforeTest(c.beforeTest());
    266     result.setAfterTest(c.afterTest());
    267     result.setBeforeSuite(c.beforeSuite());
    268     result.setAfterSuite(c.afterSuite());
    269     result.setBeforeGroups(c.beforeGroups());
    270     result.setAfterGroups(c.afterGroups());
    271     result.setParameters(c.parameters());
    272     result.setEnabled(c.enabled());
    273 
    274     result.setGroups(join(c.groups(), findInheritedStringArray(cls, Test.class, "groups")));
    275     result.setDependsOnGroups(c.dependsOnGroups());
    276     result.setDependsOnMethods(c.dependsOnMethods());
    277     result.setAlwaysRun(c.alwaysRun());
    278     result.setInheritGroups(c.inheritGroups());
    279     result.setDescription(c.description());
    280 
    281     return result;
    282   }
    283 
    284   private IAnnotation createConfigurationTag(Class<?> cls, Annotation a,
    285       boolean beforeSuite, boolean afterSuite,
    286       boolean beforeTest, boolean afterTest,
    287       String[] beforeGroups, String[] afterGroups,
    288       boolean beforeClass, boolean afterClass,
    289       boolean beforeMethod, boolean afterMethod,
    290       boolean alwaysRun,
    291       String[] dependsOnGroups, String[] dependsOnMethods,
    292       String description, boolean enabled, String[] groups,
    293       boolean inheritGroups, String[] parameters,
    294       boolean firstTimeOnly, boolean lastTimeOnly,
    295       long timeOut)
    296   {
    297     ConfigurationAnnotation result = new ConfigurationAnnotation();
    298     result.setFakeConfiguration(true);
    299     result.setBeforeSuite(beforeSuite);
    300     result.setAfterSuite(afterSuite);
    301     result.setBeforeTest(beforeTest);
    302     result.setAfterTest(afterTest);
    303     result.setBeforeTestClass(beforeClass);
    304     result.setAfterTestClass(afterClass);
    305     result.setBeforeGroups(beforeGroups);
    306     result.setAfterGroups(afterGroups);
    307     result.setBeforeTestMethod(beforeMethod);
    308     result.setAfterTestMethod(afterMethod);
    309 
    310     result.setAlwaysRun(alwaysRun);
    311     result.setDependsOnGroups(dependsOnGroups);
    312     result.setDependsOnMethods(dependsOnMethods);
    313     result.setDescription(description);
    314     result.setEnabled(enabled);
    315     result.setGroups(groups);
    316     result.setInheritGroups(inheritGroups);
    317     result.setParameters(parameters);
    318     result.setFirstTimeOnly(firstTimeOnly);
    319     result.setLastTimeOnly(lastTimeOnly);
    320     result.setTimeOut(timeOut);
    321 
    322     return result;
    323   }
    324 
    325   private IAnnotation createDataProviderTag(Annotation a) {
    326     DataProviderAnnotation result = new DataProviderAnnotation();
    327     DataProvider c = (DataProvider) a;
    328     result.setName(c.name());
    329     result.setParallel(c.parallel());
    330 
    331     return result;
    332   }
    333 
    334   @SuppressWarnings({"deprecation"})
    335   private IAnnotation createExpectedExceptionsTag(Annotation a) {
    336     ExpectedExceptionsAnnotation result = new ExpectedExceptionsAnnotation ();
    337     ExpectedExceptions c = (ExpectedExceptions ) a;
    338     result.setValue(c.value());
    339 
    340     return result;
    341   }
    342 
    343   @SuppressWarnings({"deprecation"})
    344   private IAnnotation createFactoryTag(Class<?> cls, Annotation a) {
    345     FactoryAnnotation result = new FactoryAnnotation();
    346     Factory c = (Factory) a;
    347     result.setParameters(c.parameters());
    348     result.setDataProvider(c.dataProvider());
    349     result.setDataProviderClass(
    350         findInherited(c.dataProviderClass(), cls, Factory.class, "dataProviderClass",
    351             DEFAULT_CLASS));
    352     result.setEnabled(c.enabled());
    353 
    354     return result;
    355   }
    356 
    357   private IAnnotation createObjectFactoryTag(Annotation a) {
    358     return new ObjectFactoryAnnotation();
    359   }
    360 
    361   private IAnnotation createParametersTag(Annotation a) {
    362     ParametersAnnotation result = new ParametersAnnotation();
    363     Parameters c = (Parameters) a;
    364     result.setValue(c.value());
    365 
    366     return result;
    367   }
    368 
    369   @SuppressWarnings({"deprecation"})
    370   private IAnnotation createListenersTag(Class<?> cls, Annotation a,
    371       IAnnotationTransformer transformer)
    372   {
    373     ListenersAnnotation result = new ListenersAnnotation();
    374     Listeners l = (Listeners) a;
    375     result.setValue(l.value());
    376 
    377     return result;
    378   }
    379 
    380   @SuppressWarnings({"deprecation"})
    381   private IAnnotation createTestTag(Class<?> cls, Annotation a,
    382       IAnnotationTransformer transformer)
    383   {
    384     TestAnnotation result = new TestAnnotation();
    385     Test test = (Test) a;
    386 
    387     result.setEnabled(test.enabled());
    388     result.setGroups(join(test.groups(), findInheritedStringArray(cls, Test.class, "groups")));
    389     result.setParameters(test.parameters());
    390     result.setDependsOnGroups(join(test.dependsOnGroups(),
    391         findInheritedStringArray(cls, Test.class, "dependsOnGroups")));
    392     result.setDependsOnMethods(join(test.dependsOnMethods(),
    393         findInheritedStringArray(cls, Test.class, "dependsOnMethods")));
    394     result.setTimeOut(test.timeOut());
    395     result.setInvocationTimeOut(test.invocationTimeOut());
    396     result.setInvocationCount(test.invocationCount());
    397     result.setThreadPoolSize(test.threadPoolSize());
    398     result.setSuccessPercentage(test.successPercentage());
    399     result.setDataProvider(test.dataProvider());
    400 //    result.setDataProviderClass(test.dataProviderClass() != Object.class ?
    401 //        test.dataProviderClass() : null);
    402     result.setDataProviderClass(
    403         findInherited(test.dataProviderClass(), cls, Test.class, "dataProviderClass",
    404             DEFAULT_CLASS));
    405     result.setAlwaysRun(test.alwaysRun());
    406     result.setDescription(
    407         findInherited(test.description(), cls, Test.class, "description", DEFAULT_STRING));
    408     result.setExpectedExceptions(test.expectedExceptions());
    409     result.setExpectedExceptionsMessageRegExp(test.expectedExceptionsMessageRegExp());
    410     result.setSuiteName(test.suiteName());
    411     result.setTestName(test.testName());
    412     result.setSequential(test.sequential());
    413     result.setSingleThreaded(test.singleThreaded());
    414     result.setRetryAnalyzer(test.retryAnalyzer());
    415     result.setSkipFailedInvocations(test.skipFailedInvocations());
    416     result.setIgnoreMissingDependencies(test.ignoreMissingDependencies());
    417     result.setPriority(test.priority());
    418 
    419     return result;
    420   }
    421 
    422   private String[] join(String[] strings, String[] strings2) {
    423     List<String> result = Lists.newArrayList(strings);
    424     Set<String> seen = new HashSet<>(Lists.newArrayList(strings));
    425     for (String s : strings2) {
    426       if (! seen.contains(s)) {
    427         result.add(s);
    428       }
    429     }
    430 
    431     return result.toArray(new String[result.size()]);
    432   }
    433 
    434   /**
    435    * This interface is used to calculate the default value for various
    436    * annotation return types. This is used when looking for an annotation in a
    437    * hierarchy. We can't use null as a default since annotation don't allow
    438    * nulls, so each type has a different way of defining its own default.
    439    */
    440   static interface Default<T> {
    441     boolean isDefault(T t);
    442   }
    443 
    444   private static final Default<Class<?>> DEFAULT_CLASS = new Default<Class<?>>() {
    445     @Override
    446     public boolean isDefault(Class<?> c) {
    447       return c == Object.class;
    448     }
    449   };
    450 
    451   private static final Default<String> DEFAULT_STRING = new Default<String>() {
    452     @Override
    453     public boolean isDefault(String s) {
    454       return Utils.isStringEmpty(s);
    455     }
    456   };
    457 
    458   /**
    459    * Find the value of an annotation, starting with the annotation found on the
    460    * method, then the class and then parent classes until we either find a
    461    * non-default value or we reach the top of the hierarchy (Object).
    462    */
    463   private <T> T findInherited(T methodValue, Class<?> cls,
    464       Class<? extends Annotation> annotationClass, String methodName,
    465       Default<T> def) {
    466 
    467     // Look on the method first and return right away if the annotation is there
    468     if (!def.isDefault(methodValue)) {
    469       return methodValue;
    470     }
    471 
    472     // Not found, look on the class and then up the hierarchy
    473     while (cls != null && cls != Object.class) {
    474       Annotation annotation = cls.getAnnotation(annotationClass);
    475       if (annotation != null) {
    476         T result = (T) invokeMethod(annotation, methodName);
    477         if (!def.isDefault(result)) {
    478           return result;
    479         }
    480       }
    481       cls = cls.getSuperclass();
    482     }
    483 
    484     return null;
    485   }
    486 
    487   /**
    488    * Find the value of a String[] annotation. The difference with the
    489    * findInherited method above is that TestNG aggregates String[] values across
    490    * hierarchies. For example, of the method annotation has { "a", "b" } and the
    491    * class has { "c" }, the returned value will be { "a", "b", "c" }.
    492    */
    493   private String[] findInheritedStringArray(Class<?> cls,
    494       Class<? extends Annotation> annotationClass, String methodName)
    495   {
    496     if (null == cls) {
    497       return new String[0];
    498     }
    499 
    500     List<String> result = Lists.newArrayList();
    501 
    502     while (cls != null && cls != Object.class) {
    503       Annotation annotation = cls.getAnnotation(annotationClass);
    504       if (annotation != null) {
    505         String[] g = (String[]) invokeMethod(annotation, methodName);
    506         for (String s : g) {
    507           result.add(s);
    508         }
    509       }
    510       cls = cls.getSuperclass();
    511     }
    512 
    513     return result.toArray(new String[result.size()]);
    514   }
    515 
    516   private Object invokeMethod(Annotation test, String methodName) {
    517     Object result = null;
    518     try {
    519       // Note:  we should cache methods already looked up
    520       Method m = test.getClass().getMethod(methodName, new Class[0]);
    521       result = m.invoke(test, new Object[0]);
    522     }
    523     catch (Exception e) {
    524       e.printStackTrace();
    525     }
    526     return result;
    527   }
    528 
    529   private void ppp(String string) {
    530     System.out.println("[JDK15TagFactory] " + string);
    531   }
    532 
    533 }
    534