Coverage Report - org.apache.maven.plugins.surefire.report.SurefireReportGenerator
 
Classes in this File Line Coverage Branch Coverage Complexity
SurefireReportGenerator
99%
356/361
73%
54/74
2.882
 
 1  
 package org.apache.maven.plugins.surefire.report;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *     http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import org.apache.maven.doxia.sink.Sink;
 23  
 import org.apache.maven.reporting.MavenReportException;
 24  
 
 25  
 import java.text.NumberFormat;
 26  
 import java.util.Iterator;
 27  
 import java.util.List;
 28  
 import java.util.ListIterator;
 29  
 import java.util.Locale;
 30  
 import java.util.Map;
 31  
 import java.util.ResourceBundle;
 32  
 import java.util.StringTokenizer;
 33  
 
 34  
 /**
 35  
  * @version $Id: SurefireReportGenerator.java 1061306 2011-01-20 14:10:44Z krosenvold $
 36  
  */
 37  
 public class SurefireReportGenerator
 38  
 {
 39  
     private SurefireReportParser report;
 40  
 
 41  
     private List testSuites;
 42  
 
 43  
     private boolean showSuccess;
 44  
 
 45  
     private String xrefLocation;
 46  
 
 47  
     public SurefireReportGenerator( List reportsDirectories, Locale locale, boolean showSuccess, String xrefLocation )
 48  4
     {
 49  4
         report = new SurefireReportParser( reportsDirectories, locale );
 50  
 
 51  4
         this.xrefLocation = xrefLocation;
 52  
 
 53  4
         this.showSuccess = showSuccess;
 54  4
     }
 55  
 
 56  
     public void doGenerateReport( ResourceBundle bundle, Sink sink )
 57  
         throws MavenReportException
 58  
     {
 59  4
         testSuites = report.parseXMLReportFiles();
 60  
 
 61  4
         sink.head();
 62  
 
 63  4
         sink.title();
 64  4
         sink.text( bundle.getString( "report.surefire.header" ) );
 65  4
         sink.title_();
 66  
 
 67  4
         StringBuffer str = new StringBuffer();
 68  4
         str.append( "<script type=\"text/javascript\">\n" );
 69  4
         str.append( "function toggleDisplay(elementId) {\n" );
 70  4
         str.append( " var elm = document.getElementById(elementId + 'error');\n" );
 71  4
         str.append( " if (elm && typeof elm.style != \"undefined\") {\n" );
 72  4
         str.append( " if (elm.style.display == \"none\") {\n" );
 73  4
         str.append( " elm.style.display = \"\";\n" );
 74  4
         str.append( " document.getElementById(elementId + 'off').style.display = \"none\";\n" );
 75  4
         str.append( " document.getElementById(elementId + 'on').style.display = \"inline\";\n" );
 76  4
         str.append( " }" );
 77  4
         str.append( " else if (elm.style.display == \"\") {" );
 78  4
         str.append( " elm.style.display = \"none\";\n" );
 79  4
         str.append( " document.getElementById(elementId + 'off').style.display = \"inline\";\n" );
 80  4
         str.append( " document.getElementById(elementId + 'on').style.display = \"none\";\n" );
 81  4
         str.append( " } \n" );
 82  4
         str.append( " } \n" );
 83  4
         str.append( " }\n" );
 84  4
         str.append( "</script>" );
 85  4
         sink.rawText( str.toString() );
 86  
 
 87  4
         sink.head_();
 88  
 
 89  4
         sink.body();
 90  
 
 91  4
         sink.section1();
 92  4
         sink.sectionTitle1();
 93  4
         sink.text( bundle.getString( "report.surefire.header" ) );
 94  4
         sink.sectionTitle1_();
 95  4
         sink.section1_();
 96  
 
 97  4
         constructSummarySection( bundle, sink );
 98  
 
 99  4
         Map suitePackages = report.getSuitesGroupByPackage( testSuites );
 100  4
         if ( !suitePackages.isEmpty() )
 101  
         {
 102  4
             constructPackagesSection( bundle, sink, suitePackages );
 103  
         }
 104  
 
 105  4
         if ( !testSuites.isEmpty() )
 106  
         {
 107  4
             constructTestCasesSection( bundle, sink );
 108  
         }
 109  
 
 110  4
         List failureList = report.getFailureDetails( testSuites );
 111  4
         if ( !failureList.isEmpty() )
 112  
         {
 113  4
             constructFailureDetails( sink, bundle, failureList );
 114  
         }
 115  
 
 116  4
         sink.body_();
 117  
 
 118  4
         sink.flush();
 119  
 
 120  4
         sink.close();
 121  4
     }
 122  
 
 123  
     private void constructSummarySection( ResourceBundle bundle, Sink sink )
 124  
     {
 125  4
         Map summary = report.getSummary( testSuites );
 126  
 
 127  4
         sink.section1();
 128  4
         sink.sectionTitle1();
 129  4
         sink.text( bundle.getString( "report.surefire.label.summary" ) );
 130  4
         sink.sectionTitle1_();
 131  
 
 132  4
         sinkAnchor( sink, "Summary" );
 133  
 
 134  4
         constructHotLinks( sink, bundle );
 135  
 
 136  4
         sinkLineBreak( sink );
 137  
 
 138  4
         sink.table();
 139  
 
 140  4
         sink.tableRow();
 141  
 
 142  4
         sinkHeader( sink, bundle.getString( "report.surefire.label.tests" ) );
 143  
 
 144  4
         sinkHeader( sink, bundle.getString( "report.surefire.label.errors" ) );
 145  
 
 146  4
         sinkHeader( sink, bundle.getString( "report.surefire.label.failures" ) );
 147  
 
 148  4
         sinkHeader( sink, bundle.getString( "report.surefire.label.skipped" ) );
 149  
 
 150  4
         sinkHeader( sink, bundle.getString( "report.surefire.label.successrate" ) );
 151  
 
 152  4
         sinkHeader( sink, bundle.getString( "report.surefire.label.time" ) );
 153  
 
 154  4
         sink.tableRow_();
 155  
 
 156  4
         sink.tableRow();
 157  
 
 158  4
         sinkCell( sink, (String) summary.get( "totalTests" ) );
 159  
 
 160  4
         sinkCell( sink, (String) summary.get( "totalErrors" ) );
 161  
 
 162  4
         sinkCell( sink, (String) summary.get( "totalFailures" ) );
 163  
 
 164  4
         sinkCell( sink, (String) summary.get( "totalSkipped" ) );
 165  
 
 166  4
         sinkCell( sink, summary.get( "totalPercentage" ) + "%" );
 167  
 
 168  4
         sinkCell( sink, (String) summary.get( "totalElapsedTime" ) );
 169  
 
 170  4
         sink.tableRow_();
 171  
 
 172  4
         sink.table_();
 173  
 
 174  4
         sink.lineBreak();
 175  
 
 176  4
         sink.paragraph();
 177  4
         sink.rawText( bundle.getString( "report.surefire.text.note1" ) );
 178  4
         sink.paragraph_();
 179  
 
 180  4
         sinkLineBreak( sink );
 181  
 
 182  4
         sink.section1_();
 183  4
     }
 184  
 
 185  
     private void constructPackagesSection( ResourceBundle bundle, Sink sink, Map suitePackages )
 186  
     {
 187  4
         NumberFormat numberFormat = report.getNumberFormat();
 188  
 
 189  4
         sink.section1();
 190  4
         sink.sectionTitle1();
 191  4
         sink.text( bundle.getString( "report.surefire.label.packagelist" ) );
 192  4
         sink.sectionTitle1_();
 193  
 
 194  4
         sinkAnchor( sink, "Package_List" );
 195  
 
 196  4
         constructHotLinks( sink, bundle );
 197  
 
 198  4
         sinkLineBreak( sink );
 199  
 
 200  4
         sink.table();
 201  
 
 202  4
         sink.tableRow();
 203  
 
 204  4
         sinkHeader( sink, bundle.getString( "report.surefire.label.package" ) );
 205  
 
 206  4
         sinkHeader( sink, bundle.getString( "report.surefire.label.tests" ) );
 207  
 
 208  4
         sinkHeader( sink, bundle.getString( "report.surefire.label.errors" ) );
 209  
 
 210  4
         sinkHeader( sink, bundle.getString( "report.surefire.label.failures" ) );
 211  
 
 212  4
         sinkHeader( sink, bundle.getString( "report.surefire.label.skipped" ) );
 213  
 
 214  4
         sinkHeader( sink, bundle.getString( "report.surefire.label.successrate" ) );
 215  
 
 216  4
         sinkHeader( sink, bundle.getString( "report.surefire.label.time" ) );
 217  
 
 218  4
         sink.tableRow_();
 219  
 
 220  4
         Iterator packIter = suitePackages.keySet().iterator();
 221  
 
 222  8
         while ( packIter.hasNext() )
 223  
         {
 224  4
             sink.tableRow();
 225  
 
 226  4
             String packageName = (String) packIter.next();
 227  
 
 228  4
             List testSuiteList = (List) suitePackages.get( packageName );
 229  
 
 230  4
             Map packageSummary = report.getSummary( testSuiteList );
 231  
 
 232  4
             sinkCellLink( sink, packageName, "#" + packageName );
 233  
 
 234  4
             sinkCell( sink, (String) packageSummary.get( "totalTests" ) );
 235  
 
 236  4
             sinkCell( sink, (String) packageSummary.get( "totalErrors" ) );
 237  
 
 238  4
             sinkCell( sink, (String) packageSummary.get( "totalFailures" ) );
 239  
 
 240  4
             sinkCell( sink, (String) packageSummary.get( "totalSkipped" ) );
 241  
 
 242  4
             sinkCell( sink, packageSummary.get( "totalPercentage" ) + "%" );
 243  
 
 244  4
             sinkCell( sink, (String) packageSummary.get( "totalElapsedTime" ) );
 245  
 
 246  4
             sink.tableRow_();
 247  4
         }
 248  
 
 249  4
         sink.table_();
 250  
 
 251  4
         sink.lineBreak();
 252  
 
 253  4
         sink.paragraph();
 254  4
         sink.rawText( bundle.getString( "report.surefire.text.note2" ) );
 255  4
         sink.paragraph_();
 256  
 
 257  4
         packIter = suitePackages.keySet().iterator();
 258  
 
 259  8
         while ( packIter.hasNext() )
 260  
         {
 261  4
             String packageName = (String) packIter.next();
 262  
 
 263  4
             List testSuiteList = (List) suitePackages.get( packageName );
 264  
 
 265  4
             Iterator suiteIterator = testSuiteList.iterator();
 266  
 
 267  4
             sink.section2();
 268  4
             sink.sectionTitle2();
 269  4
             sink.text( packageName );
 270  4
             sink.sectionTitle2_();
 271  
 
 272  4
             sinkAnchor( sink, packageName );
 273  
 
 274  4
             sink.table();
 275  
 
 276  4
             sink.tableRow();
 277  
 
 278  4
             sinkHeader( sink, "" );
 279  
 
 280  4
             sinkHeader( sink, bundle.getString( "report.surefire.label.class" ) );
 281  
 
 282  4
             sinkHeader( sink, bundle.getString( "report.surefire.label.tests" ) );
 283  
 
 284  4
             sinkHeader( sink, bundle.getString( "report.surefire.label.errors" ) );
 285  
 
 286  4
             sinkHeader( sink, bundle.getString( "report.surefire.label.failures" ) );
 287  
 
 288  4
             sinkHeader( sink, bundle.getString( "report.surefire.label.skipped" ) );
 289  
 
 290  4
             sinkHeader( sink, bundle.getString( "report.surefire.label.successrate" ) );
 291  
 
 292  4
             sinkHeader( sink, bundle.getString( "report.surefire.label.time" ) );
 293  
 
 294  4
             sink.tableRow_();
 295  
 
 296  8
             while ( suiteIterator.hasNext() )
 297  
             {
 298  4
                 ReportTestSuite suite = (ReportTestSuite) suiteIterator.next();
 299  
 
 300  4
                 if ( showSuccess || suite.getNumberOfErrors() != 0 || suite.getNumberOfFailures() != 0 )
 301  
                 {
 302  
 
 303  4
                     sink.tableRow();
 304  
 
 305  4
                     sink.tableCell();
 306  
 
 307  4
                     sink.link( "#" + suite.getPackageName() + suite.getName() );
 308  
 
 309  4
                     if ( suite.getNumberOfErrors() > 0 )
 310  
                     {
 311  4
                         sinkIcon( "error", sink );
 312  
                     }
 313  0
                     else if ( suite.getNumberOfFailures() > 0 )
 314  
                     {
 315  0
                         sinkIcon( "junit.framework", sink );
 316  
                     }
 317  0
                     else if ( suite.getNumberOfSkipped() > 0 )
 318  
                     {
 319  0
                         sinkIcon( "skipped", sink );
 320  
                     }
 321  
                     else
 322  
                     {
 323  0
                         sinkIcon( "success", sink );
 324  
                     }
 325  
 
 326  4
                     sink.link_();
 327  
 
 328  4
                     sink.tableCell_();
 329  
 
 330  4
                     sinkCellLink( sink, suite.getName(), "#" + suite.getPackageName() + suite.getName() );
 331  
 
 332  4
                     sinkCell( sink, Integer.toString( suite.getNumberOfTests() ) );
 333  
 
 334  4
                     sinkCell( sink, Integer.toString( suite.getNumberOfErrors() ) );
 335  
 
 336  4
                     sinkCell( sink, Integer.toString( suite.getNumberOfFailures() ) );
 337  
 
 338  4
                     sinkCell( sink, Integer.toString( suite.getNumberOfSkipped() ) );
 339  
 
 340  4
                     String percentage = report.computePercentage( suite.getNumberOfTests(), suite.getNumberOfErrors(),
 341  
                                                                   suite.getNumberOfFailures(), suite
 342  
                         .getNumberOfSkipped() );
 343  4
                     sinkCell( sink, percentage + "%" );
 344  
 
 345  4
                     sinkCell( sink, numberFormat.format( suite.getTimeElapsed() ) );
 346  
 
 347  4
                     sink.tableRow_();
 348  
                 }
 349  4
             }
 350  
 
 351  4
             sink.table_();
 352  
 
 353  4
             sink.section2_();
 354  4
         }
 355  
 
 356  4
         sinkLineBreak( sink );
 357  
 
 358  4
         sink.section1_();
 359  4
     }
 360  
 
 361  
     private void constructTestCasesSection( ResourceBundle bundle, Sink sink )
 362  
     {
 363  4
         NumberFormat numberFormat = report.getNumberFormat();
 364  
 
 365  4
         sink.section1();
 366  4
         sink.sectionTitle1();
 367  4
         sink.text( bundle.getString( "report.surefire.label.testcases" ) );
 368  4
         sink.sectionTitle1_();
 369  
 
 370  4
         sinkAnchor( sink, "Test_Cases" );
 371  
 
 372  4
         constructHotLinks( sink, bundle );
 373  
 
 374  4
         ListIterator suiteIterator = testSuites.listIterator();
 375  
 
 376  8
         while ( suiteIterator.hasNext() )
 377  
         {
 378  4
             ReportTestSuite suite = (ReportTestSuite) suiteIterator.next();
 379  
 
 380  4
             List testCases = suite.getTestCases();
 381  
 
 382  4
             if ( testCases != null && !testCases.isEmpty() )
 383  
             {
 384  4
                 ListIterator caseIterator = testCases.listIterator();
 385  
 
 386  4
                 sink.section2();
 387  4
                 sink.sectionTitle2();
 388  4
                 sink.text( suite.getName() );
 389  4
                 sink.sectionTitle2_();
 390  
 
 391  4
                 sinkAnchor( sink, suite.getPackageName() + suite.getName() );
 392  
 
 393  4
                 sink.table();
 394  
 
 395  36
                 while ( caseIterator.hasNext() )
 396  
                 {
 397  32
                     ReportTestCase testCase = (ReportTestCase) caseIterator.next();
 398  
 
 399  32
                     if ( testCase.getFailure() != null || showSuccess )
 400  
                     {
 401  26
                         sink.tableRow();
 402  
 
 403  26
                         sink.tableCell();
 404  
 
 405  26
                         Map failure = testCase.getFailure();
 406  
 
 407  26
                         if ( failure != null )
 408  
                         {
 409  8
                             sink.link( "#" + testCase.getFullName() );
 410  
 
 411  8
                             sinkIcon( (String) failure.get( "type" ), sink );
 412  
 
 413  8
                             sink.link_();
 414  
                         }
 415  
                         else
 416  
                         {
 417  18
                             sinkIcon( "success", sink );
 418  
                         }
 419  
 
 420  26
                         sink.tableCell_();
 421  
 
 422  26
                         if ( failure != null )
 423  
                         {
 424  8
                             sink.tableCell();
 425  
 
 426  8
                             sinkLink( sink, testCase.getName(), "#" + testCase.getFullName() );
 427  
 
 428  8
                             sink.rawText( "  <div class=\"detailToggle\" style=\"display:inline\">" );
 429  
 
 430  8
                             sink.link( "javascript:toggleDisplay('" + toHtmlId(testCase.getFullName()) + "');" );
 431  
 
 432  8
                             sink.rawText( "<span style=\"display: inline;\" " + "id=\"" + toHtmlId(testCase.getFullName())
 433  
                                 + "off\">+</span><span id=\"" + toHtmlId(testCase.getFullName()) + "on\" "
 434  
                                 + "style=\"display: none;\">-</span> " );
 435  8
                             sink.text( "[ Detail ]" );
 436  8
                             sink.link_();
 437  
 
 438  8
                             sink.rawText( "</div>" );
 439  
 
 440  8
                             sink.tableCell_();
 441  
                         }
 442  
                         else
 443  
                         {
 444  18
                             sinkCell( sink, testCase.getName() );
 445  
                         }
 446  
 
 447  26
                         sinkCell( sink, numberFormat.format( testCase.getTime() ) );
 448  
 
 449  26
                         sink.tableRow_();
 450  
 
 451  26
                         if ( failure != null )
 452  
                         {
 453  8
                             sink.tableRow();
 454  
 
 455  8
                             sinkCell( sink, "" );
 456  8
                             sinkCell( sink, (String) failure.get( "message" ) );
 457  8
                             sinkCell( sink, "" );
 458  8
                             sink.tableRow_();
 459  
 
 460  8
                             List detail = (List) failure.get( "detail" );
 461  8
                             if ( detail != null )
 462  
                             {
 463  
 
 464  8
                                 sink.tableRow();
 465  8
                                 sinkCell( sink, "" );
 466  
 
 467  8
                                 sink.tableCell();
 468  8
                                 sink.rawText(
 469  
                                     "  <div id=\"" + toHtmlId(testCase.getFullName()) + "error\" style=\"display:none;\">" );
 470  
 
 471  8
                                 Iterator it = detail.iterator();
 472  
 
 473  8
                                 sink.verbatim( true );
 474  44
                                 while ( it.hasNext() )
 475  
                                 {
 476  36
                                     sink.text( it.next().toString() );
 477  36
                                     sink.lineBreak();
 478  
                                 }
 479  8
                                 sink.verbatim_();
 480  
 
 481  8
                                 sink.rawText( "</div>" );
 482  8
                                 sink.tableCell_();
 483  
 
 484  8
                                 sinkCell( sink, "" );
 485  
 
 486  8
                                 sink.tableRow_();
 487  
                             }
 488  
                         }
 489  
                     }
 490  32
                 }
 491  
 
 492  4
                 sink.table_();
 493  
 
 494  4
                 sink.section2_();
 495  
             }
 496  4
         }
 497  
 
 498  4
         sinkLineBreak( sink );
 499  
 
 500  4
         sink.section1_();
 501  4
     }
 502  
 
 503  
 
 504  
     private String toHtmlId(String id){
 505  32
         return id.replace(".", "_");
 506  
     }
 507  
     private void constructFailureDetails( Sink sink, ResourceBundle bundle, List failureList )
 508  
     {
 509  4
         Iterator failIter = failureList.iterator();
 510  
 
 511  4
         if ( failIter != null )
 512  
         {
 513  4
             sink.section1();
 514  4
             sink.sectionTitle1();
 515  4
             sink.text( bundle.getString( "report.surefire.label.failuredetails" ) );
 516  4
             sink.sectionTitle1_();
 517  
 
 518  4
             sinkAnchor( sink, "Failure_Details" );
 519  
 
 520  4
             constructHotLinks( sink, bundle );
 521  
 
 522  4
             sinkLineBreak( sink );
 523  
 
 524  4
             sink.table();
 525  
 
 526  12
             while ( failIter.hasNext() )
 527  
             {
 528  8
                 ReportTestCase tCase = (ReportTestCase) failIter.next();
 529  
 
 530  8
                 Map failure = tCase.getFailure();
 531  
 
 532  8
                 sink.tableRow();
 533  
 
 534  8
                 sink.tableCell();
 535  
 
 536  8
                 String type = (String) failure.get( "type" );
 537  8
                 sinkIcon( type, sink );
 538  
 
 539  8
                 sink.tableCell_();
 540  
 
 541  8
                 sinkCellAnchor( sink, tCase.getName(), tCase.getFullName() );
 542  
 
 543  8
                 sink.tableRow_();
 544  
 
 545  8
                 String message = (String) failure.get( "message" );
 546  
 
 547  8
                 sink.tableRow();
 548  
 
 549  8
                 sinkCell( sink, "" );
 550  
 
 551  8
                 StringBuffer sb = new StringBuffer();
 552  8
                 sb.append( type );
 553  
 
 554  8
                 if ( message != null )
 555  
                 {
 556  8
                     sb.append( ": " );
 557  8
                     sb.append( message );
 558  
                 }
 559  
 
 560  8
                 sinkCell( sink, sb.toString() );
 561  
 
 562  8
                 sink.tableRow_();
 563  
 
 564  8
                 List detail = (List) failure.get( "detail" );
 565  8
                 if ( detail != null )
 566  
                 {
 567  8
                     Iterator it = detail.iterator();
 568  
 
 569  8
                     boolean firstLine = true;
 570  
 
 571  8
                     String techMessage = "";
 572  44
                     while ( it.hasNext() )
 573  
                     {
 574  36
                         techMessage = it.next().toString();
 575  36
                         if ( firstLine )
 576  
                         {
 577  8
                             firstLine = false;
 578  
                         }
 579  
                         else
 580  
                         {
 581  28
                             sink.text( "    " );
 582  
                         }
 583  
                     }
 584  
 
 585  8
                     sink.tableRow();
 586  
 
 587  8
                     sinkCell( sink, "" );
 588  
 
 589  8
                     sink.tableCell();
 590  8
                     sink.rawText( "  <div id=\"" + tCase.getName() + "error\" >" );
 591  
 
 592  8
                     if ( xrefLocation != null )
 593  
                     {
 594  4
                         String path = tCase.getFullClassName().replace( '.', '/' );
 595  
 
 596  4
                         sink.link( xrefLocation + "/" + path + ".html#" +
 597  
                             getErrorLineNumber( tCase.getFullName(), techMessage ) );
 598  
                     }
 599  8
                     sink.text(
 600  
                         tCase.getFullClassName() + ":" + getErrorLineNumber( tCase.getFullName(), techMessage ) );
 601  
 
 602  8
                     if ( xrefLocation != null )
 603  
                     {
 604  4
                         sink.link_();
 605  
                     }
 606  8
                     sink.rawText( "</div>" );
 607  
 
 608  8
                     sink.tableCell_();
 609  
 
 610  8
                     sink.tableRow_();
 611  
                 }
 612  8
             }
 613  
 
 614  4
             sink.table_();
 615  
         }
 616  
 
 617  4
         sinkLineBreak( sink );
 618  
 
 619  4
         sink.section1_();
 620  4
     }
 621  
 
 622  
     private String getErrorLineNumber( String className, String source )
 623  
     {
 624  12
         StringTokenizer tokenizer = new StringTokenizer( source );
 625  
 
 626  12
         String lineNo = "";
 627  
 
 628  24
         while ( tokenizer.hasMoreTokens() )
 629  
         {
 630  24
             String token = tokenizer.nextToken();
 631  24
             if ( token.startsWith( className ) )
 632  
             {
 633  12
                 int idx = token.indexOf( ":" );
 634  12
                 lineNo = token.substring( idx + 1, token.indexOf( ")" ) );
 635  12
                 break;
 636  
             }
 637  12
         }
 638  12
         return lineNo;
 639  
     }
 640  
 
 641  
     private void constructHotLinks( Sink sink, ResourceBundle bundle )
 642  
     {
 643  16
         if ( !testSuites.isEmpty() )
 644  
         {
 645  16
             sink.paragraph();
 646  
 
 647  16
             sink.text( "[" );
 648  16
             sinkLink( sink, bundle.getString( "report.surefire.label.summary" ), "#Summary" );
 649  16
             sink.text( "]" );
 650  
 
 651  16
             sink.text( " [" );
 652  16
             sinkLink( sink, bundle.getString( "report.surefire.label.packagelist" ), "#Package_List" );
 653  16
             sink.text( "]" );
 654  
 
 655  16
             sink.text( " [" );
 656  16
             sinkLink( sink, bundle.getString( "report.surefire.label.testcases" ), "#Test_Cases" );
 657  16
             sink.text( "]" );
 658  
 
 659  16
             sink.paragraph_();
 660  
         }
 661  16
     }
 662  
 
 663  
     private void sinkLineBreak( Sink sink )
 664  
     {
 665  28
         sink.lineBreak();
 666  28
     }
 667  
 
 668  
     private void sinkIcon( String type, Sink sink )
 669  
     {
 670  38
         sink.figure();
 671  
 
 672  38
         if ( type.startsWith( "junit.framework" ) || "skipped".equals( type ) )
 673  
         {
 674  8
             sink.figureGraphics( "images/icon_warning_sml.gif" );
 675  
         }
 676  30
         else if ( type.startsWith( "success" ) )
 677  
         {
 678  18
             sink.figureGraphics( "images/icon_success_sml.gif" );
 679  
         }
 680  
         else
 681  
         {
 682  12
             sink.figureGraphics( "images/icon_error_sml.gif" );
 683  
         }
 684  
 
 685  38
         sink.figure_();
 686  38
     }
 687  
 
 688  
     private void sinkHeader( Sink sink, String header )
 689  
     {
 690  84
         sink.tableHeaderCell();
 691  84
         sink.text( header );
 692  84
         sink.tableHeaderCell_();
 693  84
     }
 694  
 
 695  
     private void sinkCell( Sink sink, String text )
 696  
     {
 697  180
         sink.tableCell();
 698  180
         sink.text( text );
 699  180
         sink.tableCell_();
 700  180
     }
 701  
 
 702  
     private void sinkLink( Sink sink, String text, String link )
 703  
     {
 704  64
         sink.link( link );
 705  64
         sink.text( text );
 706  64
         sink.link_();
 707  64
     }
 708  
 
 709  
     private void sinkCellLink( Sink sink, String text, String link )
 710  
     {
 711  8
         sink.tableCell();
 712  8
         sinkLink( sink, text, link );
 713  8
         sink.tableCell_();
 714  8
     }
 715  
 
 716  
     private void sinkCellAnchor( Sink sink, String text, String anchor )
 717  
     {
 718  8
         sink.tableCell();
 719  8
         sinkAnchor( sink, anchor );
 720  8
         sink.text( text );
 721  8
         sink.tableCell_();
 722  8
     }
 723  
 
 724  
     private void sinkAnchor( Sink sink, String anchor )
 725  
     {
 726  32
         sink.anchor( anchor );
 727  32
         sink.anchor_();
 728  32
     }
 729  
 }