001package org.apache.maven.doxia.sink.impl; 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; 031import org.apache.maven.doxia.sink.Sink; 032import org.apache.maven.doxia.sink.SinkEventAttributes; 033import org.apache.maven.doxia.sink.SinkFactory; 034 035/** 036 * The RandomAccessSink provides the ability to create a {@link Sink} with hooks. 037 * A page can be prepared by first creating its structure and specifying the positions of these hooks. 038 * After specifying the structure, the page can be filled with content from one or more models. 039 * These hooks can prevent you to have to loop over the model multiple times to build the page as desired. 040 * 041 * @author Robert Scholte 042 * @since 1.3 043 */ 044public class RandomAccessSink 045 implements Sink 046{ 047 private SinkFactory sinkFactory; 048 049 private String encoding; 050 051 private OutputStream coreOutputStream; 052 053 private Sink coreSink; 054 055 private List<Sink> sinks = new ArrayList<>(); 056 057 private List<ByteArrayOutputStream> outputStreams = new ArrayList<>(); 058 059 private Sink currentSink; 060 061 public RandomAccessSink( SinkFactory sinkFactory, OutputStream stream ) 062 throws IOException 063 { 064 this.sinkFactory = sinkFactory; 065 this.coreOutputStream = stream; 066 this.currentSink = sinkFactory.createSink( stream ); 067 this.coreSink = this.currentSink; 068 } 069 070 public RandomAccessSink( SinkFactory sinkFactory, OutputStream stream, String encoding ) 071 throws IOException 072 { 073 this.sinkFactory = sinkFactory; 074 this.coreOutputStream = stream; 075 this.encoding = encoding; 076 this.currentSink = sinkFactory.createSink( stream, encoding ); 077 this.coreSink = this.currentSink; 078 } 079 080 public RandomAccessSink( SinkFactory sinkFactory, File outputDirectory, String outputName ) 081 throws IOException 082 { 083 this.sinkFactory = sinkFactory; 084 this.coreOutputStream = new FileOutputStream( new File( outputDirectory, outputName ) ); 085 this.currentSink = sinkFactory.createSink( coreOutputStream ); 086 this.coreSink = this.currentSink; 087 } 088 089 public RandomAccessSink( SinkFactory sinkFactory, File outputDirectory, String outputName, String encoding ) 090 throws IOException 091 { 092 this.sinkFactory = sinkFactory; 093 this.coreOutputStream = new FileOutputStream( new File( outputDirectory, outputName ) ); 094 this.encoding = encoding; 095 this.currentSink = sinkFactory.createSink( coreOutputStream, encoding ); 096 this.coreSink = this.currentSink; 097 } 098 099 @Override 100 public void address() 101 { 102 currentSink.address(); 103 } 104 105 @Override 106 public void address( SinkEventAttributes attributes ) 107 { 108 currentSink.address( attributes ); 109 } 110 111 @Override 112 public void address_() 113 { 114 currentSink.address_(); 115 } 116 117 /** 118 * By calling this method a sink reference is added at the current position. You can write to both the new sink 119 * reference and the original sink. After flushing all sinks will be flushed in the right order. 120 * 121 * @return a subsink reference you can write to 122 */ 123 public Sink addSinkHook() 124 { 125 Sink subSink = null; 126 try 127 { 128 ByteArrayOutputStream subOut = new ByteArrayOutputStream(); 129 ByteArrayOutputStream newOut = new ByteArrayOutputStream(); 130 131 outputStreams.add( subOut ); 132 outputStreams.add( newOut ); 133 134 if ( encoding != null ) 135 { 136 subSink = sinkFactory.createSink( subOut, encoding ); 137 currentSink = sinkFactory.createSink( newOut, encoding ); 138 } 139 else 140 { 141 subSink = sinkFactory.createSink( subOut ); 142 currentSink = sinkFactory.createSink( newOut ); 143 } 144 sinks.add( subSink ); 145 sinks.add( currentSink ); 146 } 147 catch ( IOException e ) 148 { 149 // IOException can only be caused by our own ByteArrayOutputStream 150 } 151 return subSink; 152 } 153 154 @Override 155 public void anchor( String name ) 156 { 157 currentSink.anchor( name ); 158 } 159 160 @Override 161 public void anchor( String name, SinkEventAttributes attributes ) 162 { 163 currentSink.anchor( name, attributes ); 164 } 165 166 @Override 167 public void anchor_() 168 { 169 currentSink.anchor_(); 170 } 171 172 @Override 173 public void article() 174 { 175 currentSink.article(); 176 } 177 178 @Override 179 public void article( SinkEventAttributes attributes ) 180 { 181 currentSink.article( attributes ); 182 } 183 184 @Override 185 public void article_() 186 { 187 currentSink.article_(); 188 } 189 190 @Override 191 public void author() 192 { 193 currentSink.author(); 194 } 195 196 @Override 197 public void author( SinkEventAttributes attributes ) 198 { 199 currentSink.author( attributes ); 200 } 201 202 @Override 203 public void author_() 204 { 205 currentSink.author_(); 206 } 207 208 @Override 209 public void blockquote() 210 { 211 currentSink.blockquote(); 212 } 213 214 @Override 215 public void blockquote( SinkEventAttributes attributes ) 216 { 217 currentSink.blockquote( attributes ); 218 } 219 220 @Override 221 public void blockquote_() 222 { 223 currentSink.blockquote_(); 224 } 225 226 @Override 227 public void body() 228 { 229 currentSink.body(); 230 } 231 232 @Override 233 public void body( SinkEventAttributes attributes ) 234 { 235 currentSink.body( attributes ); 236 } 237 238 @Override 239 public void body_() 240 { 241 currentSink.body_(); 242 } 243 244 @Override 245 public void bold() 246 { 247 currentSink.bold(); 248 } 249 250 @Override 251 public void bold_() 252 { 253 currentSink.bold_(); 254 } 255 256 /** 257 * Close all sinks 258 */ 259 public void close() 260 { 261 for ( Sink sink : sinks ) 262 { 263 // sink is responsible for closing it's stream 264 sink.close(); 265 } 266 coreSink.close(); 267 } 268 269 @Override 270 public void comment( String comment ) 271 { 272 currentSink.comment( comment ); 273 } 274 275 @Override 276 public void content() 277 { 278 currentSink.content(); 279 } 280 281 @Override 282 public void content( SinkEventAttributes attributes ) 283 { 284 currentSink.content( attributes ); 285 } 286 287 @Override 288 public void content_() 289 { 290 currentSink.content_(); 291 } 292 293 @Override 294 public void data( String value ) 295 { 296 currentSink.data( value ); 297 } 298 299 @Override 300 public void data( String value, SinkEventAttributes attributes ) 301 { 302 currentSink.data( value, attributes ); 303 } 304 305 @Override 306 public void data_() 307 { 308 currentSink.data_(); 309 } 310 311 @Override 312 public void date() 313 { 314 currentSink.date(); 315 } 316 317 @Override 318 public void date( SinkEventAttributes attributes ) 319 { 320 currentSink.date( attributes ); 321 } 322 323 @Override 324 public void date_() 325 { 326 currentSink.date_(); 327 } 328 329 @Override 330 public void definedTerm() 331 { 332 currentSink.definedTerm(); 333 } 334 335 @Override 336 public void definedTerm( SinkEventAttributes attributes ) 337 { 338 currentSink.definedTerm( attributes ); 339 } 340 341 @Override 342 public void definedTerm_() 343 { 344 currentSink.definedTerm_(); 345 } 346 347 @Override 348 public void definition() 349 { 350 currentSink.definition(); 351 } 352 353 @Override 354 public void definition( SinkEventAttributes attributes ) 355 { 356 currentSink.definition( attributes ); 357 } 358 359 @Override 360 public void definitionList() 361 { 362 currentSink.definitionList(); 363 } 364 365 @Override 366 public void definitionList( SinkEventAttributes attributes ) 367 { 368 currentSink.definitionList( attributes ); 369 } 370 371 @Override 372 public void definitionListItem() 373 { 374 currentSink.definitionListItem(); 375 } 376 377 @Override 378 public void definitionListItem( SinkEventAttributes attributes ) 379 { 380 currentSink.definitionListItem( attributes ); 381 } 382 383 @Override 384 public void definitionListItem_() 385 { 386 currentSink.definitionListItem_(); 387 } 388 389 @Override 390 public void definitionList_() 391 { 392 currentSink.definitionList_(); 393 } 394 395 @Override 396 public void definition_() 397 { 398 currentSink.definition_(); 399 } 400 401 @Override 402 public void division() 403 { 404 currentSink.division(); 405 } 406 407 @Override 408 public void division( SinkEventAttributes attributes ) 409 { 410 currentSink.division( attributes ); 411 } 412 413 @Override 414 public void division_() 415 { 416 currentSink.division_(); 417 } 418 419 @Override 420 public void figure() 421 { 422 currentSink.figure(); 423 } 424 425 @Override 426 public void figure( SinkEventAttributes attributes ) 427 { 428 currentSink.figure( attributes ); 429 } 430 431 @Override 432 public void figureCaption() 433 { 434 currentSink.figureCaption(); 435 } 436 437 @Override 438 public void figureCaption( SinkEventAttributes attributes ) 439 { 440 currentSink.figureCaption( attributes ); 441 } 442 443 @Override 444 public void figureCaption_() 445 { 446 currentSink.figureCaption_(); 447 } 448 449 @Override 450 public void figureGraphics( String name ) 451 { 452 currentSink.figureGraphics( name ); 453 } 454 455 @Override 456 public void figureGraphics( String src, SinkEventAttributes attributes ) 457 { 458 currentSink.figureGraphics( src, attributes ); 459 } 460 461 @Override 462 public void figure_() 463 { 464 currentSink.figure_(); 465 } 466 467 /** 468 * Flush all sinks 469 */ 470 public void flush() 471 { 472 for ( int i = 0; i < sinks.size(); i++ ) 473 { 474 // first flush to get complete buffer 475 // sink is responsible for flushing it's stream 476 Sink sink = sinks.get( i ); 477 sink.flush(); 478 479 ByteArrayOutputStream stream = outputStreams.get( i ); 480 try 481 { 482 coreOutputStream.write( stream.toByteArray() ); 483 } 484 catch ( IOException e ) 485 { 486 // @todo 487 } 488 } 489 coreSink.flush(); 490 } 491 492 @Override 493 public void footer() 494 { 495 currentSink.footer(); 496 } 497 498 @Override 499 public void footer( SinkEventAttributes attributes ) 500 { 501 currentSink.footer( attributes ); 502 } 503 504 @Override 505 public void footer_() 506 { 507 currentSink.footer_(); 508 } 509 510 @Override 511 public void head() 512 { 513 currentSink.head(); 514 } 515 516 @Override 517 public void head( SinkEventAttributes attributes ) 518 { 519 currentSink.head( attributes ); 520 } 521 522 @Override 523 public void head_() 524 { 525 currentSink.head_(); 526 } 527 528 @Override 529 public void header() 530 { 531 currentSink.header(); 532 } 533 534 @Override 535 public void header( SinkEventAttributes attributes ) 536 { 537 currentSink.header( attributes ); 538 } 539 540 @Override 541 public void header_() 542 { 543 currentSink.header_(); 544 } 545 546 @Override 547 public void horizontalRule() 548 { 549 currentSink.horizontalRule(); 550 } 551 552 @Override 553 public void horizontalRule( SinkEventAttributes attributes ) 554 { 555 currentSink.horizontalRule( attributes ); 556 } 557 558 @Override 559 public void inline() 560 { 561 currentSink.inline(); 562 } 563 564 @Override 565 public void inline( SinkEventAttributes attributes ) 566 { 567 currentSink.inline( attributes ); 568 } 569 570 @Override 571 public void inline_() 572 { 573 currentSink.inline_(); 574 } 575 576 @Override 577 public void italic() 578 { 579 currentSink.italic(); 580 } 581 582 @Override 583 public void italic_() 584 { 585 currentSink.italic_(); 586 } 587 588 @Override 589 public void lineBreak() 590 { 591 currentSink.lineBreak(); 592 } 593 594 @Override 595 public void lineBreak( SinkEventAttributes attributes ) 596 { 597 currentSink.lineBreak( attributes ); 598 } 599 600 @Override 601 public void lineBreakOpportunity() 602 { 603 currentSink.lineBreakOpportunity(); 604 } 605 606 @Override 607 public void lineBreakOpportunity( SinkEventAttributes attributes ) 608 { 609 currentSink.lineBreakOpportunity( attributes ); 610 } 611 612 @Override 613 public void link( String name ) 614 { 615 currentSink.link( name ); 616 } 617 618 @Override 619 public void link( String name, SinkEventAttributes attributes ) 620 { 621 currentSink.link( name, attributes ); 622 } 623 624 @Override 625 public void link_() 626 { 627 currentSink.link_(); 628 } 629 630 @Override 631 public void list() 632 { 633 currentSink.list(); 634 } 635 636 @Override 637 public void list( SinkEventAttributes attributes ) 638 { 639 currentSink.list( attributes ); 640 } 641 642 @Override 643 public void listItem() 644 { 645 currentSink.listItem(); 646 } 647 648 @Override 649 public void listItem( SinkEventAttributes attributes ) 650 { 651 currentSink.listItem( attributes ); 652 } 653 654 @Override 655 public void listItem_() 656 { 657 currentSink.listItem_(); 658 } 659 660 @Override 661 public void list_() 662 { 663 currentSink.list_(); 664 } 665 666 @Override 667 public void monospaced() 668 { 669 currentSink.monospaced(); 670 } 671 672 @Override 673 public void monospaced_() 674 { 675 currentSink.monospaced_(); 676 } 677 678 @Override 679 public void navigation() 680 { 681 currentSink.navigation(); 682 } 683 684 @Override 685 public void navigation( SinkEventAttributes attributes ) 686 { 687 currentSink.navigation( attributes ); 688 } 689 690 @Override 691 public void navigation_() 692 { 693 currentSink.navigation_(); 694 } 695 696 @Override 697 public void nonBreakingSpace() 698 { 699 currentSink.nonBreakingSpace(); 700 } 701 702 @Override 703 public void numberedList( int numbering ) 704 { 705 currentSink.numberedList( numbering ); 706 } 707 708 @Override 709 public void numberedList( int numbering, SinkEventAttributes attributes ) 710 { 711 currentSink.numberedList( numbering, attributes ); 712 } 713 714 @Override 715 public void numberedListItem() 716 { 717 currentSink.numberedListItem(); 718 } 719 720 @Override 721 public void numberedListItem( SinkEventAttributes attributes ) 722 { 723 currentSink.numberedListItem( attributes ); 724 } 725 726 @Override 727 public void numberedListItem_() 728 { 729 currentSink.numberedListItem_(); 730 } 731 732 @Override 733 public void numberedList_() 734 { 735 currentSink.numberedList_(); 736 } 737 738 @Override 739 public void pageBreak() 740 { 741 currentSink.pageBreak(); 742 } 743 744 @Override 745 public void paragraph() 746 { 747 currentSink.paragraph(); 748 } 749 750 @Override 751 public void paragraph( SinkEventAttributes attributes ) 752 { 753 currentSink.paragraph( attributes ); 754 } 755 756 @Override 757 public void paragraph_() 758 { 759 currentSink.paragraph_(); 760 } 761 762 @Override 763 public void rawText( String text ) 764 { 765 currentSink.rawText( text ); 766 } 767 768 @Override 769 public void section( int level, SinkEventAttributes attributes ) 770 { 771 currentSink.section( level, attributes ); 772 } 773 774 @Override 775 public void section1() 776 { 777 currentSink.section1(); 778 } 779 780 @Override 781 public void section1_() 782 { 783 currentSink.section1_(); 784 } 785 786 @Override 787 public void section2() 788 { 789 currentSink.section2(); 790 } 791 792 @Override 793 public void section2_() 794 { 795 currentSink.section2_(); 796 } 797 798 @Override 799 public void section3() 800 { 801 currentSink.section3(); 802 } 803 804 @Override 805 public void section3_() 806 { 807 currentSink.section3_(); 808 } 809 810 @Override 811 public void section4() 812 { 813 currentSink.section4(); 814 } 815 816 @Override 817 public void section4_() 818 { 819 currentSink.section4_(); 820 } 821 822 @Override 823 public void section5() 824 { 825 currentSink.section5(); 826 } 827 828 @Override 829 public void section5_() 830 { 831 currentSink.section5_(); 832 } 833 834 @Override 835 public void section6() 836 { 837 currentSink.section5(); 838 } 839 840 @Override 841 public void section6_() 842 { 843 currentSink.section5_(); 844 } 845 846 @Override 847 public void sectionTitle() 848 { 849 currentSink.sectionTitle(); 850 } 851 852 @Override 853 public void sectionTitle( int level, SinkEventAttributes attributes ) 854 { 855 currentSink.sectionTitle( level, attributes ); 856 } 857 858 @Override 859 public void sectionTitle1() 860 { 861 currentSink.sectionTitle1(); 862 } 863 864 @Override 865 public void sectionTitle1_() 866 { 867 currentSink.sectionTitle1_(); 868 } 869 870 @Override 871 public void sectionTitle2() 872 { 873 currentSink.sectionTitle2(); 874 } 875 876 @Override 877 public void sectionTitle2_() 878 { 879 currentSink.sectionTitle2_(); 880 } 881 882 @Override 883 public void sectionTitle3() 884 { 885 currentSink.sectionTitle3(); 886 } 887 888 @Override 889 public void sectionTitle3_() 890 { 891 currentSink.sectionTitle3_(); 892 } 893 894 @Override 895 public void sectionTitle4() 896 { 897 currentSink.sectionTitle4(); 898 } 899 900 @Override 901 public void sectionTitle4_() 902 { 903 currentSink.sectionTitle4_(); 904 } 905 906 @Override 907 public void sectionTitle5() 908 { 909 currentSink.sectionTitle5(); 910 } 911 912 @Override 913 public void sectionTitle5_() 914 { 915 currentSink.sectionTitle5_(); 916 } 917 918 @Override 919 public void sectionTitle6() 920 { 921 currentSink.sectionTitle5(); 922 } 923 924 @Override 925 public void sectionTitle6_() 926 { 927 currentSink.sectionTitle5_(); 928 } 929 930 @Override 931 public void sectionTitle_() 932 { 933 currentSink.sectionTitle_(); 934 } 935 936 @Override 937 public void sectionTitle_( int level ) 938 { 939 currentSink.sectionTitle_( level ); 940 } 941 942 @Override 943 public void section_( int level ) 944 { 945 currentSink.section_( level ); 946 } 947 948 @Override 949 public void sidebar() 950 { 951 currentSink.sidebar(); 952 } 953 954 @Override 955 public void sidebar( SinkEventAttributes attributes ) 956 { 957 currentSink.sidebar( attributes ); 958 } 959 960 @Override 961 public void sidebar_() 962 { 963 currentSink.sidebar_(); 964 } 965 966 @Override 967 public void table() 968 { 969 currentSink.table(); 970 } 971 972 @Override 973 public void table( SinkEventAttributes attributes ) 974 { 975 currentSink.table( attributes ); 976 } 977 978 @Override 979 public void tableCaption() 980 { 981 currentSink.tableCaption(); 982 } 983 984 @Override 985 public void tableCaption( SinkEventAttributes attributes ) 986 { 987 currentSink.tableCaption( attributes ); 988 } 989 990 @Override 991 public void tableCaption_() 992 { 993 currentSink.tableCaption_(); 994 } 995 996 @Override 997 public void tableCell() 998 { 999 currentSink.tableCell(); 1000 } 1001 1002 @Override 1003 public void tableCell( String width ) 1004 { 1005 currentSink.tableCell( width ); 1006 } 1007 1008 @Override 1009 public void tableCell( SinkEventAttributes attributes ) 1010 { 1011 currentSink.tableCell( attributes ); 1012 } 1013 1014 @Override 1015 public void tableCell_() 1016 { 1017 currentSink.tableCell_(); 1018 } 1019 1020 @Override 1021 public void tableHeaderCell() 1022 { 1023 currentSink.tableHeaderCell(); 1024 } 1025 1026 @Override 1027 public void tableHeaderCell( String width ) 1028 { 1029 currentSink.tableHeaderCell( width ); 1030 } 1031 1032 @Override 1033 public void tableHeaderCell( SinkEventAttributes attributes ) 1034 { 1035 currentSink.tableHeaderCell( attributes ); 1036 } 1037 1038 @Override 1039 public void tableHeaderCell_() 1040 { 1041 currentSink.tableHeaderCell_(); 1042 } 1043 1044 @Override 1045 public void tableRow() 1046 { 1047 currentSink.tableRow(); 1048 } 1049 1050 @Override 1051 public void tableRow( SinkEventAttributes attributes ) 1052 { 1053 currentSink.tableRow( attributes ); 1054 } 1055 1056 @Override 1057 public void tableRow_() 1058 { 1059 currentSink.tableRow_(); 1060 } 1061 1062 @Override 1063 public void tableRows( int[] justification, boolean grid ) 1064 { 1065 currentSink.tableRows( justification, grid ); 1066 } 1067 1068 @Override 1069 public void tableRows_() 1070 { 1071 currentSink.tableRows_(); 1072 } 1073 1074 @Override 1075 public void table_() 1076 { 1077 currentSink.table_(); 1078 } 1079 1080 @Override 1081 public void text( String text ) 1082 { 1083 currentSink.text( text ); 1084 } 1085 1086 @Override 1087 public void text( String text, SinkEventAttributes attributes ) 1088 { 1089 currentSink.text( text, attributes ); 1090 } 1091 1092 @Override 1093 public void time( String datetime ) 1094 { 1095 currentSink.time( datetime ); 1096 } 1097 1098 @Override 1099 public void time( String datetime, SinkEventAttributes attributes ) 1100 { 1101 currentSink.time( datetime, attributes ); 1102 } 1103 1104 @Override 1105 public void time_() 1106 { 1107 currentSink.time_(); 1108 } 1109 1110 @Override 1111 public void title() 1112 { 1113 currentSink.title(); 1114 } 1115 1116 @Override 1117 public void title( SinkEventAttributes attributes ) 1118 { 1119 currentSink.title( attributes ); 1120 } 1121 1122 @Override 1123 public void title_() 1124 { 1125 currentSink.title_(); 1126 } 1127 1128 @Override 1129 public void unknown( String name, Object[] requiredParams, SinkEventAttributes attributes ) 1130 { 1131 currentSink.unknown( name, requiredParams, attributes ); 1132 } 1133 1134 @Override 1135 public void verbatim( boolean boxed ) 1136 { 1137 currentSink.verbatim( boxed ); 1138 } 1139 1140 @Override 1141 public void verbatim( SinkEventAttributes attributes ) 1142 { 1143 currentSink.verbatim( attributes ); 1144 } 1145 1146 @Override 1147 public void verbatim_() 1148 { 1149 currentSink.verbatim_(); 1150 } 1151 1152 @Override 1153 public void enableLogging( Log log ) 1154 { 1155 currentSink.enableLogging( log ); 1156 } 1157}