1 package org.apache.maven.plugins.pdf;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.Reader;
25 import java.io.StringReader;
26 import java.io.StringWriter;
27 import java.io.Writer;
28 import java.lang.reflect.InvocationHandler;
29 import java.lang.reflect.Method;
30 import java.lang.reflect.Proxy;
31 import java.util.ArrayList;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Locale;
36 import java.util.Map;
37
38 import javax.swing.text.AttributeSet;
39
40 import org.apache.maven.artifact.Artifact;
41 import org.apache.maven.artifact.factory.ArtifactFactory;
42 import org.apache.maven.artifact.repository.ArtifactRepository;
43 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
44 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
45 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
46 import org.apache.maven.doxia.Doxia;
47 import org.apache.maven.doxia.docrenderer.AbstractDocumentRenderer;
48 import org.apache.maven.doxia.docrenderer.DocumentRenderer;
49 import org.apache.maven.doxia.docrenderer.DocumentRendererContext;
50 import org.apache.maven.doxia.docrenderer.DocumentRendererException;
51 import org.apache.maven.doxia.docrenderer.pdf.PdfRenderer;
52 import org.apache.maven.doxia.document.DocumentModel;
53 import org.apache.maven.doxia.document.DocumentTOCItem;
54 import org.apache.maven.doxia.document.io.xpp3.DocumentXpp3Writer;
55 import org.apache.maven.doxia.index.IndexEntry;
56 import org.apache.maven.doxia.index.IndexingSink;
57 import org.apache.maven.doxia.markup.HtmlMarkup;
58 import org.apache.maven.doxia.module.xdoc.XdocSink;
59 import org.apache.maven.doxia.parser.ParseException;
60 import org.apache.maven.doxia.parser.manager.ParserNotFoundException;
61 import org.apache.maven.doxia.sink.Sink;
62 import org.apache.maven.doxia.sink.SinkAdapter;
63 import org.apache.maven.doxia.sink.SinkEventAttributeSet;
64 import org.apache.maven.doxia.sink.SinkEventAttributes;
65 import org.apache.maven.doxia.site.decoration.DecorationModel;
66 import org.apache.maven.doxia.site.decoration.io.xpp3.DecorationXpp3Reader;
67 import org.apache.maven.doxia.siterenderer.Renderer;
68 import org.apache.maven.doxia.siterenderer.SiteRenderingContext;
69 import org.apache.maven.doxia.tools.SiteTool;
70 import org.apache.maven.doxia.tools.SiteToolException;
71 import org.apache.maven.execution.MavenSession;
72 import org.apache.maven.model.MailingList;
73 import org.apache.maven.model.ReportPlugin;
74 import org.apache.maven.model.ReportSet;
75 import org.apache.maven.plugin.AbstractMojo;
76 import org.apache.maven.plugin.InvalidPluginException;
77 import org.apache.maven.plugin.MojoExecution;
78 import org.apache.maven.plugin.MojoExecutionException;
79 import org.apache.maven.plugin.MojoFailureException;
80 import org.apache.maven.plugin.PluginConfigurationException;
81 import org.apache.maven.plugin.PluginManager;
82 import org.apache.maven.plugin.PluginManagerException;
83 import org.apache.maven.plugin.PluginNotFoundException;
84 import org.apache.maven.plugin.descriptor.MojoDescriptor;
85 import org.apache.maven.plugin.descriptor.PluginDescriptor;
86 import org.apache.maven.plugin.version.PluginVersionNotFoundException;
87 import org.apache.maven.plugin.version.PluginVersionResolutionException;
88 import org.apache.maven.project.MavenProject;
89 import org.apache.maven.project.MavenProjectBuilder;
90 import org.apache.maven.project.ProjectBuildingException;
91 import org.apache.maven.reporting.AbstractMavenReport;
92 import org.apache.maven.reporting.AbstractMavenReportRenderer;
93 import org.apache.maven.reporting.MavenReport;
94 import org.apache.maven.reporting.MavenReportException;
95 import org.apache.maven.settings.Settings;
96 import org.codehaus.classworlds.ClassRealm;
97 import org.codehaus.plexus.i18n.I18N;
98 import org.codehaus.plexus.util.FileUtils;
99 import org.codehaus.plexus.util.IOUtil;
100 import org.codehaus.plexus.util.PathTool;
101 import org.codehaus.plexus.util.ReaderFactory;
102 import org.codehaus.plexus.util.StringUtils;
103 import org.codehaus.plexus.util.WriterFactory;
104 import org.codehaus.plexus.util.xml.XmlStreamReader;
105 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
106
107
108
109
110
111
112
113
114 public class PdfMojo
115 extends AbstractMojo
116 {
117
118 private static final String EOL = System.getProperty( "line.separator" );
119
120
121
122
123
124
125
126
127
128
129 private PdfRenderer foRenderer;
130
131
132
133
134
135
136 private I18N i18n;
137
138
139
140
141
142
143 private PdfRenderer itextRenderer;
144
145
146
147
148
149
150
151 private String locales;
152
153
154
155
156
157
158 private Renderer siteRenderer;
159
160
161
162
163
164
165 private SiteTool siteTool;
166
167
168
169
170
171
172
173 private PluginManager pluginManager;
174
175
176
177
178
179
180
181 private Doxia doxia;
182
183
184
185
186
187
188
189 private ArtifactFactory artifactFactory;
190
191
192
193
194
195
196
197 private MavenProjectBuilder mavenProjectBuilder;
198
199
200
201
202
203
204
205
206
207
208
209
210 private MavenProject project;
211
212
213
214
215
216
217
218
219
220 private Settings settings;
221
222
223
224
225
226
227
228
229
230 private MavenSession session;
231
232
233
234
235
236
237
238 private File siteDirectory;
239
240
241
242
243
244
245
246
247 private File generatedSiteDirectory;
248
249
250
251
252
253
254
255 private File outputDirectory;
256
257
258
259
260
261
262
263 private File workingDirectory;
264
265
266
267
268
269
270 private File docDescriptor;
271
272
273
274
275
276
277
278 private String implementation;
279
280
281
282
283
284
285
286
287 private ArtifactRepository localRepository;
288
289
290
291
292
293
294
295 private List remoteRepositories;
296
297
298
299
300
301
302
303 private boolean aggregate;
304
305
306
307
308
309
310
311 private String pluginVersion;
312
313
314
315
316
317
318
319
320
321 private boolean includeReports;
322
323
324
325
326
327
328
329
330
331 private String generateTOC;
332
333
334
335
336
337
338
339
340
341 private DocumentRenderer docRenderer;
342
343
344
345
346 private Locale defaultLocale;
347
348
349
350
351 private List localesList;
352
353
354
355
356 private DecorationModel defaultDecorationModel;
357
358
359
360
361
362
363 private File siteDirectoryTmp;
364
365
366
367
368
369
370 private File generatedSiteDirectoryTmp;
371
372
373
374
375
376
377 private Map generatedMavenReports;
378
379
380
381
382
383
384 public void execute()
385 throws MojoExecutionException, MojoFailureException
386 {
387 init();
388
389 try
390 {
391 generatedPdf();
392 }
393 catch ( IOException e )
394 {
395 debugLogGeneratedModel( getDocumentModel( Locale.ENGLISH ) );
396
397 throw new MojoExecutionException( "Error during document generation: " + e.getMessage(), e );
398 }
399
400 try
401 {
402 copyGeneratedPdf();
403 }
404 catch ( IOException e )
405 {
406 throw new MojoExecutionException( "Error copying generated PDF: " + e.getMessage(), e );
407 }
408 }
409
410
411
412
413
414
415 private void init()
416 throws MojoFailureException
417 {
418 if ( "fo".equalsIgnoreCase( implementation ) )
419 {
420 this.docRenderer = foRenderer;
421 }
422 else if ( "itext".equalsIgnoreCase( implementation ) )
423 {
424 this.docRenderer = itextRenderer;
425 }
426 else
427 {
428 throw new MojoFailureException( "Not a valid 'implementation' parameter: '" + implementation
429 + "'. Should be 'fo' or 'itext'." );
430 }
431
432 if ( !( "none".equalsIgnoreCase( generateTOC ) || "start".equalsIgnoreCase( generateTOC ) || "end"
433 .equalsIgnoreCase( generateTOC ) ) )
434 {
435 throw new MojoFailureException( "Not a valid 'generateTOC' parameter: '" + generateTOC
436 + "'. Should be 'none', 'start' or 'end'." );
437 }
438 }
439
440
441
442
443
444
445
446
447 private void copyGeneratedPdf()
448 throws MojoExecutionException, IOException
449 {
450 if ( !outputDirectory.getCanonicalPath().equals( workingDirectory.getCanonicalPath() ) )
451 {
452 String outputName = getDocumentModel( getDefaultLocale() ).getOutputName();
453 final String extension = FileUtils.getExtension( outputName );
454 if ( StringUtils.isNotEmpty( extension ) )
455 {
456 outputName = outputName.substring( 0, outputName.indexOf( extension ) - 1 );
457 }
458
459 for ( final Iterator iterator = getAvailableLocales().iterator(); iterator.hasNext(); )
460 {
461 final Locale locale = (Locale) iterator.next();
462
463 File generatedPdfSource;
464 if ( !locale.getLanguage().equals( getDefaultLocale().getLanguage() ) )
465 {
466 generatedPdfSource =
467 new File( workingDirectory, locale.getLanguage() + File.separator + outputName + ".pdf" );
468 }
469 else
470 {
471 generatedPdfSource = new File( workingDirectory, outputName + ".pdf" );
472 }
473
474 if ( !generatedPdfSource.exists() )
475 {
476 getLog().warn( "Unable to find the generated pdf: " + generatedPdfSource.getAbsolutePath() );
477 continue;
478 }
479
480 File generatedPdfDest;
481 if ( !locale.getLanguage().equals( getDefaultLocale().getLanguage() ) )
482 {
483 generatedPdfDest =
484 new File( outputDirectory, locale.getLanguage() + File.separator + outputName + ".pdf" );
485 }
486 else
487 {
488 generatedPdfDest = new File( outputDirectory, outputName + ".pdf" );
489 }
490
491 FileUtils.copyFile( generatedPdfSource, generatedPdfDest );
492 generatedPdfSource.delete();
493 }
494 }
495 }
496
497
498
499
500
501
502
503
504
505
506
507
508 private void generatedPdf()
509 throws MojoExecutionException, IOException
510 {
511 try
512 {
513 FileUtils.deleteDirectory( workingDirectory );
514 }
515 catch ( IOException e )
516 {
517 if ( getLog().isDebugEnabled() )
518 {
519 getLog().error( "IOException: " + e.getMessage(), e );
520 }
521 else
522 {
523 getLog().error( "IOException: " + e.getMessage() );
524 }
525 }
526
527 Locale.setDefault( getDefaultLocale() );
528
529 for ( final Iterator iterator = getAvailableLocales().iterator(); iterator.hasNext(); )
530 {
531 final Locale locale = (Locale) iterator.next();
532
533 final File workingDir = getWorkingDirectory( locale );
534
535 File siteDirectoryFile = getSiteDirectoryTmp();
536 if ( !locale.getLanguage().equals( getDefaultLocale().getLanguage() ) )
537 {
538 siteDirectoryFile = new File( getSiteDirectoryTmp(), locale.getLanguage() );
539 }
540
541
542 copyResources( locale );
543
544
545 generateMavenReports( locale );
546
547 DocumentRendererContext context = new DocumentRendererContext();
548 context.put( "project", project );
549 context.put( "settings", settings );
550 context.put( "PathTool", new PathTool() );
551 context.put( "FileUtils", new FileUtils() );
552 context.put( "StringUtils", new StringUtils() );
553 context.put( "i18n", i18n );
554 context.put( "generateTOC", generateTOC );
555
556 try
557 {
558
559 if ( aggregate )
560 {
561 ( (AbstractDocumentRenderer) docRenderer ).render( siteDirectoryFile, workingDir,
562 getDocumentModel( locale ), context );
563 }
564 else
565 {
566 ( (AbstractDocumentRenderer) docRenderer ).render( siteDirectoryFile, workingDir, null,
567 context );
568 }
569 }
570 catch ( DocumentRendererException e )
571 {
572 if ( getLog().isDebugEnabled() )
573 {
574 throw new MojoExecutionException( "Error during document generation: " + e.getMessage(), e );
575 }
576
577 throw new MojoExecutionException( "Error during document generation: " + e.getMessage() );
578 }
579 }
580 }
581
582
583
584
585
586
587 private File getSiteDirectoryTmp()
588 throws IOException
589 {
590 if ( this.siteDirectoryTmp == null )
591 {
592 final File tmpSiteDir = new File( workingDirectory, "site.tmp" );
593 prepareTempSiteDirectory( tmpSiteDir );
594
595 this.siteDirectoryTmp = tmpSiteDir;
596 }
597
598 return this.siteDirectoryTmp;
599 }
600
601
602
603
604
605 private File getGeneratedSiteDirectoryTmp()
606 {
607 if ( this.generatedSiteDirectoryTmp == null )
608 {
609 this.generatedSiteDirectoryTmp = new File( workingDirectory, "generated-site.tmp" );
610 }
611
612 return this.generatedSiteDirectoryTmp;
613 }
614
615
616
617
618
619
620
621
622
623
624
625 private void prepareTempSiteDirectory( final File tmpSiteDir )
626 throws IOException
627 {
628
629 tmpSiteDir.mkdirs();
630
631
632 FileUtils.copyDirectoryStructure( siteDirectory, tmpSiteDir );
633
634 List files =
635 FileUtils.getFileAndDirectoryNames( tmpSiteDir, FileUtils.getDefaultExcludesAsString(), null, true,
636 true, true, true );
637 for ( final Iterator it = files.iterator(); it.hasNext(); )
638 {
639 final File file = new File( it.next().toString() );
640
641 if ( file.isDirectory() )
642 {
643 FileUtils.deleteDirectory( file );
644 }
645 else
646 {
647 file.delete();
648 }
649 }
650
651 copySiteDir( generatedSiteDirectory, tmpSiteDir );
652 }
653
654
655
656
657
658
659
660
661
662 private void copySiteDir( final File from, final File to )
663 throws IOException
664 {
665 if ( from == null || !from.exists() )
666 {
667 return;
668 }
669
670
671 for ( final Iterator iterator = getAvailableLocales().iterator(); iterator.hasNext(); )
672 {
673 final Locale locale = (Locale) iterator.next();
674
675 String excludes = getDefaultExcludesWithLocales( getAvailableLocales(), getDefaultLocale() );
676 List siteFiles = FileUtils.getFileNames( siteDirectory, "**/*", excludes, false );
677 File siteDirectoryLocale = new File( siteDirectory, locale.getLanguage() );
678 if ( !locale.getLanguage().equals( getDefaultLocale().getLanguage() ) && siteDirectoryLocale.exists() )
679 {
680 siteFiles = FileUtils.getFileNames( siteDirectoryLocale, "**/*", excludes, false );
681 }
682
683 List generatedSiteFiles = FileUtils.getFileNames( from, "**/*", excludes, false );
684 File fromLocale = new File( from, locale.getLanguage() );
685 if ( !locale.getLanguage().equals( getDefaultLocale().getLanguage() ) && fromLocale.exists() )
686 {
687 generatedSiteFiles = FileUtils.getFileNames( fromLocale, "**/*", excludes, false );
688 }
689
690 for ( final Iterator it = generatedSiteFiles.iterator(); it.hasNext(); )
691 {
692 final String generatedSiteFile = it.next().toString();
693
694 if ( siteFiles.contains( generatedSiteFile ) )
695 {
696 getLog().warn(
697 "Generated-site already contains a file in site: " + generatedSiteFile
698 + ". Ignoring copying it!" );
699 continue;
700 }
701
702 if ( !locale.getLanguage().equals( getDefaultLocale().getLanguage() ) )
703 {
704 if ( fromLocale.exists() )
705 {
706 File in = new File( fromLocale, generatedSiteFile );
707 File out = new File( new File( to, locale.getLanguage() ), generatedSiteFile );
708 out.getParentFile().mkdirs();
709 FileUtils.copyFile( in, out );
710 }
711 }
712 else
713 {
714 File in = new File( from, generatedSiteFile );
715 File out = new File( to, generatedSiteFile );
716 out.getParentFile().mkdirs();
717 FileUtils.copyFile( in, out );
718 }
719 }
720 }
721 }
722
723
724
725
726
727
728
729
730
731
732 private DocumentModel getDocumentModel( Locale locale )
733 throws MojoExecutionException
734 {
735 if ( docDescriptor.exists() )
736 {
737 DocumentModel doc = getDocumentModelFromDescriptor( locale );
738
739
740 appendGeneratedReports( doc, locale );
741
742 return doc;
743 }
744
745 DocumentModel model = new DocumentModelBuilder( project, getDefaultDecorationModel() ).getDocumentModel();
746
747 model.getMeta().setGenerator( getDefaultGenerator() );
748 model.getMeta().setLanguage( locale.getLanguage() );
749 model.getCover().setCoverType( i18n.getString( "pdf-plugin", getDefaultLocale(), "toc.type" ) );
750 model.getToc().setName( i18n.getString( "pdf-plugin", getDefaultLocale(), "toc.title" ) );
751
752 appendGeneratedReports( model, locale );
753
754 debugLogGeneratedModel( model );
755
756 return model;
757 }
758
759
760
761
762
763
764
765
766 private DocumentModel getDocumentModelFromDescriptor( Locale locale )
767 throws MojoExecutionException
768 {
769 DocumentModel model = null;
770
771 try
772 {
773 model =
774 new DocumentDescriptorReader( project, getLog() ).readAndFilterDocumentDescriptor( docDescriptor );
775 }
776 catch ( XmlPullParserException ex )
777 {
778 throw new MojoExecutionException( "Error reading DocumentDescriptor!", ex );
779 }
780 catch ( IOException io )
781 {
782 throw new MojoExecutionException( "Error opening DocumentDescriptor!", io );
783 }
784
785 if ( StringUtils.isEmpty( model.getMeta().getLanguage() ) )
786 {
787 model.getMeta().setLanguage( locale.getLanguage() );
788 }
789
790 if ( StringUtils.isEmpty( model.getMeta().getGenerator() ) )
791 {
792 model.getMeta().setGenerator( getDefaultGenerator() );
793 }
794
795 return model;
796 }
797
798
799
800
801
802
803
804 private File getWorkingDirectory( Locale locale )
805 {
806 if ( locale.getLanguage().equals( getDefaultLocale().getLanguage() ) )
807 {
808 return workingDirectory;
809 }
810
811 return new File( workingDirectory, locale.getLanguage() );
812 }
813
814
815
816
817
818 private Locale getDefaultLocale()
819 {
820 if ( this.defaultLocale == null )
821 {
822 this.defaultLocale = (Locale) getAvailableLocales().get( 0 );
823 }
824
825 return this.defaultLocale;
826 }
827
828
829
830
831
832 private List getAvailableLocales()
833 {
834 if ( this.localesList == null )
835 {
836 this.localesList = siteTool.getAvailableLocales( locales );
837 }
838
839 return this.localesList;
840 }
841
842
843
844
845
846 private DecorationModel getDefaultDecorationModel()
847 throws MojoExecutionException
848 {
849 if ( this.defaultDecorationModel == null )
850 {
851 final Locale locale = getDefaultLocale();
852
853 final File basedir = project.getBasedir();
854 final String relativePath =
855 siteTool.getRelativePath( siteDirectory.getAbsolutePath(), basedir.getAbsolutePath() );
856
857 final File descriptorFile = siteTool.getSiteDescriptorFromBasedir( relativePath, basedir, locale );
858 DecorationModel decoration = null;
859
860 if ( descriptorFile.exists() )
861 {
862 XmlStreamReader reader = null;
863 try
864 {
865 reader = ReaderFactory.newXmlReader( descriptorFile );
866 String enc = reader.getEncoding();
867
868 String siteDescriptorContent = IOUtil.toString( reader );
869 siteDescriptorContent =
870 siteTool.getInterpolatedSiteDescriptorContent( new HashMap(), project,
871 siteDescriptorContent, enc, enc );
872
873 decoration = new DecorationXpp3Reader().read( new StringReader( siteDescriptorContent ) );
874 }
875 catch ( XmlPullParserException e )
876 {
877 throw new MojoExecutionException( "Error parsing site descriptor", e );
878 }
879 catch ( IOException e )
880 {
881 throw new MojoExecutionException( "Error reading site descriptor", e );
882 }
883 catch ( SiteToolException e )
884 {
885 throw new MojoExecutionException( "Error when interpoling site descriptor", e );
886 }
887 finally
888 {
889 IOUtil.close( reader );
890 }
891 }
892
893 this.defaultDecorationModel = decoration;
894 }
895
896 return this.defaultDecorationModel;
897 }
898
899
900
901
902
903
904
905
906 private void copyResources( Locale locale )
907 throws MojoExecutionException
908 {
909 final DecorationModel decorationModel = getDefaultDecorationModel();
910 if ( decorationModel == null )
911 {
912 return;
913 }
914
915 File skinFile;
916 try
917 {
918 skinFile =
919 siteTool.getSkinArtifactFromRepository( localRepository, project.getRemoteArtifactRepositories(),
920 decorationModel ).getFile();
921 }
922 catch ( SiteToolException e )
923 {
924 throw new MojoExecutionException( "SiteToolException: " + e.getMessage(), e );
925 }
926
927 if ( skinFile == null )
928 {
929 return;
930 }
931
932 if ( getLog().isDebugEnabled() )
933 {
934 getLog().debug( "Copy resources from skin artifact: '" + skinFile + "'..." );
935 }
936
937 try
938 {
939 final SiteRenderingContext context =
940 siteRenderer.createContextForSkin( skinFile, new HashMap(), decorationModel, project.getName(),
941 locale );
942 context.addSiteDirectory( new File( siteDirectory, locale.getLanguage() ) );
943
944 for ( final Iterator i = context.getSiteDirectories().iterator(); i.hasNext(); )
945 {
946 final File siteDirectoryFile = (File) i.next();
947
948 siteRenderer.copyResources( context, new File( siteDirectoryFile, "resources" ), workingDirectory );
949 }
950 }
951 catch ( IOException e )
952 {
953 throw new MojoExecutionException( "IOException: " + e.getMessage(), e );
954 }
955 }
956
957
958
959
960
961
962 private String getDefaultGenerator()
963 {
964 return "Maven PDF Plugin v. " + pluginVersion + ", '" + implementation + "' implementation.";
965 }
966
967
968
969
970
971
972 private void debugLogGeneratedModel( final DocumentModel docModel )
973 {
974 if ( getLog().isDebugEnabled() && project != null )
975 {
976 final File outputDir = new File( project.getBuild().getDirectory(), "pdf" );
977
978 if ( !outputDir.exists() )
979 {
980 outputDir.mkdirs();
981 }
982
983 final File doc = FileUtils.createTempFile( "pdf", ".xml", outputDir );
984 final DocumentXpp3Writer xpp3 = new DocumentXpp3Writer();
985
986 Writer w = null;
987 try
988 {
989 w = WriterFactory.newXmlWriter( doc );
990 xpp3.write( w, docModel );
991
992 if ( getLog().isDebugEnabled() )
993 {
994 getLog().debug( "Generated a default document model: " + doc.getAbsolutePath() );
995 }
996 }
997 catch ( IOException e )
998 {
999 if ( getLog().isDebugEnabled() )
1000 {
1001 getLog().error( "Failed to write document model: " + e.getMessage(), e );
1002 }
1003 else
1004 {
1005 getLog().error( "Failed to write document model: " + e.getMessage() );
1006 }
1007 }
1008 finally
1009 {
1010 IOUtil.close( w );
1011 }
1012 }
1013 }
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024 private void generateMavenReports( Locale locale )
1025 throws MojoExecutionException, IOException
1026 {
1027 if ( !includeReports )
1028 {
1029 if ( getLog().isInfoEnabled() )
1030 {
1031 getLog().info( "Skipped report generation." );
1032 }
1033
1034 return;
1035 }
1036
1037 if ( project.getReporting() == null )
1038 {
1039 if ( getLog().isInfoEnabled() )
1040 {
1041 getLog().info( "No report was specified." );
1042 }
1043 return;
1044 }
1045
1046 for ( final Iterator it = project.getReporting().getPlugins().iterator(); it.hasNext(); )
1047 {
1048 final ReportPlugin reportPlugin = (ReportPlugin) it.next();
1049
1050 final PluginDescriptor pluginDescriptor = getPluginDescriptor( reportPlugin );
1051
1052 List goals = new ArrayList();
1053 for ( final Iterator it2 = reportPlugin.getReportSets().iterator(); it2.hasNext(); )
1054 {
1055 final ReportSet reportSet = (ReportSet) it2.next();
1056
1057 for ( final Iterator it3 = reportSet.getReports().iterator(); it3.hasNext(); )
1058 {
1059 goals.add( it3.next().toString() );
1060 }
1061 }
1062
1063 List mojoDescriptors = pluginDescriptor.getMojos();
1064 for ( final Iterator it2 = mojoDescriptors.iterator(); it2.hasNext(); )
1065 {
1066 final MojoDescriptor mojoDescriptor = (MojoDescriptor) it2.next();
1067
1068 if ( goals.isEmpty() || ( !goals.isEmpty() && goals.contains( mojoDescriptor.getGoal() ) ) )
1069 {
1070 MavenReport report = getMavenReport( mojoDescriptor );
1071
1072 generateMavenReport( mojoDescriptor, report, locale );
1073 }
1074 }
1075 }
1076
1077
1078 if ( !getGeneratedMavenReports( locale ).isEmpty() )
1079 {
1080 File outDir = new File( getGeneratedSiteDirectoryTmp(), "xdoc" );
1081 if ( !locale.getLanguage().equals( defaultLocale.getLanguage() ) )
1082 {
1083 outDir = new File( new File( getGeneratedSiteDirectoryTmp(), locale.getLanguage() ), "xdoc" );
1084 }
1085 outDir.mkdirs();
1086
1087 File piReport = new File( outDir, "project-info.xml" );
1088
1089 StringWriter sw = new StringWriter();
1090
1091 PdfSink sink = new PdfSink( sw );
1092 ProjectInfoRenderer r = new ProjectInfoRenderer( sink, getGeneratedMavenReports( locale ), i18n, locale );
1093 r.render();
1094
1095 writeGeneratedReport( sw.toString(), piReport );
1096 }
1097
1098
1099 copySiteDir( getGeneratedSiteDirectoryTmp(), getSiteDirectoryTmp() );
1100 copySiteDir( generatedSiteDirectory, getSiteDirectoryTmp() );
1101 }
1102
1103
1104
1105
1106
1107
1108
1109 private PluginDescriptor getPluginDescriptor( ReportPlugin reportPlugin )
1110 throws MojoExecutionException
1111 {
1112 try
1113 {
1114 return pluginManager.verifyReportPlugin( reportPlugin, project, session );
1115 }
1116 catch ( ArtifactResolutionException e )
1117 {
1118 throw new MojoExecutionException( "ArtifactResolutionException: " + e.getMessage(), e );
1119 }
1120 catch ( ArtifactNotFoundException e )
1121 {
1122 throw new MojoExecutionException( "ArtifactNotFoundException: " + e.getMessage(), e );
1123 }
1124 catch ( PluginNotFoundException e )
1125 {
1126 throw new MojoExecutionException( "PluginNotFoundException: " + e.getMessage(), e );
1127 }
1128 catch ( PluginVersionResolutionException e )
1129 {
1130 throw new MojoExecutionException( "PluginVersionResolutionException: " + e.getMessage(), e );
1131 }
1132 catch ( InvalidVersionSpecificationException e )
1133 {
1134 throw new MojoExecutionException( "InvalidVersionSpecificationException: " + e.getMessage(), e );
1135 }
1136 catch ( InvalidPluginException e )
1137 {
1138 throw new MojoExecutionException( "InvalidPluginException: " + e.getMessage(), e );
1139 }
1140 catch ( PluginManagerException e )
1141 {
1142 throw new MojoExecutionException( "PluginManagerException: " + e.getMessage(), e );
1143 }
1144 catch ( PluginVersionNotFoundException e )
1145 {
1146 throw new MojoExecutionException( "PluginVersionNotFoundException: " + e.getMessage(), e );
1147 }
1148 }
1149
1150
1151
1152
1153
1154
1155
1156 private MavenReport getMavenReport( MojoDescriptor mojoDescriptor )
1157 throws MojoExecutionException
1158 {
1159 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
1160 try
1161 {
1162 Thread.currentThread()
1163 .setContextClassLoader( mojoDescriptor.getPluginDescriptor().getClassRealm().getClassLoader() );
1164
1165 MojoExecution mojoExecution = new MojoExecution( mojoDescriptor );
1166
1167 return pluginManager.getReport( project, mojoExecution, session );
1168 }
1169 catch ( ArtifactNotFoundException e )
1170 {
1171 throw new MojoExecutionException( "ArtifactNotFoundException: " + e.getMessage(), e );
1172 }
1173 catch ( ArtifactResolutionException e )
1174 {
1175 throw new MojoExecutionException( "ArtifactResolutionException: " + e.getMessage(), e );
1176 }
1177 catch ( PluginConfigurationException e )
1178 {
1179 throw new MojoExecutionException( "PluginConfigurationException: " + e.getMessage(), e );
1180 }
1181 catch ( PluginManagerException e )
1182 {
1183 throw new MojoExecutionException( "PluginManagerException: " + e.getMessage(), e );
1184 }
1185 finally
1186 {
1187 Thread.currentThread().setContextClassLoader( oldClassLoader );
1188 }
1189 }
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202 private void generateMavenReport( MojoDescriptor mojoDescriptor, MavenReport report, Locale locale )
1203 throws IOException, MojoExecutionException
1204 {
1205 if ( report == null )
1206 {
1207 return;
1208 }
1209
1210 String localReportName = report.getName( locale );
1211 if ( !report.canGenerateReport() )
1212 {
1213 if ( getLog().isInfoEnabled() )
1214 {
1215 getLog().info( "Skipped \"" + localReportName + "\" report." );
1216 }
1217 if ( getLog().isDebugEnabled() )
1218 {
1219 getLog().debug( "canGenerateReport() was false." );
1220 }
1221
1222 return;
1223 }
1224
1225 if ( report.isExternalReport() )
1226 {
1227 if ( getLog().isInfoEnabled() )
1228 {
1229 getLog().info( "Skipped external \"" + localReportName + "\" report." );
1230 }
1231 if ( getLog().isDebugEnabled() )
1232 {
1233 getLog().debug( "isExternalReport() was false." );
1234 }
1235
1236 return;
1237 }
1238
1239 for ( final Iterator it = getGeneratedMavenReports( locale ).iterator(); it.hasNext(); )
1240 {
1241 MavenReport generatedReport = (MavenReport) it.next();
1242
1243 if ( report.getName( locale ).equals( generatedReport.getName( locale ) ) )
1244 {
1245 if ( getLog().isDebugEnabled() )
1246 {
1247 getLog().debug( report.getName( locale ) + " was already generated." );
1248 }
1249 return;
1250 }
1251 }
1252
1253 File outDir = new File( getGeneratedSiteDirectoryTmp(), "xdoc" );
1254 if ( !locale.getLanguage().equals( defaultLocale.getLanguage() ) )
1255 {
1256 outDir = new File( new File( getGeneratedSiteDirectoryTmp(), locale.getLanguage() ), "xdoc" );
1257 }
1258 outDir.mkdirs();
1259
1260 File generatedReport = new File( outDir, report.getOutputName() + ".xml" );
1261
1262 String excludes = getDefaultExcludesWithLocales( getAvailableLocales(), getDefaultLocale() );
1263 List files = FileUtils.getFileNames( siteDirectory, "*/" + report.getOutputName() + ".*", excludes, false );
1264 if ( !locale.getLanguage().equals( defaultLocale.getLanguage() ) )
1265 {
1266 files =
1267 FileUtils.getFileNames( new File( siteDirectory, locale.getLanguage() ), "*/"
1268 + report.getOutputName() + ".*", excludes, false );
1269 }
1270
1271 if ( files.size() != 0 )
1272 {
1273 String displayLanguage = locale.getDisplayLanguage( Locale.ENGLISH );
1274
1275 if ( getLog().isInfoEnabled() )
1276 {
1277 getLog().info(
1278 "Skipped \"" + report.getName( locale ) + "\" report, file \""
1279 + report.getOutputName() + "\" already exists for the " + displayLanguage
1280 + " version." );
1281 }
1282
1283 return;
1284 }
1285
1286 if ( getLog().isInfoEnabled() )
1287 {
1288 getLog().info( "Generating \"" + localReportName + "\" report." );
1289 }
1290
1291 StringWriter sw = new StringWriter();
1292
1293 PdfSink sink = null;
1294 try
1295 {
1296 sink = new PdfSink( sw );
1297 org.codehaus.doxia.sink.Sink proxy =
1298 (org.codehaus.doxia.sink.Sink) Proxy
1299 .newProxyInstance(
1300 org.codehaus.doxia.sink.Sink.class
1301 .getClassLoader(),
1302 new Class[] { org.codehaus.doxia.sink.Sink.class },
1303 new SinkDelegate( sink ) );
1304 report.generate( proxy, locale );
1305 }
1306 catch ( MavenReportException e )
1307 {
1308 throw new MojoExecutionException( "MavenReportException: " + e.getMessage(), e );
1309 }
1310 catch ( LinkageError e )
1311 {
1312 if ( getLog().isErrorEnabled() )
1313 {
1314 ClassRealm reportPluginRealm = mojoDescriptor.getPluginDescriptor().getClassRealm();
1315 StringBuffer sb = new StringBuffer();
1316 sb.append( report.getClass().getName() ).append( "#generate(...) caused a linkage error (" );
1317 sb.append( e.getClass().getName() )
1318 .append( ") and may be out-of-date. Check the realms:" ).append( EOL );
1319 sb.append( "Maven Report Plugin realm = " + reportPluginRealm.getId() ).append( EOL );
1320 for ( int i = 0; i < reportPluginRealm.getConstituents().length; i++ )
1321 {
1322 sb.append( "urls[" + i + "] = " + reportPluginRealm.getConstituents()[i] );
1323 if ( i != ( reportPluginRealm.getConstituents().length - 1 ) )
1324 {
1325 sb.append( EOL );
1326 }
1327 }
1328
1329 getLog().error( sb.toString() );
1330 }
1331
1332 throw e;
1333 }
1334 finally
1335 {
1336 if ( sink != null )
1337 {
1338 sink.close();
1339 }
1340 }
1341
1342 writeGeneratedReport( sw.toString(), generatedReport );
1343
1344 if ( isValidGeneratedReport( mojoDescriptor, generatedReport, localReportName ) )
1345 {
1346 getGeneratedMavenReports( locale ).add( report );
1347 }
1348 }
1349
1350
1351
1352
1353
1354
1355
1356
1357 private List getGeneratedMavenReports( Locale locale )
1358 {
1359 if ( this.generatedMavenReports == null )
1360 {
1361 this.generatedMavenReports = new HashMap();
1362 }
1363
1364 if ( this.generatedMavenReports.get( locale ) == null )
1365 {
1366 this.generatedMavenReports.put( locale, new ArrayList() );
1367 }
1368
1369 return ( (List) this.generatedMavenReports.get( locale ) );
1370 }
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388 private void appendGeneratedReports( DocumentModel model, Locale locale )
1389 {
1390 if ( !includeReports )
1391 {
1392 return;
1393 }
1394 if ( getGeneratedMavenReports( locale ).isEmpty() )
1395 {
1396 return;
1397 }
1398
1399 final DocumentTOCItem documentTOCItem = new DocumentTOCItem();
1400 documentTOCItem.setName( i18n.getString( "pdf-plugin", locale, "toc.project-info.item" ) );
1401 documentTOCItem.setRef( "/project-info" );
1402
1403 List addedRef = new ArrayList();
1404
1405 List items = new ArrayList();
1406
1407
1408 for ( final Iterator it = getGeneratedMavenReports( locale ).iterator(); it.hasNext(); )
1409 {
1410 final MavenReport report = (MavenReport) it.next();
1411
1412 final DocumentTOCItem reportItem = new DocumentTOCItem();
1413 reportItem.setName( report.getName( locale ) );
1414 reportItem.setRef( "/" + report.getOutputName() );
1415
1416 items.add( reportItem );
1417
1418 addedRef.add( report.getOutputName() );
1419 }
1420
1421
1422 try
1423 {
1424 if ( generatedSiteDirectory.exists() )
1425 {
1426 String excludes = getDefaultExcludesWithLocales( getAvailableLocales(), getDefaultLocale() );
1427 List generatedDirs = FileUtils.getDirectoryNames( generatedSiteDirectory, "*", excludes, true );
1428 if ( !locale.getLanguage().equals( getDefaultLocale().getLanguage() ) )
1429 {
1430 generatedDirs =
1431 FileUtils.getFileNames( new File( generatedSiteDirectory, locale.getLanguage() ), "*",
1432 excludes, true );
1433 }
1434
1435 for ( final Iterator it = generatedDirs.iterator(); it.hasNext(); )
1436 {
1437 final String generatedDir = it.next().toString();
1438
1439 List generatedFiles =
1440 FileUtils.getFileNames( new File( generatedDir ), "**.*", excludes, false );
1441
1442 for ( final Iterator it2 = generatedFiles.iterator(); it2.hasNext(); )
1443 {
1444 final String generatedFile = it2.next().toString();
1445 final String ref = generatedFile.substring( 0, generatedFile.lastIndexOf( "." ) );
1446
1447 if ( !addedRef.contains( ref ) )
1448 {
1449 final String title =
1450 getGeneratedDocumentTitle( new File( generatedDir, generatedFile ) );
1451
1452 if ( title != null )
1453 {
1454 final DocumentTOCItem reportItem = new DocumentTOCItem();
1455 reportItem.setName( title );
1456 reportItem.setRef( "/" + ref );
1457
1458 items.add( reportItem );
1459 }
1460 }
1461 }
1462 }
1463 }
1464 }
1465 catch ( IOException e )
1466 {
1467 if ( getLog().isDebugEnabled() )
1468 {
1469 getLog().error( "IOException: " + e.getMessage(), e );
1470 }
1471 else
1472 {
1473 getLog().error( "IOException: " + e.getMessage() );
1474 }
1475 }
1476
1477
1478 documentTOCItem.setItems( items );
1479 model.getToc().addItem( documentTOCItem );
1480 }
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490 private String getGeneratedDocumentTitle( final File f )
1491 throws IOException
1492 {
1493 final IndexEntry entry = new IndexEntry( "index" );
1494 final IndexingSink titleSink = new IndexingSink( entry );
1495
1496 Reader reader = null;
1497 try
1498 {
1499 reader = ReaderFactory.newXmlReader( f );
1500
1501 doxia.parse( reader, f.getParentFile().getName(), titleSink );
1502 }
1503 catch ( ParseException e )
1504 {
1505 if ( getLog().isDebugEnabled() )
1506 {
1507 getLog().error( "ParseException: " + e.getMessage(), e );
1508 }
1509 else
1510 {
1511 getLog().error( "ParseException: " + e.getMessage() );
1512 }
1513 return null;
1514 }
1515 catch ( ParserNotFoundException e )
1516 {
1517 if ( getLog().isDebugEnabled() )
1518 {
1519 getLog().error( "ParserNotFoundException: " + e.getMessage(), e );
1520 }
1521 else
1522 {
1523 getLog().error( "ParserNotFoundException: " + e.getMessage() );
1524 }
1525 return null;
1526 }
1527 finally
1528 {
1529 IOUtil.close( reader );
1530 }
1531
1532 return titleSink.getTitle();
1533 }
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544 private boolean isValidGeneratedReport( MojoDescriptor mojoDescriptor, File generatedReport,
1545 String localReportName )
1546 {
1547 SinkAdapter sinkAdapter = new SinkAdapter();
1548 Reader reader = null;
1549 try
1550 {
1551 reader = ReaderFactory.newXmlReader( generatedReport );
1552
1553 doxia.parse( reader, generatedReport.getParentFile().getName(), sinkAdapter );
1554 }
1555 catch ( ParseException e )
1556 {
1557 StringBuffer sb = new StringBuffer();
1558
1559 sb.append( EOL ).append( EOL );
1560 sb.append( "Error when parsing the generated report: " ).append( generatedReport.getAbsolutePath() );
1561 sb.append( EOL );
1562 sb.append( e.getMessage() );
1563 sb.append( EOL ).append( EOL );
1564
1565 sb.append( "You could:" ).append( EOL );
1566 sb.append( " * exclude all reports using -DincludeReports=false" ).append( EOL );
1567 sb.append( " * remove the " );
1568 sb.append( mojoDescriptor.getPluginDescriptor().getGroupId() );
1569 sb.append( ":" );
1570 sb.append( mojoDescriptor.getPluginDescriptor().getArtifactId() );
1571 sb.append( ":" );
1572 sb.append( mojoDescriptor.getPluginDescriptor().getVersion() );
1573 sb.append( " from the <reporting/> part. To not affect the site generation, " );
1574 sb.append( "you could create a PDF profile." ).append( EOL );
1575 sb.append( EOL );
1576
1577 MavenProject pluginProject = getReportPluginProject( mojoDescriptor.getPluginDescriptor() );
1578
1579 if ( pluginProject == null )
1580 {
1581 sb.append( "You could also contact the Plugin team." ).append( EOL );
1582 }
1583 else
1584 {
1585 sb.append( "You could also contact the Plugin team:" ).append( EOL );
1586 if ( pluginProject.getMailingLists() != null && pluginProject.getMailingLists().size() != 0 )
1587 {
1588 boolean appended = false;
1589 for ( Iterator i = pluginProject.getMailingLists().iterator(); i.hasNext(); )
1590 {
1591 MailingList mailingList = (MailingList) i.next();
1592
1593 if ( StringUtils.isNotEmpty( mailingList.getName() )
1594 && StringUtils.isNotEmpty( mailingList.getPost() ) )
1595 {
1596 if ( !appended )
1597 {
1598 sb.append( " Mailing Lists:" ).append( EOL );
1599 appended = true;
1600 }
1601 sb.append( " " ).append( mailingList.getName() );
1602 sb.append( ": " ).append( mailingList.getPost() );
1603 sb.append( EOL );
1604 }
1605 }
1606 }
1607 if ( StringUtils.isNotEmpty( pluginProject.getUrl() ) )
1608 {
1609 sb.append( " Web Site:" ).append( EOL );
1610 sb.append( " " ).append( pluginProject.getUrl() );
1611 sb.append( EOL );
1612 }
1613 if ( pluginProject.getIssueManagement() != null
1614 && StringUtils.isNotEmpty( pluginProject.getIssueManagement().getUrl() ) )
1615 {
1616 sb.append( " Issue Tracking:" ).append( EOL );
1617 sb.append( " " ).append( pluginProject.getIssueManagement().getUrl() );
1618 sb.append( EOL );
1619 }
1620 }
1621
1622 sb.append( EOL ).append( "Ignoring the \"" + localReportName + "\" report in the PDF." ).append( EOL );
1623
1624 if ( getLog().isDebugEnabled() )
1625 {
1626 getLog().error( sb.toString(), e );
1627 }
1628 else
1629 {
1630 getLog().error( sb.toString() );
1631 }
1632
1633 return false;
1634 }
1635 catch ( ParserNotFoundException e )
1636 {
1637 if ( getLog().isDebugEnabled() )
1638 {
1639 getLog().error( "ParserNotFoundException: " + e.getMessage(), e );
1640 }
1641 else
1642 {
1643 getLog().error( "ParserNotFoundException: " + e.getMessage() );
1644 }
1645
1646 return false;
1647 }
1648 catch ( IOException e )
1649 {
1650 if ( getLog().isDebugEnabled() )
1651 {
1652 getLog().error( "IOException: " + e.getMessage(), e );
1653 }
1654 else
1655 {
1656 getLog().error( "IOException: " + e.getMessage() );
1657 }
1658
1659 return false;
1660 }
1661 finally
1662 {
1663 IOUtil.close( reader );
1664 }
1665
1666 return true;
1667 }
1668
1669
1670
1671
1672
1673
1674 private MavenProject getReportPluginProject( PluginDescriptor pluginDescriptor )
1675 {
1676 Artifact artifact =
1677 artifactFactory.createProjectArtifact( pluginDescriptor.getGroupId(),
1678 pluginDescriptor.getArtifactId(),
1679 pluginDescriptor.getVersion(), Artifact.SCOPE_COMPILE );
1680 try
1681 {
1682 return mavenProjectBuilder.buildFromRepository( artifact, remoteRepositories, localRepository );
1683 }
1684 catch ( ProjectBuildingException e )
1685 {
1686 if ( getLog().isDebugEnabled() )
1687 {
1688 getLog().error( "ProjectBuildingException: " + e.getMessage(), e );
1689 }
1690 else
1691 {
1692 getLog().error( "ProjectBuildingException: " + e.getMessage() );
1693 }
1694 }
1695
1696 return null;
1697 }
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713 private static void writeGeneratedReport( String content, File toFile )
1714 throws IOException
1715 {
1716 if ( StringUtils.isEmpty( content ) )
1717 {
1718 return;
1719 }
1720
1721
1722 content = StringUtils.replace( content, "<table><table", "<table" );
1723 Writer writer = null;
1724 try
1725 {
1726 writer = WriterFactory.newXmlWriter( toFile );
1727 writer.write( content );
1728 }
1729 finally
1730 {
1731 IOUtil.close( writer );
1732 }
1733 }
1734
1735
1736
1737
1738
1739
1740
1741
1742 private static String getDefaultExcludesWithLocales( List locales, Locale defaultLocale )
1743 {
1744 String excludesLocales = FileUtils.getDefaultExcludesAsString();
1745 for ( final Iterator it = locales.iterator(); it.hasNext(); )
1746 {
1747 final Locale locale = (Locale) it.next();
1748
1749 if ( !locale.getLanguage().equals( defaultLocale.getLanguage() ) )
1750 {
1751 excludesLocales = excludesLocales + ",**/" + locale.getLanguage() + "/*";
1752 }
1753 }
1754
1755 return excludesLocales;
1756 }
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767 private static class PdfSink
1768 extends XdocSink
1769 {
1770 protected PdfSink( Writer writer )
1771 {
1772 super( writer );
1773 }
1774
1775
1776 public void table()
1777 {
1778 super.table();
1779
1780
1781 writeStartTag( HtmlMarkup.TABLE );
1782 }
1783
1784
1785 public void text( String text )
1786 {
1787
1788 super.write( StringUtils.replace( text, "\u0092", "'" ) );
1789 }
1790 }
1791
1792
1793
1794
1795
1796
1797 private static class ProjectInfoRenderer
1798 extends AbstractMavenReportRenderer
1799 {
1800 private final List generatedReports;
1801
1802 private final I18N i18n;
1803
1804 private final Locale locale;
1805
1806 public ProjectInfoRenderer( Sink sink, List generatedReports, I18N i18n, Locale locale )
1807 {
1808 super( sink );
1809
1810 this.generatedReports = generatedReports;
1811 this.i18n = i18n;
1812 this.locale = locale;
1813 }
1814
1815
1816 public String getTitle()
1817 {
1818 return i18n.getString( "pdf-plugin", locale, "report.project-info.title" );
1819 }
1820
1821
1822 public void renderBody()
1823 {
1824 sink.section1();
1825 sink.sectionTitle1();
1826 sink.text( i18n.getString( "pdf-plugin", locale, "report.project-info.title" ) );
1827 sink.sectionTitle1_();
1828
1829 sink.paragraph();
1830 sink.text( i18n.getString( "pdf-plugin", locale, "report.project-info.description1" ) + " " );
1831 sink.link( "http://maven.apache.org" );
1832 sink.text( "Maven" );
1833 sink.link_();
1834 sink.text( " " + i18n.getString( "pdf-plugin", locale, "report.project-info.description2" ) );
1835 sink.paragraph_();
1836
1837 sink.section2();
1838 sink.sectionTitle2();
1839 sink.text( i18n.getString( "pdf-plugin", locale, "report.project-info.sectionTitle" ) );
1840 sink.sectionTitle2_();
1841
1842 sink.table();
1843
1844 sink.tableRows( new int[] { Sink.JUSTIFY_LEFT, Sink.JUSTIFY_LEFT }, false );
1845
1846 String name = i18n.getString( "pdf-plugin", locale, "report.project-info.column.document" );
1847 String description = i18n.getString( "pdf-plugin", locale, "report.project-info.column.description" );
1848
1849 sink.tableRow();
1850
1851 sink.tableHeaderCell( SinkEventAttributeSet.CENTER );
1852
1853 sink.text( name );
1854
1855 sink.tableHeaderCell_();
1856
1857 sink.tableHeaderCell( SinkEventAttributeSet.CENTER );
1858
1859 sink.text( description );
1860
1861 sink.tableHeaderCell_();
1862
1863 sink.tableRow_();
1864
1865 if ( generatedReports != null )
1866 {
1867 for ( final Iterator it = generatedReports.iterator(); it.hasNext(); )
1868 {
1869 final MavenReport report = (MavenReport) it.next();
1870
1871 sink.tableRow();
1872 sink.tableCell();
1873 sink.link( report.getOutputName() + ".html" );
1874 sink.text( report.getName( locale ) );
1875 sink.link_();
1876 sink.tableCell_();
1877 sink.tableCell();
1878 sink.text( report.getDescription( locale ) );
1879 sink.tableCell_();
1880 sink.tableRow_();
1881 }
1882 }
1883
1884 sink.tableRows_();
1885
1886 sink.table_();
1887
1888 sink.section2_();
1889
1890 sink.section1_();
1891 }
1892 }
1893
1894
1895
1896
1897
1898
1899
1900 private static class SinkDelegate
1901 implements InvocationHandler
1902 {
1903 private final Sink sink;
1904
1905 public SinkDelegate( Sink sink )
1906 {
1907 this.sink = sink;
1908 }
1909
1910
1911 public Object invoke( Object proxy, Method method, Object[] args )
1912 throws Throwable
1913 {
1914 Class[] parameterTypes = method.getParameterTypes();
1915
1916 for ( int i = parameterTypes.length - 1; i >= 0; i-- )
1917 {
1918 if ( AttributeSet.class.isAssignableFrom( parameterTypes[i] ) )
1919 {
1920 parameterTypes[i] = SinkEventAttributes.class;
1921 }
1922 }
1923
1924 if ( args != null )
1925 {
1926 for ( int i = args.length - 1; i >= 0; i-- )
1927 {
1928 if ( AttributeSet.class.isInstance( args[i] ) )
1929 {
1930 args[i] = new SinkEventAttributeSet( (AttributeSet) args[i] );
1931 }
1932 }
1933 }
1934
1935 Method target = Sink.class.getMethod( method.getName(), parameterTypes );
1936
1937 return target.invoke( sink, args );
1938 }
1939 }
1940 }