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