1 package org.apache.maven.reporting; 2 3 18 19 import org.apache.commons.validator.EmailValidator; 20 import org.apache.commons.validator.UrlValidator; 21 import org.apache.maven.doxia.sink.Sink; 22 import org.codehaus.plexus.util.StringUtils; 23 24 import java.util.Collections ; 25 import java.util.Iterator ; 26 import java.util.LinkedHashMap ; 27 import java.util.Map ; 28 import java.util.Properties ; 29 30 39 public abstract class AbstractMavenReportRenderer 40 implements MavenReportRenderer 41 { 42 protected Sink sink; 43 44 private int section; 45 46 public AbstractMavenReportRenderer( Sink sink ) 47 { 48 this.sink = sink; 49 } 50 51 public void render() 52 { 53 sink.head(); 54 55 sink.title(); 56 57 text( getTitle() ); 58 59 sink.title_(); 60 61 sink.head_(); 62 63 sink.body(); 64 65 renderBody(); 66 67 sink.body_(); 68 69 sink.flush(); 70 71 sink.close(); 72 } 73 74 protected void startTable() 75 { 76 sink.table(); 77 } 78 79 protected void endTable() 80 { 81 sink.table_(); 82 } 83 84 protected void startSection( String name ) 85 { 86 section = section + 1; 87 88 switch ( section ) 89 { 90 case 1: 91 sink.section1(); 92 sink.sectionTitle1(); 93 break; 94 case 2: 95 sink.section2(); 96 sink.sectionTitle2(); 97 break; 98 case 3: 99 sink.section3(); 100 sink.sectionTitle3(); 101 break; 102 case 4: 103 sink.section4(); 104 sink.sectionTitle4(); 105 break; 106 case 5: 107 sink.section5(); 108 sink.sectionTitle5(); 109 break; 110 111 default: 112 break; 114 } 115 116 text( name ); 117 118 switch ( section ) 119 { 120 case 1: 121 sink.sectionTitle1_(); 122 break; 123 case 2: 124 sink.sectionTitle2_(); 125 break; 126 case 3: 127 sink.sectionTitle3_(); 128 break; 129 case 4: 130 sink.sectionTitle4_(); 131 break; 132 case 5: 133 sink.sectionTitle5_(); 134 break; 135 136 default: 137 break; 139 } 140 } 141 142 protected void endSection() 143 { 144 switch ( section ) 145 { 146 case 1: 147 sink.section1_(); 148 break; 149 case 2: 150 sink.section2_(); 151 break; 152 case 3: 153 sink.section3_(); 154 break; 155 case 4: 156 sink.section4_(); 157 break; 158 case 5: 159 sink.section5_(); 160 break; 161 162 default: 163 break; 165 } 166 167 section = section - 1; 168 169 if ( section < 0 ) 170 { 171 throw new IllegalStateException ( "Too many closing sections" ); 172 } 173 } 174 175 protected void tableHeaderCell( String text ) 176 { 177 sink.tableHeaderCell(); 178 179 text( text ); 180 181 sink.tableHeaderCell_(); 182 } 183 184 191 protected void tableCell( String text ) 192 { 193 tableCell( text, false ); 194 } 195 196 203 protected void tableCell( String text, boolean asHtml ) 204 { 205 sink.tableCell(); 206 207 if ( asHtml ) 208 { 209 sink.rawText( text ); 210 } 211 else 212 { 213 linkPatternedText( text ); 214 } 215 216 sink.tableCell_(); 217 } 218 219 protected void tableRow( String [] content ) 220 { 221 sink.tableRow(); 222 223 for ( int i = 0; i < content.length; i++ ) 224 { 225 tableCell( content[i] ); 226 } 227 228 sink.tableRow_(); 229 } 230 231 protected void tableHeader( String [] content ) 232 { 233 sink.tableRow(); 234 235 for ( int i = 0; i < content.length; i++ ) 236 { 237 tableHeaderCell( content[i] ); 238 } 239 240 sink.tableRow_(); 241 } 242 243 protected void tableCaption( String caption ) 244 { 245 sink.tableCaption(); 246 247 text( caption ); 248 249 sink.tableCaption_(); 250 } 251 252 protected void paragraph( String paragraph ) 253 { 254 sink.paragraph(); 255 256 text( paragraph ); 257 258 sink.paragraph_(); 259 } 260 261 protected void link( String href, String name ) 262 { 263 sink.link( href ); 264 265 text( name ); 266 267 sink.link_(); 268 } 269 270 276 protected void text( String text ) 277 { 278 if ( text == null || text.length() == 0 ) { 280 sink.text( "-" ); 281 } 282 else 283 { 284 sink.text( text ); 285 } 286 } 287 288 294 protected void verbatimText( String text ) 295 { 296 sink.verbatim( true ); 297 298 text( text ); 299 300 sink.verbatim_(); 301 } 302 303 310 protected void verbatimLink( String text, String href ) 311 { 312 if ( StringUtils.isEmpty( href ) ) 313 { 314 verbatimText( text ); 315 } 316 else 317 { 318 sink.verbatim( true ); 319 320 link( href, text ); 321 322 sink.verbatim_(); 323 } 324 } 325 326 331 protected void javaScript( String jsCode ) 332 { 333 sink.rawText( "<script type=\"text/javascript\">\n" + jsCode + "</script>" ); 334 } 335 336 345 public void linkPatternedText( String text ) 346 { 347 if ( StringUtils.isEmpty( text ) ) 348 { 349 text( text ); 350 } 351 else 352 { 353 Map segments = applyPattern( text ); 354 355 if ( segments == null ) 356 { 357 text( text ); 358 } 359 else 360 { 361 for ( Iterator it = segments.entrySet().iterator(); it.hasNext(); ) 362 { 363 Map.Entry entry = (Map.Entry ) it.next(); 364 365 String name = (String ) entry.getKey(); 366 String href = (String ) entry.getValue(); 367 368 if ( href == null ) 369 { 370 text( name ); 371 } 372 else 373 { 374 if ( getValidHref( href ) != null ) 375 { 376 link( getValidHref( href ), name ); 377 } 378 else 379 { 380 text( href ); 381 } 382 } 383 } 384 } 385 } 386 } 387 388 398 protected static String createLinkPatternedText( String text, String href ) 399 { 400 if ( text == null ) 401 { 402 return text; 403 } 404 405 if ( href == null ) 406 { 407 return text; 408 } 409 410 StringBuffer sb = new StringBuffer (); 411 sb.append( "{" ).append( text ).append( ", " ).append( href ).append( "}" ); 412 413 return sb.toString(); 414 } 415 416 422 protected static String propertiesToString( Properties props ) 423 { 424 StringBuffer sb = new StringBuffer (); 425 426 if ( props == null || props.isEmpty() ) 427 { 428 return sb.toString(); 429 } 430 431 for ( Iterator i = props.keySet().iterator(); i.hasNext(); ) 432 { 433 String key = (String ) i.next(); 434 sb.append( key ).append( "=" ).append( props.get( key ) ); 435 if ( i.hasNext() ) 436 { 437 sb.append( ", " ); 438 } 439 } 440 441 return sb.toString(); 442 } 443 444 452 private static String getValidHref( String href ) 453 { 454 href = href.trim(); 455 456 String [] schemes = {"http", "https"}; 457 UrlValidator urlValidator = new UrlValidator( schemes ); 458 459 if ( ( EmailValidator.getInstance().isValid( href ) ) || 460 ( ( href.indexOf( "?" ) != -1 ) && 461 ( EmailValidator.getInstance().isValid( href.substring( 0, href.indexOf( "?" ) ) ) ) ) ) 462 { 463 return "mailto:" + href; 464 } 465 else if ( href.toLowerCase().startsWith( "mailto:" ) ) 466 { 467 return href; 468 } 469 else if ( urlValidator.isValid( href ) ) 470 { 471 return href; 472 } 473 else 474 { 475 String hrefTmp; 478 if ( !href.endsWith( "/" ) ) 479 { 480 hrefTmp = href + "/index.html"; 481 } 482 else 483 { 484 hrefTmp = href + "index.html"; 485 } 486 487 if ( urlValidator.isValid( hrefTmp ) ) 488 { 489 return href; 490 } 491 492 if ( href.startsWith( "./" ) ) 493 { 494 if ( href.length() > 2 ) 495 { 496 return href.substring(2, href.length() ); 497 } 498 else 499 { 500 return "."; 501 } 502 } 503 504 return null; 505 } 506 } 507 508 515 private static Map applyPattern( String text ) 516 { 517 if ( StringUtils.isEmpty( text ) ) 518 { 519 return null; 520 } 521 522 Map segments = new LinkedHashMap (); 525 526 if ( text.indexOf( "${" ) != -1 ) 528 { 529 int lastComma = text.lastIndexOf( "," ); 530 int lastSemi = text.lastIndexOf( "}" ); 531 if ( lastComma != -1 && lastSemi != -1 ) 532 { 533 segments.put( text.substring( lastComma + 1, lastSemi ).trim(), null ); 534 } 535 else 536 { 537 segments.put( text, null ); 538 } 539 540 return segments; 541 } 542 543 boolean inQuote = false; 544 int braceStack = 0; 545 int lastOffset = 0; 546 547 for ( int i = 0; i < text.length(); i++ ) 548 { 549 char ch = text.charAt( i ); 550 551 if ( ch == '\'' && !inQuote ) 552 { 553 if ( i + 1 < text.length() && text.charAt( i + 1 ) == '\'' ) 555 { 556 i++; 557 } 558 else 559 { 560 inQuote = true; 561 } 562 } 563 else 564 { 565 switch ( ch ) 566 { 567 case '{': 568 if ( !inQuote ) 569 { 570 if ( braceStack == 0 ) 571 { 572 if ( i != 0 ) { 574 segments.put( text.substring( lastOffset, i ), null ); 575 } 576 lastOffset = i + 1; 577 braceStack++; 578 } 579 } 580 break; 581 case '}': 582 if ( !inQuote ) 583 { 584 braceStack--; 585 if ( braceStack == 0 ) 586 { 587 String subString = text.substring( lastOffset, i ); 588 lastOffset = i + 1; 589 590 int lastComma = subString.lastIndexOf( "," ); 591 if ( lastComma != -1 ) 592 { 593 segments.put( subString.substring( 0, lastComma ).trim(), 594 subString.substring( lastComma + 1 ).trim() ); 595 } 596 else 597 { 598 segments.put( subString.substring( 0, lastComma ).trim(), null ); 599 } 600 } 601 } 602 break; 603 case '\'': 604 inQuote = false; 605 break; 606 default: 607 break; 608 } 609 } 610 } 611 612 if ( !StringUtils.isEmpty( text.substring( lastOffset, text.length() ) ) ) 613 { 614 segments.put( text.substring( lastOffset, text.length() ), null ); 615 } 616 617 if ( braceStack != 0 ) 618 { 619 throw new IllegalArgumentException ( "Unmatched braces in the pattern." ); 620 } 621 622 return Collections.unmodifiableMap( segments ); 623 } 624 625 public abstract String getTitle(); 626 627 protected abstract void renderBody(); 628 } 629 | Popular Tags |