View Javadoc
1   package org.apache.maven.doxia.sink.impl;
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 java.io.ByteArrayOutputStream;
23  import java.io.File;
24  import java.io.FileOutputStream;
25  import java.io.IOException;
26  import java.io.OutputStream;
27  import java.util.ArrayList;
28  import java.util.List;
29  
30  import org.apache.maven.doxia.logging.Log;
31  import org.apache.maven.doxia.sink.Sink;
32  import org.apache.maven.doxia.sink.SinkEventAttributes;
33  import org.apache.maven.doxia.sink.SinkFactory;
34  
35  /**
36   * The RandomAccessSink provides the ability to create a {@link Sink} with hooks.
37   * A page can be prepared by first creating its structure and specifying the positions of these hooks.
38   * After specifying the structure, the page can be filled with content from one or more models.
39   * These hooks can prevent you to have to loop over the model multiple times to build the page as desired. 
40   * 
41   * @author Robert Scholte
42   * @since 1.3
43   */
44  public class RandomAccessSink
45      implements Sink
46  {
47      private SinkFactory sinkFactory;
48  
49      private String encoding;
50  
51      private OutputStream coreOutputStream;
52  
53      private Sink coreSink;
54  
55      private List<Sink> sinks = new ArrayList<>();
56  
57      private List<ByteArrayOutputStream> outputStreams = new ArrayList<>();
58  
59      private Sink currentSink;
60  
61      public RandomAccessSink( SinkFactory sinkFactory, OutputStream stream )
62          throws IOException
63      {
64          this.sinkFactory = sinkFactory;
65          this.coreOutputStream = stream;
66          this.currentSink = sinkFactory.createSink( stream );
67          this.coreSink = this.currentSink;
68      }
69  
70      public RandomAccessSink( SinkFactory sinkFactory, OutputStream stream, String encoding )
71          throws IOException
72      {
73          this.sinkFactory = sinkFactory;
74          this.coreOutputStream = stream;
75          this.encoding = encoding;
76          this.currentSink = sinkFactory.createSink( stream, encoding );
77          this.coreSink = this.currentSink;
78      }
79  
80      public RandomAccessSink( SinkFactory sinkFactory, File outputDirectory, String outputName )
81          throws IOException
82      {
83          this.sinkFactory = sinkFactory;
84          this.coreOutputStream = new FileOutputStream( new File( outputDirectory, outputName ) );
85          this.currentSink = sinkFactory.createSink( coreOutputStream );
86          this.coreSink = this.currentSink;
87      }
88  
89      public RandomAccessSink( SinkFactory sinkFactory, File outputDirectory, String outputName, String encoding )
90          throws IOException
91      {
92          this.sinkFactory = sinkFactory;
93          this.coreOutputStream = new FileOutputStream( new File( outputDirectory, outputName ) );
94          this.encoding = encoding;
95          this.currentSink = sinkFactory.createSink( coreOutputStream, encoding );
96          this.coreSink = this.currentSink;
97      }
98  
99      @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 }