1 package org.testng.xml; 2 3 import static org.testng.internal.Utils.isStringBlank; 4 5 import org.testng.ITestObjectFactory; 6 import org.testng.TestNGException; 7 import org.testng.collections.Lists; 8 import org.testng.collections.Maps; 9 import org.testng.internal.Utils; 10 import org.testng.log4testng.Logger; 11 import org.xml.sax.Attributes; 12 import org.xml.sax.InputSource; 13 import org.xml.sax.SAXException; 14 import org.xml.sax.SAXParseException; 15 import org.xml.sax.helpers.DefaultHandler; 16 17 import java.io.IOException; 18 import java.io.InputStream; 19 import java.util.ArrayList; 20 import java.util.List; 21 import java.util.Map; 22 import java.util.Stack; 23 24 /** 25 * Suite definition parser utility. 26 * 27 * @author Cedric Beust 28 * @author <a href='mailto:the_mindstorm@evolva.ro'>Alexandru Popescu</a> 29 */ 30 public class TestNGContentHandler extends DefaultHandler { 31 private XmlSuite m_currentSuite = null; 32 private XmlTest m_currentTest = null; 33 private List<String> m_currentDefines = null; 34 private List<String> m_currentRuns = null; 35 private List<XmlClass> m_currentClasses = null; 36 private int m_currentTestIndex = 0; 37 private int m_currentClassIndex = 0; 38 private int m_currentIncludeIndex = 0; 39 private List<XmlPackage> m_currentPackages = null; 40 private XmlPackage m_currentPackage = null; 41 private List<XmlSuite> m_suites = Lists.newArrayList(); 42 private List<String> m_currentIncludedGroups = null; 43 private List<String> m_currentExcludedGroups = null; 44 private Map<String, String> m_currentTestParameters = null; 45 private Map<String, String> m_currentSuiteParameters = null; 46 private Map<String, String> m_currentClassParameters = null; 47 private Include m_currentInclude; 48 private List<String> m_currentMetaGroup = null; 49 private String m_currentMetaGroupName; 50 51 enum Location { 52 SUITE, 53 TEST, 54 CLASS, 55 INCLUDE, 56 EXCLUDE 57 } 58 private Stack<Location> m_locations = new Stack<>(); 59 60 private XmlClass m_currentClass = null; 61 private ArrayList<XmlInclude> m_currentIncludedMethods = null; 62 private List<String> m_currentExcludedMethods = null; 63 private ArrayList<XmlMethodSelector> m_currentSelectors = null; 64 private XmlMethodSelector m_currentSelector = null; 65 private String m_currentLanguage = null; 66 private String m_currentExpression = null; 67 private List<String> m_suiteFiles = Lists.newArrayList(); 68 private boolean m_enabledTest; 69 private List<String> m_listeners; 70 71 private String m_fileName; 72 private boolean m_loadClasses; 73 private boolean m_validate = false; 74 private boolean m_hasWarn = false; 75 TestNGContentHandler(String fileName, boolean loadClasses)76 public TestNGContentHandler(String fileName, boolean loadClasses) { 77 m_fileName = fileName; 78 m_loadClasses = loadClasses; 79 } 80 ppp(String s)81 static private void ppp(String s) { 82 System.out.println("[TestNGContentHandler] " + s); 83 } 84 85 /* 86 * (non-Javadoc) 87 * 88 * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String, 89 * java.lang.String) 90 */ 91 @Override resolveEntity(String systemId, String publicId)92 public InputSource resolveEntity(String systemId, String publicId) 93 throws IOException, SAXException { 94 InputSource result = null; 95 if (Parser.DEPRECATED_TESTNG_DTD_URL.equals(publicId) 96 || Parser.TESTNG_DTD_URL.equals(publicId)) { 97 m_validate = true; 98 InputStream is = getClass().getClassLoader().getResourceAsStream(Parser.TESTNG_DTD); 99 if (null == is) { 100 is = Thread.currentThread().getContextClassLoader().getResourceAsStream(Parser.TESTNG_DTD); 101 if (null == is) { 102 System.out.println("WARNING: couldn't find in classpath " + publicId 103 + "\n" + "Fetching it from the Web site."); 104 result = super.resolveEntity(systemId, publicId); 105 } 106 else { 107 result = new InputSource(is); 108 } 109 } 110 else { 111 result = new InputSource(is); 112 } 113 } 114 else { 115 result = super.resolveEntity(systemId, publicId); 116 } 117 118 return result; 119 } 120 121 /** 122 * Parse <suite-file> 123 */ xmlSuiteFile(boolean start, Attributes attributes)124 private void xmlSuiteFile(boolean start, Attributes attributes) { 125 if (start) { 126 String path = attributes.getValue("path"); 127 pushLocation(Location.SUITE); 128 m_suiteFiles.add(path); 129 } 130 else { 131 m_currentSuite.setSuiteFiles(m_suiteFiles); 132 popLocation(Location.SUITE); 133 } 134 } 135 136 /** 137 * Parse <suite> 138 */ xmlSuite(boolean start, Attributes attributes)139 private void xmlSuite(boolean start, Attributes attributes) { 140 if (start) { 141 pushLocation(Location.SUITE); 142 String name = attributes.getValue("name"); 143 if (isStringBlank(name)) { 144 throw new TestNGException("The <suite> tag must define the name attribute"); 145 } 146 m_currentSuite = new XmlSuite(); 147 m_currentSuite.setFileName(m_fileName); 148 m_currentSuite.setName(name); 149 m_currentSuiteParameters = Maps.newHashMap(); 150 151 String verbose = attributes.getValue("verbose"); 152 if (null != verbose) { 153 m_currentSuite.setVerbose(Integer.parseInt(verbose)); 154 } 155 String jUnit = attributes.getValue("junit"); 156 if (null != jUnit) { 157 m_currentSuite.setJUnit(Boolean.valueOf(jUnit)); 158 } 159 String parallel = attributes.getValue("parallel"); 160 if (parallel != null) { 161 XmlSuite.ParallelMode mode = XmlSuite.ParallelMode.getValidParallel(parallel); 162 if (mode != null) { 163 m_currentSuite.setParallel(mode); 164 } else { 165 Utils.log("Parser", 1, "[WARN] Unknown value of attribute 'parallel' at suite level: '" + parallel + "'."); 166 } 167 } 168 String parentModule = attributes.getValue("parent-module"); 169 if (parentModule != null) { 170 m_currentSuite.setParentModule(parentModule); 171 } 172 String guiceStage = attributes.getValue("guice-stage"); 173 if (guiceStage != null) { 174 m_currentSuite.setGuiceStage(guiceStage); 175 } 176 String configFailurePolicy = attributes.getValue("configfailurepolicy"); 177 if (null != configFailurePolicy) { 178 if (XmlSuite.SKIP.equals(configFailurePolicy) || XmlSuite.CONTINUE.equals(configFailurePolicy)) { 179 m_currentSuite.setConfigFailurePolicy(configFailurePolicy); 180 } 181 } 182 String groupByInstances = attributes.getValue("group-by-instances"); 183 if (groupByInstances!= null) { 184 m_currentSuite.setGroupByInstances(Boolean.valueOf(groupByInstances)); 185 } 186 String skip = attributes.getValue("skipfailedinvocationcounts"); 187 if (skip != null) { 188 m_currentSuite.setSkipFailedInvocationCounts(Boolean.valueOf(skip)); 189 } 190 String threadCount = attributes.getValue("thread-count"); 191 if (null != threadCount) { 192 m_currentSuite.setThreadCount(Integer.parseInt(threadCount)); 193 } 194 String dataProviderThreadCount = attributes.getValue("data-provider-thread-count"); 195 if (null != dataProviderThreadCount) { 196 m_currentSuite.setDataProviderThreadCount(Integer.parseInt(dataProviderThreadCount)); 197 } 198 String timeOut = attributes.getValue("time-out"); 199 if (null != timeOut) { 200 m_currentSuite.setTimeOut(timeOut); 201 } 202 String objectFactory = attributes.getValue("object-factory"); 203 if (null != objectFactory && m_loadClasses) { 204 try { 205 m_currentSuite.setObjectFactory((ITestObjectFactory)Class.forName(objectFactory).newInstance()); 206 } 207 catch(Exception e) { 208 Utils.log("Parser", 1, "[ERROR] Unable to create custom object factory '" + objectFactory + "' :" + e); 209 } 210 } 211 String preserveOrder = attributes.getValue("preserve-order"); 212 if (preserveOrder != null) { 213 m_currentSuite.setPreserveOrder(preserveOrder); 214 } 215 String allowReturnValues = attributes.getValue("allow-return-values"); 216 if (allowReturnValues != null) { 217 m_currentSuite.setAllowReturnValues(Boolean.valueOf(allowReturnValues)); 218 } 219 } 220 else { 221 m_currentSuite.setParameters(m_currentSuiteParameters); 222 m_suites.add(m_currentSuite); 223 m_currentSuiteParameters = null; 224 popLocation(Location.SUITE); 225 } 226 } 227 228 /** 229 * Parse <define> 230 */ xmlDefine(boolean start, Attributes attributes)231 private void xmlDefine(boolean start, Attributes attributes) { 232 if (start) { 233 String name = attributes.getValue("name"); 234 m_currentDefines = Lists.newArrayList(); 235 m_currentMetaGroup = Lists.newArrayList(); 236 m_currentMetaGroupName = name; 237 } 238 else { 239 m_currentTest.addMetaGroup(m_currentMetaGroupName, m_currentMetaGroup); 240 m_currentDefines = null; 241 } 242 } 243 244 /** 245 * Parse <script> 246 */ xmlScript(boolean start, Attributes attributes)247 private void xmlScript(boolean start, Attributes attributes) { 248 if (start) { 249 // ppp("OPEN SCRIPT"); 250 m_currentLanguage = attributes.getValue("language"); 251 m_currentExpression = ""; 252 } 253 else { 254 // ppp("CLOSE SCRIPT:@@" + m_currentExpression + "@@"); 255 m_currentSelector.setExpression(m_currentExpression); 256 m_currentSelector.setLanguage(m_currentLanguage); 257 if (m_locations.peek() == Location.TEST) { 258 m_currentTest.setBeanShellExpression(m_currentExpression); 259 } 260 m_currentLanguage = null; 261 m_currentExpression = null; 262 } 263 } 264 265 /** 266 * Parse <test> 267 */ xmlTest(boolean start, Attributes attributes)268 private void xmlTest(boolean start, Attributes attributes) { 269 if (start) { 270 m_currentTest = new XmlTest(m_currentSuite, m_currentTestIndex++); 271 pushLocation(Location.TEST); 272 m_currentTestParameters = Maps.newHashMap(); 273 final String testName= attributes.getValue("name"); 274 if(isStringBlank(testName)) { 275 throw new TestNGException("The <test> tag must define the name attribute"); 276 } 277 m_currentTest.setName(attributes.getValue("name")); 278 String verbose = attributes.getValue("verbose"); 279 if (null != verbose) { 280 m_currentTest.setVerbose(Integer.parseInt(verbose)); 281 } 282 String jUnit = attributes.getValue("junit"); 283 if (null != jUnit) { 284 m_currentTest.setJUnit(Boolean.valueOf(jUnit)); 285 } 286 String skip = attributes.getValue("skipfailedinvocationcounts"); 287 if (skip != null) { 288 m_currentTest.setSkipFailedInvocationCounts(Boolean.valueOf(skip)); 289 } 290 String groupByInstances = attributes.getValue("group-by-instances"); 291 if (groupByInstances!= null) { 292 m_currentTest.setGroupByInstances(Boolean.valueOf(groupByInstances)); 293 } 294 String preserveOrder = attributes.getValue("preserve-order"); 295 if (preserveOrder != null) { 296 m_currentTest.setPreserveOrder(preserveOrder); 297 } 298 String parallel = attributes.getValue("parallel"); 299 if (parallel != null) { 300 XmlSuite.ParallelMode mode = XmlSuite.ParallelMode.getValidParallel(parallel); 301 if (mode != null) { 302 m_currentTest.setParallel(mode); 303 } else { 304 Utils.log("Parser", 1, "[WARN] Unknown value of attribute 'parallel' for test '" 305 + m_currentTest.getName() + "': '" + parallel + "'"); 306 } 307 } 308 String threadCount = attributes.getValue("thread-count"); 309 if(null != threadCount) { 310 m_currentTest.setThreadCount(Integer.parseInt(threadCount)); 311 } 312 String timeOut = attributes.getValue("time-out"); 313 if (null != timeOut) { 314 m_currentTest.setTimeOut(Long.parseLong(timeOut)); 315 } 316 m_enabledTest= true; 317 String enabledTestString = attributes.getValue("enabled"); 318 if(null != enabledTestString) { 319 m_enabledTest = Boolean.valueOf(enabledTestString); 320 } 321 } 322 else { 323 if (null != m_currentTestParameters && m_currentTestParameters.size() > 0) { 324 m_currentTest.setParameters(m_currentTestParameters); 325 } 326 if (null != m_currentClasses) { 327 m_currentTest.setXmlClasses(m_currentClasses); 328 } 329 m_currentClasses = null; 330 m_currentTest = null; 331 m_currentTestParameters = null; 332 popLocation(Location.TEST); 333 if(!m_enabledTest) { 334 List<XmlTest> tests= m_currentSuite.getTests(); 335 tests.remove(tests.size() - 1); 336 } 337 } 338 } 339 340 /** 341 * Parse <classes> 342 */ xmlClasses(boolean start, Attributes attributes)343 public void xmlClasses(boolean start, Attributes attributes) { 344 if (start) { 345 m_currentClasses = Lists.newArrayList(); 346 m_currentClassIndex = 0; 347 } 348 else { 349 m_currentTest.setXmlClasses(m_currentClasses); 350 m_currentClasses = null; 351 } 352 } 353 354 /** 355 * Parse <listeners> 356 */ xmlListeners(boolean start, Attributes attributes)357 public void xmlListeners(boolean start, Attributes attributes) { 358 if (start) { 359 m_listeners = Lists.newArrayList(); 360 } 361 else { 362 if (null != m_listeners) { 363 m_currentSuite.setListeners(m_listeners); 364 m_listeners = null; 365 } 366 } 367 } 368 369 /** 370 * Parse <listener> 371 */ xmlListener(boolean start, Attributes attributes)372 public void xmlListener(boolean start, Attributes attributes) { 373 if (start) { 374 String listener = attributes.getValue("class-name"); 375 m_listeners.add(listener); 376 } 377 } 378 379 /** 380 * Parse <packages> 381 */ xmlPackages(boolean start, Attributes attributes)382 public void xmlPackages(boolean start, Attributes attributes) { 383 if (start) { 384 m_currentPackages = Lists.newArrayList(); 385 } 386 else { 387 if (null != m_currentPackages) { 388 switch(m_locations.peek()) { 389 case TEST: 390 m_currentTest.setXmlPackages(m_currentPackages); 391 break; 392 case SUITE: 393 m_currentSuite.setXmlPackages(m_currentPackages); 394 break; 395 case CLASS: 396 throw new UnsupportedOperationException("CLASS"); 397 } 398 } 399 400 m_currentPackages = null; 401 m_currentPackage = null; 402 } 403 } 404 405 /** 406 * Parse <method-selectors> 407 */ xmlMethodSelectors(boolean start, Attributes attributes)408 public void xmlMethodSelectors(boolean start, Attributes attributes) { 409 if (start) { 410 m_currentSelectors = new ArrayList<>(); 411 } 412 else { 413 switch(m_locations.peek()) { 414 case TEST: 415 m_currentTest.setMethodSelectors(m_currentSelectors); 416 break; 417 default: 418 m_currentSuite.setMethodSelectors(m_currentSelectors); 419 break; 420 } 421 422 m_currentSelectors = null; 423 } 424 } 425 426 /** 427 * Parse <selector-class> 428 */ xmlSelectorClass(boolean start, Attributes attributes)429 public void xmlSelectorClass(boolean start, Attributes attributes) { 430 if (start) { 431 m_currentSelector.setName(attributes.getValue("name")); 432 String priority = attributes.getValue("priority"); 433 if (priority == null) { 434 priority = "0"; 435 } 436 m_currentSelector.setPriority(Integer.parseInt(priority)); 437 } 438 else { 439 // do nothing 440 } 441 } 442 443 /** 444 * Parse <method-selector> 445 */ xmlMethodSelector(boolean start, Attributes attributes)446 public void xmlMethodSelector(boolean start, Attributes attributes) { 447 if (start) { 448 m_currentSelector = new XmlMethodSelector(); 449 } 450 else { 451 m_currentSelectors.add(m_currentSelector); 452 m_currentSelector = null; 453 } 454 } 455 xmlMethod(boolean start, Attributes attributes)456 private void xmlMethod(boolean start, Attributes attributes) { 457 if (start) { 458 m_currentIncludedMethods = new ArrayList<>(); 459 m_currentExcludedMethods = Lists.newArrayList(); 460 m_currentIncludeIndex = 0; 461 } 462 else { 463 m_currentClass.setIncludedMethods(m_currentIncludedMethods); 464 m_currentClass.setExcludedMethods(m_currentExcludedMethods); 465 m_currentIncludedMethods = null; 466 m_currentExcludedMethods = null; 467 } 468 } 469 470 /** 471 * Parse <run> 472 */ xmlRun(boolean start, Attributes attributes)473 public void xmlRun(boolean start, Attributes attributes) throws SAXException { 474 if (start) { 475 m_currentRuns = Lists.newArrayList(); 476 } 477 else { 478 if (m_currentTest != null) { 479 m_currentTest.setIncludedGroups(m_currentIncludedGroups); 480 m_currentTest.setExcludedGroups(m_currentExcludedGroups); 481 } else { 482 m_currentSuite.setIncludedGroups(m_currentIncludedGroups); 483 m_currentSuite.setExcludedGroups(m_currentExcludedGroups); 484 } 485 m_currentRuns = null; 486 } 487 } 488 489 490 /** 491 * Parse <group> 492 */ xmlGroup(boolean start, Attributes attributes)493 public void xmlGroup(boolean start, Attributes attributes) throws SAXException { 494 if (start) { 495 m_currentTest.addXmlDependencyGroup(attributes.getValue("name"), 496 attributes.getValue("depends-on")); 497 } 498 } 499 500 /** 501 * NOTE: I only invoke xml*methods (e.g. xmlSuite()) if I am acting on both 502 * the start and the end of the tag. This way I can keep the treatment of 503 * this tag in one place. If I am only doing something when the tag opens, 504 * the code is inlined below in the startElement() method. 505 */ 506 @Override startElement(String uri, String localName, String qName, Attributes attributes)507 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { 508 if (!m_validate && !m_hasWarn) { 509 Logger.getLogger(TestNGContentHandler.class).warn("It is strongly recommended to add " + 510 "\"<!DOCTYPE suite SYSTEM \"http://testng.org/testng-1.0.dtd\" >\" at the top of your file, " + 511 "otherwise TestNG may fail or not work as expected."); 512 m_hasWarn = true; 513 } 514 String name = attributes.getValue("name"); 515 516 // ppp("START ELEMENT uri:" + uri + " sName:" + localName + " qName:" + qName + 517 // " " + attributes); 518 if ("suite".equals(qName)) { 519 xmlSuite(true, attributes); 520 } 521 else if ("suite-file".equals(qName)) { 522 xmlSuiteFile(true, attributes); 523 } 524 else if ("test".equals(qName)) { 525 xmlTest(true, attributes); 526 } 527 else if ("script".equals(qName)) { 528 xmlScript(true, attributes); 529 } 530 else if ("method-selector".equals(qName)) { 531 xmlMethodSelector(true, attributes); 532 } 533 else if ("method-selectors".equals(qName)) { 534 xmlMethodSelectors(true, attributes); 535 } 536 else if ("selector-class".equals(qName)) { 537 xmlSelectorClass(true, attributes); 538 } 539 else if ("classes".equals(qName)) { 540 xmlClasses(true, attributes); 541 } 542 else if ("packages".equals(qName)) { 543 xmlPackages(true, attributes); 544 } 545 else if ("listeners".equals(qName)) { 546 xmlListeners(true, attributes); 547 } 548 else if ("listener".equals(qName)) { 549 xmlListener(true, attributes); 550 } 551 else if ("class".equals(qName)) { 552 // If m_currentClasses is null, the XML is invalid and SAX 553 // will complain, but in the meantime, dodge the NPE so SAX 554 // can finish parsing the file. 555 if (null != m_currentClasses) { 556 m_currentClass = new XmlClass(name, m_currentClassIndex++, m_loadClasses); 557 m_currentClass.setXmlTest(m_currentTest); 558 m_currentClassParameters = Maps.newHashMap(); 559 m_currentClasses.add(m_currentClass); 560 pushLocation(Location.CLASS); 561 } 562 } 563 else if ("package".equals(qName)) { 564 if (null != m_currentPackages) { 565 m_currentPackage = new XmlPackage(); 566 m_currentPackage.setName(name); 567 m_currentPackages.add(m_currentPackage); 568 } 569 } 570 else if ("define".equals(qName)) { 571 xmlDefine(true, attributes); 572 } 573 else if ("run".equals(qName)) { 574 xmlRun(true, attributes); 575 } 576 else if ("group".equals(qName)) { 577 xmlGroup(true, attributes); 578 } 579 else if ("groups".equals(qName)) { 580 m_currentIncludedGroups = Lists.newArrayList(); 581 m_currentExcludedGroups = Lists.newArrayList(); 582 } 583 else if ("methods".equals(qName)) { 584 xmlMethod(true, attributes); 585 } 586 else if ("include".equals(qName)) { 587 xmlInclude(true, attributes); 588 } 589 else if ("exclude".equals(qName)) { 590 xmlExclude(true, attributes); 591 } 592 else if ("parameter".equals(qName)) { 593 String value = expandValue(attributes.getValue("value")); 594 switch(m_locations.peek()) { 595 case TEST: 596 m_currentTestParameters.put(name, value); 597 break; 598 case SUITE: 599 m_currentSuiteParameters.put(name, value); 600 break; 601 case CLASS: 602 m_currentClassParameters.put(name, value); 603 break; 604 case INCLUDE: 605 m_currentInclude.parameters.put(name, value); 606 break; 607 } 608 } 609 } 610 611 private static class Include { 612 String name; 613 String invocationNumbers; 614 String description; 615 Map<String, String> parameters = Maps.newHashMap(); 616 Include(String name, String numbers)617 public Include(String name, String numbers) { 618 this.name = name; 619 this.invocationNumbers = numbers; 620 } 621 } 622 xmlInclude(boolean start, Attributes attributes)623 private void xmlInclude(boolean start, Attributes attributes) { 624 if (start) { 625 m_locations.push(Location.INCLUDE); 626 m_currentInclude = new Include(attributes.getValue("name"), 627 attributes.getValue("invocation-numbers")); 628 } else { 629 String name = m_currentInclude.name; 630 if (null != m_currentIncludedMethods) { 631 String in = m_currentInclude.invocationNumbers; 632 XmlInclude include; 633 if (!Utils.isStringEmpty(in)) { 634 include = new XmlInclude(name, stringToList(in), m_currentIncludeIndex++); 635 } else { 636 include = new XmlInclude(name, m_currentIncludeIndex++); 637 } 638 for (Map.Entry<String, String> entry : m_currentInclude.parameters.entrySet()) { 639 include.addParameter(entry.getKey(), entry.getValue()); 640 } 641 642 include.setDescription(m_currentInclude.description); 643 m_currentIncludedMethods.add(include); 644 } 645 else if (null != m_currentDefines) { 646 m_currentMetaGroup.add(name); 647 } 648 else if (null != m_currentRuns) { 649 m_currentIncludedGroups.add(name); 650 } 651 else if (null != m_currentPackage) { 652 m_currentPackage.getInclude().add(name); 653 } 654 655 popLocation(Location.INCLUDE); 656 m_currentInclude = null; 657 } 658 } 659 xmlExclude(boolean start, Attributes attributes)660 private void xmlExclude(boolean start, Attributes attributes) { 661 if (start) { 662 m_locations.push(Location.EXCLUDE); 663 String name = attributes.getValue("name"); 664 if (null != m_currentExcludedMethods) { 665 m_currentExcludedMethods.add(name); 666 } 667 else if (null != m_currentRuns) { 668 m_currentExcludedGroups.add(name); 669 } 670 else if (null != m_currentPackage) { 671 m_currentPackage.getExclude().add(name); 672 } 673 } else { 674 popLocation(Location.EXCLUDE); 675 } 676 } 677 pushLocation(Location l)678 private void pushLocation(Location l) { 679 m_locations.push(l); 680 } 681 popLocation(Location location)682 private Location popLocation(Location location) { 683 return m_locations.pop(); 684 } 685 stringToList(String in)686 private List<Integer> stringToList(String in) { 687 String[] numbers = in.split(" "); 688 List<Integer> result = Lists.newArrayList(); 689 for (String n : numbers) { 690 result.add(Integer.parseInt(n)); 691 } 692 return result; 693 } 694 695 @Override endElement(String uri, String localName, String qName)696 public void endElement(String uri, String localName, String qName) throws SAXException { 697 if ("suite".equals(qName)) { 698 xmlSuite(false, null); 699 } 700 else if ("suite-file".equals(qName)) { 701 xmlSuiteFile(false, null); 702 } 703 else if ("test".equals(qName)) { 704 xmlTest(false, null); 705 } 706 else if ("define".equals(qName)) { 707 xmlDefine(false, null); 708 } 709 else if ("run".equals(qName)) { 710 xmlRun(false, null); 711 } 712 else if ("methods".equals(qName)) { 713 xmlMethod(false, null); 714 } 715 else if ("classes".equals(qName)) { 716 xmlClasses(false, null); 717 } 718 else if ("packages".equals(qName)) { 719 xmlPackages(false, null); 720 } 721 else if ("class".equals(qName)) { 722 m_currentClass.setParameters(m_currentClassParameters); 723 m_currentClassParameters = null; 724 popLocation(Location.CLASS); 725 } 726 else if ("listeners".equals(qName)) { 727 xmlListeners(false, null); 728 } 729 else if ("method-selector".equals(qName)) { 730 xmlMethodSelector(false, null); 731 } 732 else if ("method-selectors".equals(qName)) { 733 xmlMethodSelectors(false, null); 734 } 735 else if ("selector-class".equals(qName)) { 736 xmlSelectorClass(false, null); 737 } 738 else if ("script".equals(qName)) { 739 xmlScript(false, null); 740 } 741 else if ("packages".equals(qName)) { 742 xmlPackages(false, null); 743 } 744 else if ("include".equals(qName)) { 745 xmlInclude(false, null); 746 } else if ("exclude".equals(qName)){ 747 xmlExclude(false, null); 748 } 749 } 750 751 @Override error(SAXParseException e)752 public void error(SAXParseException e) throws SAXException { 753 if (m_validate) { 754 throw e; 755 } 756 } 757 areWhiteSpaces(char[] ch, int start, int length)758 private boolean areWhiteSpaces(char[] ch, int start, int length) { 759 for (int i = start; i < start + length; i++) { 760 char c = ch[i]; 761 if (c != '\n' && c != '\t' && c != ' ') { 762 return false; 763 } 764 } 765 766 return true; 767 } 768 769 @Override characters(char ch[], int start, int length)770 public void characters(char ch[], int start, int length) { 771 if (null != m_currentLanguage && ! areWhiteSpaces(ch, start, length)) { 772 m_currentExpression += new String(ch, start, length); 773 } 774 } 775 getSuite()776 public XmlSuite getSuite() { 777 return m_currentSuite; 778 } 779 expandValue(String value)780 private static String expandValue(String value) 781 { 782 StringBuffer result = null; 783 int startIndex = 0; 784 int endIndex = 0; 785 int startPosition = 0; 786 String property = null; 787 while ((startIndex = value.indexOf("${", startPosition)) > -1 && (endIndex = value.indexOf("}", startIndex + 3)) > -1) { 788 property = value.substring(startIndex + 2, endIndex); 789 if (result == null) { 790 result = new StringBuffer(value.substring(startPosition, startIndex)); 791 } else { 792 result.append(value.substring(startPosition, startIndex)); 793 } 794 String propertyValue = System.getProperty(property); 795 if (propertyValue == null) { 796 propertyValue = System.getenv(property); 797 } 798 if (propertyValue != null) { 799 result.append(propertyValue); 800 } else { 801 result.append("${"); 802 result.append(property); 803 result.append("}"); 804 } 805 startPosition = startIndex + 3 + property.length(); 806 } 807 if (result != null) { 808 result.append(value.substring(startPosition)); 809 return result.toString(); 810 } else { 811 return value; 812 } 813 } 814 } 815