001package org.apache.maven.doxia.sink; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.io.ByteArrayOutputStream; 023import java.io.File; 024import java.io.FileOutputStream; 025import java.io.IOException; 026import java.io.OutputStream; 027import java.util.ArrayList; 028import java.util.List; 029 030import org.apache.maven.doxia.logging.Log; 031 032/** 033 * The RandomAccessSink provides the ability to create a {@link Sink} with hooks. 034 * A page can be prepared by first creating its structure and specifying the positions of these hooks. 035 * After specifying the structure, the page can be filled with content from one or more models. 036 * These hooks can prevent you to have to loop over the model multiple times to build the page as desired. 037 * 038 * @author Robert Scholte 039 * @since 1.3 040 */ 041public class RandomAccessSink 042 implements Sink 043{ 044 private SinkFactory sinkFactory; 045 046 private String encoding; 047 048 private OutputStream coreOutputStream; 049 050 private Sink coreSink; 051 052 private List<Sink> sinks = new ArrayList<Sink>(); 053 054 private List<ByteArrayOutputStream> outputStreams = new ArrayList<ByteArrayOutputStream>(); 055 056 private Sink currentSink; 057 058 public RandomAccessSink( SinkFactory sinkFactory, OutputStream stream ) 059 throws IOException 060 { 061 this.sinkFactory = sinkFactory; 062 this.coreOutputStream = stream; 063 this.coreSink = this.currentSink = sinkFactory.createSink( stream ); 064 } 065 066 public RandomAccessSink( SinkFactory sinkFactory, OutputStream stream, String encoding ) 067 throws IOException 068 { 069 this.sinkFactory = sinkFactory; 070 this.coreOutputStream = stream; 071 this.encoding = encoding; 072 this.coreSink = this.currentSink = sinkFactory.createSink( stream, encoding ); 073 } 074 075 public RandomAccessSink( SinkFactory sinkFactory, File outputDirectory, String outputName ) 076 throws IOException 077 { 078 this.sinkFactory = sinkFactory; 079 this.coreOutputStream = new FileOutputStream( new File( outputDirectory, outputName ) ); 080 this.coreSink = this.currentSink = sinkFactory.createSink( coreOutputStream ); 081 } 082 083 public RandomAccessSink( SinkFactory sinkFactory, File outputDirectory, String outputName, String encoding ) 084 throws IOException 085 { 086 this.sinkFactory = sinkFactory; 087 this.coreOutputStream = new FileOutputStream( new File( outputDirectory, outputName ) ); 088 this.encoding = encoding; 089 this.coreSink = this.currentSink = sinkFactory.createSink( coreOutputStream, encoding ); 090 } 091 092 /** 093 * By calling this method a sink reference is added at the current position. You can write to both the new sink 094 * reference and the original sink. After flushing all sinks will be flushed in the right order. 095 * 096 * @return a subsink reference you can write to 097 */ 098 public Sink addSinkHook() 099 { 100 Sink subSink = null; 101 try 102 { 103 ByteArrayOutputStream subOut = new ByteArrayOutputStream(); 104 ByteArrayOutputStream newOut = new ByteArrayOutputStream(); 105 106 outputStreams.add( subOut ); 107 outputStreams.add( newOut ); 108 109 if ( encoding != null ) 110 { 111 subSink = sinkFactory.createSink( subOut, encoding ); 112 currentSink = sinkFactory.createSink( newOut, encoding ); 113 } 114 else 115 { 116 subSink = sinkFactory.createSink( subOut ); 117 currentSink = sinkFactory.createSink( newOut ); 118 } 119 sinks.add( subSink ); 120 sinks.add( currentSink ); 121 } 122 catch ( IOException e ) 123 { 124 // IOException can only be caused by our own ByteArrayOutputStream 125 } 126 return subSink; 127 } 128 129 /** {@inheritDoc} */ 130 public void anchor( String name ) 131 { 132 currentSink.anchor( name ); 133 } 134 135 /** {@inheritDoc} */ 136 public void anchor( String name, SinkEventAttributes attributes ) 137 { 138 currentSink.anchor( name, attributes ); 139 } 140 141 /** {@inheritDoc} */ 142 public void anchor_() 143 { 144 currentSink.anchor_(); 145 } 146 147 /** {@inheritDoc} */ 148 public void author() 149 { 150 currentSink.author(); 151 } 152 153 /** {@inheritDoc} */ 154 public void author( SinkEventAttributes attributes ) 155 { 156 currentSink.author( attributes ); 157 } 158 159 /** {@inheritDoc} */ 160 public void author_() 161 { 162 currentSink.author_(); 163 } 164 165 /** {@inheritDoc} */ 166 public void body() 167 { 168 currentSink.body(); 169 } 170 171 /** {@inheritDoc} */ 172 public void body( SinkEventAttributes attributes ) 173 { 174 currentSink.body( attributes ); 175 } 176 177 /** {@inheritDoc} */ 178 public void body_() 179 { 180 currentSink.body_(); 181 } 182 183 /** {@inheritDoc} */ 184 public void bold() 185 { 186 currentSink.bold(); 187 } 188 189 /** {@inheritDoc} */ 190 public void bold_() 191 { 192 currentSink.bold_(); 193 } 194 195 /** 196 * Close all sinks 197 */ 198 public void close() 199 { 200 for ( Sink sink : sinks ) 201 { 202 // sink is responsible for closing it's stream 203 sink.close(); 204 } 205 coreSink.close(); 206 } 207 208 /** {@inheritDoc} */ 209 public void comment( String comment ) 210 { 211 currentSink.comment( comment ); 212 } 213 214 /** {@inheritDoc} */ 215 public void date() 216 { 217 currentSink.date(); 218 } 219 220 /** {@inheritDoc} */ 221 public void date( SinkEventAttributes attributes ) 222 { 223 currentSink.date( attributes ); 224 } 225 226 /** {@inheritDoc} */ 227 public void date_() 228 { 229 currentSink.date_(); 230 } 231 232 /** {@inheritDoc} */ 233 public void definedTerm() 234 { 235 currentSink.definedTerm(); 236 } 237 238 /** {@inheritDoc} */ 239 public void definedTerm( SinkEventAttributes attributes ) 240 { 241 currentSink.definedTerm( attributes ); 242 } 243 244 /** {@inheritDoc} */ 245 public void definedTerm_() 246 { 247 currentSink.definedTerm_(); 248 } 249 250 /** {@inheritDoc} */ 251 public void definition() 252 { 253 currentSink.definition(); 254 } 255 256 /** {@inheritDoc} */ 257 public void definition( SinkEventAttributes attributes ) 258 { 259 currentSink.definition( attributes ); 260 } 261 262 /** {@inheritDoc} */ 263 public void definitionList() 264 { 265 currentSink.definitionList(); 266 } 267 268 /** {@inheritDoc} */ 269 public void definitionList( SinkEventAttributes attributes ) 270 { 271 currentSink.definitionList( attributes ); 272 } 273 274 /** {@inheritDoc} */ 275 public void definitionListItem() 276 { 277 currentSink.definitionListItem(); 278 } 279 280 /** {@inheritDoc} */ 281 public void definitionListItem( SinkEventAttributes attributes ) 282 { 283 currentSink.definitionListItem( attributes ); 284 } 285 286 /** {@inheritDoc} */ 287 public void definitionListItem_() 288 { 289 currentSink.definitionListItem_(); 290 } 291 292 /** {@inheritDoc} */ 293 public void definitionList_() 294 { 295 currentSink.definitionList_(); 296 } 297 298 /** {@inheritDoc} */ 299 public void definition_() 300 { 301 currentSink.definition_(); 302 } 303 304 /** {@inheritDoc} */ 305 public void figure() 306 { 307 currentSink.figure(); 308 } 309 310 /** {@inheritDoc} */ 311 public void figure( SinkEventAttributes attributes ) 312 { 313 currentSink.figure( attributes ); 314 } 315 316 /** {@inheritDoc} */ 317 public void figureCaption() 318 { 319 currentSink.figureCaption(); 320 } 321 322 /** {@inheritDoc} */ 323 public void figureCaption( SinkEventAttributes attributes ) 324 { 325 currentSink.figureCaption( attributes ); 326 } 327 328 /** {@inheritDoc} */ 329 public void figureCaption_() 330 { 331 currentSink.figureCaption_(); 332 } 333 334 /** {@inheritDoc} */ 335 public void figureGraphics( String name ) 336 { 337 currentSink.figureGraphics( name ); 338 } 339 340 /** {@inheritDoc} */ 341 public void figureGraphics( String src, SinkEventAttributes attributes ) 342 { 343 currentSink.figureGraphics( src, attributes ); 344 } 345 346 /** {@inheritDoc} */ 347 public void figure_() 348 { 349 currentSink.figure_(); 350 } 351 352 /** 353 * Flush all sinks 354 */ 355 public void flush() 356 { 357 for ( int i = 0; i < sinks.size(); i++ ) 358 { 359 // first flush to get complete buffer 360 // sink is responsible for flushing it's stream 361 Sink sink = sinks.get( i ); 362 sink.flush(); 363 364 ByteArrayOutputStream stream = outputStreams.get( i ); 365 try 366 { 367 coreOutputStream.write( stream.toByteArray() ); 368 } 369 catch ( IOException e ) 370 { 371 // @todo 372 } 373 } 374 coreSink.flush(); 375 } 376 377 /** {@inheritDoc} */ 378 public void head() 379 { 380 currentSink.head(); 381 } 382 383 /** {@inheritDoc} */ 384 public void head( SinkEventAttributes attributes ) 385 { 386 currentSink.head( attributes ); 387 } 388 389 /** {@inheritDoc} */ 390 public void head_() 391 { 392 currentSink.head_(); 393 } 394 395 /** {@inheritDoc} */ 396 public void horizontalRule() 397 { 398 currentSink.horizontalRule(); 399 } 400 401 /** {@inheritDoc} */ 402 public void horizontalRule( SinkEventAttributes attributes ) 403 { 404 currentSink.horizontalRule( attributes ); 405 } 406 407 /** {@inheritDoc} */ 408 public void italic() 409 { 410 currentSink.italic(); 411 } 412 413 /** {@inheritDoc} */ 414 public void italic_() 415 { 416 currentSink.italic_(); 417 } 418 419 /** {@inheritDoc} */ 420 public void lineBreak() 421 { 422 currentSink.lineBreak(); 423 } 424 425 /** {@inheritDoc} */ 426 public void lineBreak( SinkEventAttributes attributes ) 427 { 428 currentSink.lineBreak( attributes ); 429 } 430 431 /** {@inheritDoc} */ 432 public void link( String name ) 433 { 434 currentSink.link( name ); 435 } 436 437 /** {@inheritDoc} */ 438 public void link( String name, SinkEventAttributes attributes ) 439 { 440 currentSink.link( name, attributes ); 441 } 442 443 /** {@inheritDoc} */ 444 public void link_() 445 { 446 currentSink.link_(); 447 } 448 449 /** {@inheritDoc} */ 450 public void list() 451 { 452 currentSink.list(); 453 } 454 455 /** {@inheritDoc} */ 456 public void list( SinkEventAttributes attributes ) 457 { 458 currentSink.list( attributes ); 459 } 460 461 /** {@inheritDoc} */ 462 public void listItem() 463 { 464 currentSink.listItem(); 465 } 466 467 /** {@inheritDoc} */ 468 public void listItem( SinkEventAttributes attributes ) 469 { 470 currentSink.listItem( attributes ); 471 } 472 473 /** {@inheritDoc} */ 474 public void listItem_() 475 { 476 currentSink.listItem_(); 477 } 478 479 /** {@inheritDoc} */ 480 public void list_() 481 { 482 currentSink.list_(); 483 } 484 485 /** {@inheritDoc} */ 486 public void monospaced() 487 { 488 currentSink.monospaced(); 489 } 490 491 /** {@inheritDoc} */ 492 public void monospaced_() 493 { 494 currentSink.monospaced_(); 495 } 496 497 /** {@inheritDoc} */ 498 public void nonBreakingSpace() 499 { 500 currentSink.nonBreakingSpace(); 501 } 502 503 /** {@inheritDoc} */ 504 public void numberedList( int numbering ) 505 { 506 currentSink.numberedList( numbering ); 507 } 508 509 /** {@inheritDoc} */ 510 public void numberedList( int numbering, SinkEventAttributes attributes ) 511 { 512 currentSink.numberedList( numbering, attributes ); 513 } 514 515 /** {@inheritDoc} */ 516 public void numberedListItem() 517 { 518 currentSink.numberedListItem(); 519 } 520 521 /** {@inheritDoc} */ 522 public void numberedListItem( SinkEventAttributes attributes ) 523 { 524 currentSink.numberedListItem( attributes ); 525 } 526 527 /** {@inheritDoc} */ 528 public void numberedListItem_() 529 { 530 currentSink.numberedListItem_(); 531 } 532 533 /** {@inheritDoc} */ 534 public void numberedList_() 535 { 536 currentSink.numberedList_(); 537 } 538 539 /** {@inheritDoc} */ 540 public void pageBreak() 541 { 542 currentSink.pageBreak(); 543 } 544 545 /** {@inheritDoc} */ 546 public void paragraph() 547 { 548 currentSink.paragraph(); 549 } 550 551 /** {@inheritDoc} */ 552 public void paragraph( SinkEventAttributes attributes ) 553 { 554 currentSink.paragraph( attributes ); 555 } 556 557 /** {@inheritDoc} */ 558 public void paragraph_() 559 { 560 currentSink.paragraph_(); 561 } 562 563 /** {@inheritDoc} */ 564 public void rawText( String text ) 565 { 566 currentSink.rawText( text ); 567 } 568 569 /** {@inheritDoc} */ 570 public void section( int level, SinkEventAttributes attributes ) 571 { 572 currentSink.section( level, attributes ); 573 } 574 575 /** {@inheritDoc} */ 576 public void section1() 577 { 578 currentSink.section1(); 579 } 580 581 /** {@inheritDoc} */ 582 public void section1_() 583 { 584 currentSink.section1_(); 585 } 586 587 /** {@inheritDoc} */ 588 public void section2() 589 { 590 currentSink.section2(); 591 } 592 593 /** {@inheritDoc} */ 594 public void section2_() 595 { 596 currentSink.section2_(); 597 } 598 599 /** {@inheritDoc} */ 600 public void section3() 601 { 602 currentSink.section3(); 603 } 604 605 /** {@inheritDoc} */ 606 public void section3_() 607 { 608 currentSink.section3_(); 609 } 610 611 /** {@inheritDoc} */ 612 public void section4() 613 { 614 currentSink.section4(); 615 } 616 617 /** {@inheritDoc} */ 618 public void section4_() 619 { 620 currentSink.section4_(); 621 } 622 623 /** {@inheritDoc} */ 624 public void section5() 625 { 626 currentSink.section5(); 627 } 628 629 /** {@inheritDoc} */ 630 public void section5_() 631 { 632 currentSink.section5_(); 633 } 634 635 /** {@inheritDoc} */ 636 public void sectionTitle() 637 { 638 currentSink.sectionTitle(); 639 } 640 641 /** {@inheritDoc} */ 642 public void sectionTitle( int level, SinkEventAttributes attributes ) 643 { 644 currentSink.sectionTitle( level, attributes ); 645 } 646 647 /** {@inheritDoc} */ 648 public void sectionTitle1() 649 { 650 currentSink.sectionTitle1(); 651 } 652 653 /** {@inheritDoc} */ 654 public void sectionTitle1_() 655 { 656 currentSink.sectionTitle1_(); 657 } 658 659 /** {@inheritDoc} */ 660 public void sectionTitle2() 661 { 662 currentSink.sectionTitle2(); 663 } 664 665 /** {@inheritDoc} */ 666 public void sectionTitle2_() 667 { 668 currentSink.sectionTitle2_(); 669 } 670 671 /** {@inheritDoc} */ 672 public void sectionTitle3() 673 { 674 currentSink.sectionTitle3(); 675 } 676 677 /** {@inheritDoc} */ 678 public void sectionTitle3_() 679 { 680 currentSink.sectionTitle3_(); 681 } 682 683 /** {@inheritDoc} */ 684 public void sectionTitle4() 685 { 686 currentSink.sectionTitle4(); 687 } 688 689 /** {@inheritDoc} */ 690 public void sectionTitle4_() 691 { 692 currentSink.sectionTitle4_(); 693 } 694 695 /** {@inheritDoc} */ 696 public void sectionTitle5() 697 { 698 currentSink.sectionTitle5(); 699 } 700 701 /** {@inheritDoc} */ 702 public void sectionTitle5_() 703 { 704 currentSink.sectionTitle5_(); 705 } 706 707 /** {@inheritDoc} */ 708 public void sectionTitle_() 709 { 710 currentSink.sectionTitle_(); 711 } 712 713 /** {@inheritDoc} */ 714 public void sectionTitle_( int level ) 715 { 716 currentSink.sectionTitle_( level ); 717 } 718 719 /** {@inheritDoc} */ 720 public void section_( int level ) 721 { 722 currentSink.section_( level ); 723 } 724 725 /** {@inheritDoc} */ 726 public void table() 727 { 728 currentSink.table(); 729 } 730 731 /** {@inheritDoc} */ 732 public void table( SinkEventAttributes attributes ) 733 { 734 currentSink.table( attributes ); 735 } 736 737 /** {@inheritDoc} */ 738 public void tableCaption() 739 { 740 currentSink.tableCaption(); 741 } 742 743 /** {@inheritDoc} */ 744 public void tableCaption( SinkEventAttributes attributes ) 745 { 746 currentSink.tableCaption( attributes ); 747 } 748 749 /** {@inheritDoc} */ 750 public void tableCaption_() 751 { 752 currentSink.tableCaption_(); 753 } 754 755 /** {@inheritDoc} */ 756 public void tableCell() 757 { 758 currentSink.tableCell(); 759 } 760 761 /** {@inheritDoc} */ 762 public void tableCell( String width ) 763 { 764 currentSink.tableCell( width ); 765 } 766 767 /** {@inheritDoc} */ 768 public void tableCell( SinkEventAttributes attributes ) 769 { 770 currentSink.tableCell( attributes ); 771 } 772 773 /** {@inheritDoc} */ 774 public void tableCell_() 775 { 776 currentSink.tableCell_(); 777 } 778 779 /** {@inheritDoc} */ 780 public void tableHeaderCell() 781 { 782 currentSink.tableHeaderCell(); 783 } 784 785 /** {@inheritDoc} */ 786 public void tableHeaderCell( String width ) 787 { 788 currentSink.tableHeaderCell( width ); 789 } 790 791 /** {@inheritDoc} */ 792 public void tableHeaderCell( SinkEventAttributes attributes ) 793 { 794 currentSink.tableHeaderCell( attributes ); 795 } 796 797 /** {@inheritDoc} */ 798 public void tableHeaderCell_() 799 { 800 currentSink.tableHeaderCell_(); 801 } 802 803 /** {@inheritDoc} */ 804 public void tableRow() 805 { 806 currentSink.tableRow(); 807 } 808 809 /** {@inheritDoc} */ 810 public void tableRow( SinkEventAttributes attributes ) 811 { 812 currentSink.tableRow( attributes ); 813 } 814 815 /** {@inheritDoc} */ 816 public void tableRow_() 817 { 818 currentSink.tableRow_(); 819 } 820 821 /** {@inheritDoc} */ 822 public void tableRows( int[] justification, boolean grid ) 823 { 824 currentSink.tableRows( justification, grid ); 825 } 826 827 /** {@inheritDoc} */ 828 public void tableRows_() 829 { 830 currentSink.tableRows_(); 831 } 832 833 /** {@inheritDoc} */ 834 public void table_() 835 { 836 currentSink.table_(); 837 } 838 839 /** {@inheritDoc} */ 840 public void text( String text ) 841 { 842 currentSink.text( text ); 843 } 844 845 /** {@inheritDoc} */ 846 public void text( String text, SinkEventAttributes attributes ) 847 { 848 currentSink.text( text, attributes ); 849 } 850 851 /** {@inheritDoc} */ 852 public void title() 853 { 854 currentSink.title(); 855 } 856 857 /** {@inheritDoc} */ 858 public void title( SinkEventAttributes attributes ) 859 { 860 currentSink.title( attributes ); 861 } 862 863 /** {@inheritDoc} */ 864 public void title_() 865 { 866 currentSink.title_(); 867 } 868 869 /** {@inheritDoc} */ 870 public void unknown( String name, Object[] requiredParams, SinkEventAttributes attributes ) 871 { 872 currentSink.unknown( name, requiredParams, attributes ); 873 } 874 875 /** {@inheritDoc} */ 876 public void verbatim( boolean boxed ) 877 { 878 currentSink.verbatim( boxed ); 879 } 880 881 /** {@inheritDoc} */ 882 public void verbatim( SinkEventAttributes attributes ) 883 { 884 currentSink.verbatim( attributes ); 885 } 886 887 /** {@inheritDoc} */ 888 public void verbatim_() 889 { 890 currentSink.verbatim_(); 891 } 892 893 /** {@inheritDoc} */ 894 public void enableLogging( Log log ) 895 { 896 currentSink.enableLogging( log ); 897 } 898}