| package org.apache.maven.plugins.pdf; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.Reader; |
| import java.io.StringReader; |
| import java.io.StringWriter; |
| import java.io.Writer; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.Properties; |
| |
| import org.apache.commons.io.input.XmlStreamReader; |
| import org.apache.maven.artifact.Artifact; |
| import org.apache.maven.artifact.repository.ArtifactRepository; |
| import org.apache.maven.artifact.versioning.ArtifactVersion; |
| import org.apache.maven.artifact.versioning.DefaultArtifactVersion; |
| import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; |
| import org.apache.maven.artifact.versioning.VersionRange; |
| import org.apache.maven.doxia.Doxia; |
| import org.apache.maven.doxia.docrenderer.AbstractDocumentRenderer; |
| import org.apache.maven.doxia.docrenderer.DocumentRenderer; |
| import org.apache.maven.doxia.docrenderer.DocumentRendererContext; |
| import org.apache.maven.doxia.docrenderer.DocumentRendererException; |
| import org.apache.maven.doxia.docrenderer.pdf.PdfRenderer; |
| import org.apache.maven.doxia.document.DocumentMeta; |
| import org.apache.maven.doxia.document.DocumentModel; |
| import org.apache.maven.doxia.document.DocumentTOC; |
| import org.apache.maven.doxia.document.DocumentTOCItem; |
| import org.apache.maven.doxia.document.io.xpp3.DocumentXpp3Writer; |
| import org.apache.maven.doxia.index.IndexEntry; |
| import org.apache.maven.doxia.index.IndexingSink; |
| import org.apache.maven.doxia.module.xdoc.XdocSink; |
| import org.apache.maven.doxia.parser.ParseException; |
| import org.apache.maven.doxia.parser.manager.ParserNotFoundException; |
| import org.apache.maven.doxia.sink.Sink; |
| import org.apache.maven.doxia.sink.impl.SinkAdapter; |
| import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet; |
| import org.apache.maven.doxia.site.decoration.DecorationModel; |
| import org.apache.maven.doxia.site.decoration.io.xpp3.DecorationXpp3Reader; |
| import org.apache.maven.doxia.siterenderer.Renderer; |
| import org.apache.maven.doxia.siterenderer.RendererException; |
| import org.apache.maven.doxia.siterenderer.SiteRenderingContext; |
| import org.apache.maven.doxia.tools.SiteTool; |
| import org.apache.maven.doxia.tools.SiteToolException; |
| import org.apache.maven.execution.MavenSession; |
| import org.apache.maven.model.ReportPlugin; |
| import org.apache.maven.model.Reporting; |
| import org.apache.maven.plugin.MojoExecutionException; |
| import org.apache.maven.plugin.MojoFailureException; |
| import org.apache.maven.plugin.PluginManager; |
| import org.apache.maven.plugins.annotations.Component; |
| import org.apache.maven.plugins.annotations.Mojo; |
| import org.apache.maven.plugins.annotations.Parameter; |
| import org.apache.maven.plugins.annotations.ResolutionScope; |
| import org.apache.maven.project.MavenProject; |
| import org.apache.maven.project.MavenProjectBuilder; |
| import org.apache.maven.reporting.AbstractMavenReportRenderer; |
| import org.apache.maven.reporting.MavenReport; |
| import org.apache.maven.reporting.MavenReportException; |
| import org.apache.maven.reporting.exec.MavenReportExecution; |
| import org.apache.maven.reporting.exec.MavenReportExecutor; |
| import org.apache.maven.reporting.exec.MavenReportExecutorRequest; |
| import org.apache.maven.settings.Settings; |
| import org.codehaus.plexus.PlexusConstants; |
| import org.codehaus.plexus.PlexusContainer; |
| import org.codehaus.plexus.component.repository.exception.ComponentLookupException; |
| import org.codehaus.plexus.context.Context; |
| import org.codehaus.plexus.context.ContextException; |
| import org.codehaus.plexus.i18n.I18N; |
| import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable; |
| import org.codehaus.plexus.util.FileUtils; |
| import org.codehaus.plexus.util.IOUtil; |
| import org.codehaus.plexus.util.PathTool; |
| import org.codehaus.plexus.util.ReaderFactory; |
| import org.codehaus.plexus.util.StringUtils; |
| import org.codehaus.plexus.util.WriterFactory; |
| import org.codehaus.plexus.util.xml.pull.XmlPullParserException; |
| |
| /** |
| * Generates a PDF document for a project documentation usually published as web site (with maven-site-plugin). |
| * |
| * @author ltheussl |
| */ |
| @Mojo( name = "pdf", requiresDependencyResolution = ResolutionScope.TEST, threadSafe = true ) |
| public class PdfMojo |
| extends AbstractPdfMojo implements Contextualizable |
| { |
| |
| /** |
| * The vm line separator |
| */ |
| private static final String EOL = System.getProperty( "line.separator" ); |
| |
| // ---------------------------------------------------------------------- |
| // Mojo components |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * FO Document Renderer. |
| */ |
| @Component( hint = "fo" ) |
| private PdfRenderer foRenderer; |
| |
| /** |
| * Internationalization. |
| */ |
| @Component |
| private I18N i18n; |
| |
| /** |
| * IText Document Renderer. |
| */ |
| @Component( hint = "itext" ) |
| private PdfRenderer itextRenderer; |
| |
| /** |
| * A comma separated list of locales supported by Maven. |
| * The first valid token will be the default Locale for this instance of the Java Virtual Machine. |
| */ |
| @Parameter( property = "locales" ) |
| private String locales; |
| |
| /** |
| * Site renderer. |
| */ |
| @Component |
| private Renderer siteRenderer; |
| |
| /** |
| * SiteTool. |
| */ |
| @Component |
| private SiteTool siteTool; |
| |
| /** |
| * The Plugin manager instance used to resolve Plugin descriptors. |
| * |
| * @since 1.1 |
| */ |
| @Component( role = PluginManager.class ) |
| private PluginManager pluginManager; |
| |
| /** |
| * Doxia. |
| * |
| * @since 1.1 |
| */ |
| @Component |
| private Doxia doxia; |
| |
| /** |
| * Project builder. |
| * |
| * @since 1.1 |
| */ |
| @Component |
| private MavenProjectBuilder mavenProjectBuilder; |
| |
| // ---------------------------------------------------------------------- |
| // Mojo Parameters |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * The Maven Project Object. |
| */ |
| @Parameter( defaultValue = "${project}", readonly = true, required = true ) |
| protected MavenProject project; |
| |
| /** |
| * The Maven Settings. |
| * |
| * @since 1.1 |
| */ |
| @Parameter( defaultValue = "${settings}", readonly = true, required = true ) |
| private Settings settings; |
| |
| /** |
| * The current build session instance. |
| * |
| * @since 1.1 |
| */ |
| @Parameter( defaultValue = "${session}", readonly = true, required = true ) |
| private MavenSession session; |
| |
| /** |
| * Directory containing source for apt, fml and xdoc docs. |
| */ |
| @Parameter( defaultValue = "${basedir}/src/site", required = true ) |
| private File siteDirectory; |
| |
| /** |
| * Directory containing generated sources for apt, fml and xdoc docs. |
| * |
| * @since 1.1 |
| */ |
| @Parameter( defaultValue = "${project.build.directory}/generated-site", required = true ) |
| private File generatedSiteDirectory; |
| |
| /** |
| * Output directory where PDF files should be created. |
| */ |
| @Parameter( defaultValue = "${project.build.directory}/pdf", required = true ) |
| private File outputDirectory; |
| |
| /** |
| * Working directory for working files like temp files/resources. |
| */ |
| @Parameter( defaultValue = "${project.build.directory}/pdf", required = true ) |
| private File workingDirectory; |
| |
| /** |
| * File that contains the DocumentModel of the PDF to generate. |
| */ |
| @Parameter( defaultValue = "src/site/pdf.xml" ) |
| private File docDescriptor; |
| |
| /** |
| * Identifies the framework to use for pdf generation: either "fo" (default) or "itext". |
| */ |
| @Parameter( property = "implementation", defaultValue = "fo", required = true ) |
| private String implementation; |
| |
| /** |
| * The local repository. |
| */ |
| @Parameter( defaultValue = "${localRepository}", required = true, readonly = true ) |
| private ArtifactRepository localRepository; |
| |
| /** |
| * The remote repositories where artifacts are located. |
| * |
| * @since 1.1 |
| */ |
| @Parameter( defaultValue = "${project.remoteArtifactRepositories}" ) |
| private List<ArtifactRepository> remoteRepositories; |
| |
| /** |
| * If <code>true</false>, aggregate all source documents in one pdf, otherwise generate one pdf for each |
| * source document. |
| */ |
| @Parameter( property = "aggregate", defaultValue = "true" ) |
| private boolean aggregate; |
| |
| /** |
| * The current version of this plugin. |
| */ |
| @Parameter( defaultValue = "${plugin.version}", readonly = true ) |
| private String pluginVersion; |
| |
| /** |
| * If <code>true</false>, generate all Maven reports defined in <code>${project.reporting}</code> and append |
| * them as a new entry in the TOC (Table Of Contents). |
| * <b>Note</b>: Including the report generation could fail the PDF generation or increase the build time. |
| * |
| * @since 1.1 |
| */ |
| @Parameter( property = "includeReports", defaultValue = "true" ) |
| private boolean includeReports; |
| |
| /** |
| * Generate a TOC (Table Of Content) for all items defined in the <toc/> element from the document descriptor. |
| * <br/> |
| * Possible values are: 'none', 'start' and 'end'. |
| * |
| * @since 1.1 |
| */ |
| @Parameter( property = "generateTOC", defaultValue = "start" ) |
| private String generateTOC; |
| |
| /** |
| * Whether to validate xml input documents. |
| * If set to true, <strong>all</strong> input documents in xml format |
| * (in particular xdoc and fml) will be validated and any error will |
| * lead to a build failure. |
| * |
| * @since 1.2 |
| */ |
| @Parameter( property = "validate", defaultValue = "false" ) |
| private boolean validate; |
| |
| /** |
| * Reports (Maven 2). |
| * |
| * @since 1.3 |
| */ |
| @Parameter( defaultValue = "${reports}", required = true, readonly = true ) |
| private MavenReport[] reports; |
| |
| /** |
| * Reports (Maven 3). |
| * |
| * @since 1.5 |
| */ |
| @Parameter( defaultValue = "${project.reporting}", readonly = true ) |
| private Reporting reporting; |
| |
| // ---------------------------------------------------------------------- |
| // Instance fields |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * The current document Renderer. |
| * @see #implementation |
| */ |
| private DocumentRenderer docRenderer; |
| |
| /** |
| * The default locale. |
| */ |
| private Locale defaultLocale; |
| |
| /** |
| * The available locales list. |
| */ |
| private List<Locale> localesList; |
| |
| /** |
| * The default decoration model. |
| */ |
| private DecorationModel defaultDecorationModel; |
| |
| /** |
| * The temp Generated Site dir to have generated reports by this plugin. |
| * |
| * @since 1.1 |
| */ |
| private File generatedSiteDirectoryTmp; |
| |
| /** |
| * A map of generated MavenReport list using locale as key. |
| * |
| * @since 1.1 |
| */ |
| private Map<Locale, List<MavenReport>> generatedMavenReports; |
| |
| /** |
| * @since 1.3 |
| */ |
| private PlexusContainer container; |
| |
| // ---------------------------------------------------------------------- |
| // Public methods |
| // ---------------------------------------------------------------------- |
| |
| /** {@inheritDoc} */ |
| public void execute() |
| throws MojoExecutionException, MojoFailureException |
| { |
| init(); |
| |
| try |
| { |
| generatePdf(); |
| } |
| catch ( IOException e ) |
| { |
| debugLogGeneratedModel( getDocumentModel( Locale.ENGLISH ) ); |
| |
| throw new MojoExecutionException( "Error during document generation: " + e.getMessage(), e ); |
| } |
| |
| try |
| { |
| copyGeneratedPdf(); |
| } |
| catch ( IOException e ) |
| { |
| throw new MojoExecutionException( "Error copying generated PDF: " + e.getMessage(), e ); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void contextualize( Context context ) |
| throws ContextException |
| { |
| container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY ); |
| } |
| |
| protected File getOutputDirectory() |
| { |
| return outputDirectory; |
| } |
| |
| protected File getWorkingDirectory() |
| { |
| return workingDirectory; |
| } |
| |
| protected boolean isIncludeReports() |
| { |
| return includeReports; |
| } |
| |
| // ---------------------------------------------------------------------- |
| // Private methods |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * Init and validate parameters |
| */ |
| private void init() |
| { |
| if ( "fo".equalsIgnoreCase( implementation ) ) |
| { |
| this.docRenderer = foRenderer; |
| } |
| else if ( "itext".equalsIgnoreCase( implementation ) ) |
| { |
| this.docRenderer = itextRenderer; |
| } |
| else |
| { |
| getLog().warn( "Invalid 'implementation' parameter: '" + implementation |
| + "', using 'fo' as default." ); |
| |
| this.docRenderer = foRenderer; |
| } |
| |
| if ( !( "none".equalsIgnoreCase( generateTOC ) |
| || "start".equalsIgnoreCase( generateTOC ) || "end".equalsIgnoreCase( generateTOC ) ) ) |
| { |
| getLog().warn( "Invalid 'generateTOC' parameter: '" + generateTOC |
| + "', using 'start' as default." ); |
| |
| this.generateTOC = "start"; |
| } |
| } |
| |
| /** |
| * Copy the generated PDF to outputDirectory. |
| * |
| * @throws MojoExecutionException if any |
| * @throws IOException if any |
| * @since 1.1 |
| */ |
| private void copyGeneratedPdf() |
| throws MojoExecutionException, IOException |
| { |
| boolean requireCopy = |
| !getOutputDirectory().getCanonicalPath().equals( getWorkingDirectory().getCanonicalPath() ); |
| |
| String outputName = getDocumentModel( getDefaultLocale() ).getOutputName().trim(); |
| if ( !outputName.endsWith( ".pdf" ) ) |
| { |
| outputName = outputName.concat( ".pdf" ); |
| } |
| |
| for ( final Locale locale : getAvailableLocales() ) |
| { |
| File generatedPdfSource = new File( getLocaleDirectory( getWorkingDirectory(), locale ), outputName ); |
| |
| if ( !generatedPdfSource.exists() ) |
| { |
| getLog().warn( "Unable to find the generated pdf: " + generatedPdfSource.getAbsolutePath() ); |
| continue; |
| } |
| |
| File generatedPdfDest = new File( getLocaleDirectory( getOutputDirectory(), locale ), outputName ); |
| |
| if ( requireCopy ) |
| { |
| FileUtils.copyFile( generatedPdfSource, generatedPdfDest ); |
| generatedPdfSource.delete(); |
| } |
| |
| getLog().info( "pdf generated: " + generatedPdfDest ); |
| } |
| } |
| |
| /** |
| * Generate the PDF. |
| * |
| * @throws MojoExecutionException if any |
| * @throws IOException if any |
| * @since 1.1 |
| */ |
| private void generatePdf() |
| throws MojoExecutionException, IOException |
| { |
| Locale.setDefault( getDefaultLocale() ); |
| |
| for ( final Locale locale : getAvailableLocales() ) |
| { |
| final File workingDir = getLocaleDirectory( getWorkingDirectory(), locale ); |
| |
| File siteDirectoryFile = getLocaleDirectory( getSiteDirectoryTmp(), locale ); |
| |
| copyResources( locale ); |
| |
| // generated xdoc sources for reports |
| generateMavenReports( locale ); |
| |
| // render all Doxia source files to pdf (were handwritten or generated by reports) |
| DocumentRendererContext context = new DocumentRendererContext(); |
| context.put( "project", project ); |
| context.put( "settings", settings ); |
| context.put( "PathTool", new PathTool() ); |
| context.put( "FileUtils", new FileUtils() ); |
| context.put( "StringUtils", new StringUtils() ); |
| context.put( "i18n", i18n ); |
| context.put( "generateTOC", generateTOC ); |
| context.put( "validate", validate ); |
| |
| // Put any of the properties in directly into the Velocity context |
| for ( Map.Entry<Object, Object> entry : project.getProperties().entrySet() ) |
| { |
| context.put( (String) entry.getKey(), entry.getValue() ); |
| } |
| |
| final DocumentModel model = aggregate ? getDocumentModel( locale ) : null; |
| |
| try |
| { |
| // TODO use interface see DOXIASITETOOLS-30 |
| ( (AbstractDocumentRenderer) docRenderer ).render( siteDirectoryFile, workingDir, model, context ); |
| } |
| catch ( DocumentRendererException e ) |
| { |
| throw new MojoExecutionException( "Error during document generation: " + e.getMessage(), e ); |
| } |
| } |
| } |
| |
| /** |
| * @return the default tmpGeneratedSiteDirectory when report will be created. |
| * @since 1.1 |
| */ |
| private File getGeneratedSiteDirectoryTmp() |
| { |
| if ( this.generatedSiteDirectoryTmp == null ) |
| { |
| this.generatedSiteDirectoryTmp = new File( getWorkingDirectory(), "generated-site.tmp" ); |
| } |
| |
| return this.generatedSiteDirectoryTmp; |
| } |
| |
| /** |
| * Copy all site and generated-site files in the tmpSiteDirectory. |
| * <br/> |
| * <b>Note</b>: ignore copying of <code>generated-site</code> files if they already exist in the |
| * <code>site</code> dir. |
| * |
| * @param tmpSiteDir not null |
| * @throws IOException if any |
| * @since 1.1 |
| */ |
| protected void prepareTempSiteDirectory( final File tmpSiteDir ) |
| throws IOException |
| { |
| // safety |
| tmpSiteDir.mkdirs(); |
| |
| // copy site |
| if ( siteDirectory.exists() ) |
| { |
| FileUtils.copyDirectoryStructure( siteDirectory, tmpSiteDir ); |
| } |
| |
| // Remove SCM files |
| List<String> files = |
| FileUtils.getFileAndDirectoryNames( tmpSiteDir, FileUtils.getDefaultExcludesAsString(), null, true, |
| true, true, true ); |
| for ( final String fileName : files ) |
| { |
| final File file = new File( fileName ); |
| |
| if ( file.isDirectory() ) |
| { |
| FileUtils.deleteDirectory( file ); |
| } |
| else |
| { |
| file.delete(); |
| } |
| } |
| |
| copySiteDir( generatedSiteDirectory, tmpSiteDir ); |
| } |
| |
| /** |
| * Copy the from site dir to the to dir. |
| * |
| * @param from not null |
| * @param to not null |
| * @throws IOException if any |
| * @since 1.1 |
| */ |
| private void copySiteDir( final File from, final File to ) |
| throws IOException |
| { |
| if ( from == null || !from.exists() ) |
| { |
| return; |
| } |
| |
| // copy generated-site |
| for ( final Locale locale : getAvailableLocales() ) |
| { |
| String excludes = getDefaultExcludesWithLocales( getAvailableLocales(), getDefaultLocale() ); |
| List<String> siteFiles = |
| siteDirectory.exists() ? FileUtils.getFileNames( siteDirectory, "**/*", excludes, false ) |
| : new ArrayList<String>(); |
| File siteDirectoryLocale = new File( siteDirectory, locale.getLanguage() ); |
| if ( !locale.getLanguage().equals( getDefaultLocale().getLanguage() ) && siteDirectoryLocale.exists() ) |
| { |
| siteFiles = FileUtils.getFileNames( siteDirectoryLocale, "**/*", excludes, false ); |
| } |
| |
| List<String> generatedSiteFiles = FileUtils.getFileNames( from, "**/*", excludes, false ); |
| File fromLocale = new File( from, locale.getLanguage() ); |
| if ( !locale.getLanguage().equals( getDefaultLocale().getLanguage() ) && fromLocale.exists() ) |
| { |
| generatedSiteFiles = FileUtils.getFileNames( fromLocale, "**/*", excludes, false ); |
| } |
| |
| for ( final String generatedSiteFile : generatedSiteFiles ) |
| { |
| if ( siteFiles.contains( generatedSiteFile ) ) |
| { |
| getLog().warn( "Generated-site already contains a file in site: " + generatedSiteFile |
| + ". Ignoring copying it!" ); |
| continue; |
| } |
| |
| if ( !locale.getLanguage().equals( getDefaultLocale().getLanguage() ) ) |
| { |
| if ( fromLocale.exists() ) |
| { |
| File in = new File( fromLocale, generatedSiteFile ); |
| File out = new File( new File( to, locale.getLanguage() ), generatedSiteFile ); |
| out.getParentFile().mkdirs(); |
| FileUtils.copyFile( in, out ); |
| } |
| } |
| else |
| { |
| File in = new File( from, generatedSiteFile ); |
| File out = new File( to, generatedSiteFile ); |
| out.getParentFile().mkdirs(); |
| FileUtils.copyFile( in, out ); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Constructs a DocumentModel for the current project. The model is either read from |
| * a descriptor file, if it exists, or constructed from information in the pom and site.xml. |
| * |
| * @param locale not null |
| * @return DocumentModel. |
| * @throws MojoExecutionException if any |
| * @see #appendGeneratedReports(DocumentModel, Locale) |
| */ |
| private DocumentModel getDocumentModel( Locale locale ) |
| throws MojoExecutionException |
| { |
| if ( docDescriptor.exists() ) |
| { |
| DocumentModel doc = getDocumentModelFromDescriptor( locale ); |
| // TODO: descriptor model should get merged into default model, see MODELLO-63 |
| |
| appendGeneratedReports( doc, locale ); |
| |
| saveTOC( doc.getToc(), locale ); |
| |
| return doc; |
| } |
| |
| DocumentModel model = new DocumentModelBuilder( project, getDefaultDecorationModel() ).getDocumentModel(); |
| |
| model.getMeta().setGenerator( getDefaultGenerator() ); |
| model.getMeta().setLanguage( locale.getLanguage() ); |
| model.getCover().setCoverType( i18n.getString( "pdf-plugin", getDefaultLocale(), "toc.type" ) ); |
| model.getToc().setName( i18n.getString( "pdf-plugin", getDefaultLocale(), "toc.title" ) ); |
| |
| appendGeneratedReports( model, locale ); |
| |
| saveTOC( model.getToc(), locale ); |
| |
| debugLogGeneratedModel( model ); |
| |
| return model; |
| } |
| |
| /** |
| * Read a DocumentModel from a file. |
| * |
| * @param locale used to set the language. |
| * @return the DocumentModel read from the configured document descriptor. |
| * @throws org.apache.maven.plugin.MojoExecutionException if the model could not be read. |
| */ |
| private DocumentModel getDocumentModelFromDescriptor( Locale locale ) |
| throws MojoExecutionException |
| { |
| DocumentModel model; |
| |
| try |
| { |
| model = new DocumentDescriptorReader( project, getLog(), |
| locale ).readAndFilterDocumentDescriptor( docDescriptor ); |
| } |
| catch ( XmlPullParserException ex ) |
| { |
| throw new MojoExecutionException( "Error reading DocumentDescriptor!", ex ); |
| } |
| catch ( IOException io ) |
| { |
| throw new MojoExecutionException( "Error opening DocumentDescriptor!", io ); |
| } |
| |
| if ( model.getMeta() == null ) |
| { |
| model.setMeta( new DocumentMeta() ); |
| } |
| |
| if ( StringUtils.isEmpty( model.getMeta().getLanguage() ) ) |
| { |
| model.getMeta().setLanguage( locale.getLanguage() ); |
| } |
| |
| if ( StringUtils.isEmpty( model.getMeta().getGenerator() ) ) |
| { |
| model.getMeta().setGenerator( getDefaultGenerator() ); |
| } |
| |
| return model; |
| } |
| |
| /** |
| * Return the directory for a given Locale and the current default Locale. |
| * |
| * @param basedir the base directory |
| * @param locale a Locale. |
| * @return File. |
| */ |
| private File getLocaleDirectory( File basedir, Locale locale ) |
| { |
| if ( locale.getLanguage().equals( getDefaultLocale().getLanguage() ) ) |
| { |
| return basedir; |
| } |
| |
| return new File( basedir, locale.getLanguage() ); |
| } |
| |
| /** |
| * @return the default locale from <code>siteTool</code>. |
| * @see #getAvailableLocales() |
| */ |
| private Locale getDefaultLocale() |
| { |
| if ( this.defaultLocale == null ) |
| { |
| this.defaultLocale = getAvailableLocales().get( 0 ); |
| } |
| |
| return this.defaultLocale; |
| } |
| |
| /** |
| * @return the available locales from <code>siteTool</code>. |
| */ |
| private List<Locale> getAvailableLocales() |
| { |
| if ( this.localesList == null ) |
| { |
| this.localesList = siteTool.getSiteLocales( locales ); |
| } |
| |
| return this.localesList; |
| } |
| |
| /** |
| * @return the DecorationModel instance from <code>site.xml</code> |
| * @throws MojoExecutionException if any |
| */ |
| private DecorationModel getDefaultDecorationModel() |
| throws MojoExecutionException |
| { |
| if ( this.defaultDecorationModel == null ) |
| { |
| final Locale locale = getDefaultLocale(); |
| |
| final File descriptorFile = siteTool.getSiteDescriptor( siteDirectory, locale ); |
| DecorationModel decoration = null; |
| |
| if ( descriptorFile.exists() ) |
| { |
| try ( XmlStreamReader reader = new XmlStreamReader( descriptorFile ) ) |
| { |
| String siteDescriptorContent = IOUtil.toString( reader ); |
| |
| siteDescriptorContent = |
| siteTool.getInterpolatedSiteDescriptorContent( new HashMap<String, String>( 2 ), project, |
| siteDescriptorContent ); |
| |
| decoration = new DecorationXpp3Reader().read( new StringReader( siteDescriptorContent ) ); |
| } |
| catch ( XmlPullParserException e ) |
| { |
| throw new MojoExecutionException( "Error parsing site descriptor", e ); |
| } |
| catch ( IOException e ) |
| { |
| throw new MojoExecutionException( "Error reading site descriptor", e ); |
| } |
| catch ( SiteToolException e ) |
| { |
| throw new MojoExecutionException( "Error when interpoling site descriptor", e ); |
| } |
| } |
| |
| this.defaultDecorationModel = decoration; |
| } |
| |
| return this.defaultDecorationModel; |
| } |
| |
| /** |
| * Parse the decoration model to find the skin artifact and copy its resources to the output dir. |
| * |
| * @param locale not null |
| * @throws MojoExecutionException if any |
| * @see #getDefaultDecorationModel() |
| */ |
| private void copyResources( Locale locale ) |
| throws MojoExecutionException |
| { |
| final DecorationModel decorationModel = getDefaultDecorationModel(); |
| if ( decorationModel == null ) |
| { |
| return; |
| } |
| |
| Artifact skinArtifact; |
| try |
| { |
| skinArtifact = |
| siteTool.getSkinArtifactFromRepository( localRepository, project.getRemoteArtifactRepositories(), |
| decorationModel ); |
| } |
| catch ( SiteToolException e ) |
| { |
| throw new MojoExecutionException( "SiteToolException: " + e.getMessage(), e ); |
| } |
| |
| if ( skinArtifact == null ) |
| { |
| return; |
| } |
| |
| if ( getLog().isDebugEnabled() ) |
| { |
| getLog().debug( "Copy resources from skin artifact: '" + skinArtifact.getId() + "'..." ); |
| } |
| |
| try |
| { |
| final SiteRenderingContext context = |
| siteRenderer.createContextForSkin( skinArtifact, new HashMap<String, Object>( 2 ), decorationModel, |
| project.getName(), locale ); |
| context.addSiteDirectory( new File( siteDirectory, locale.getLanguage() ) ); |
| |
| siteRenderer.copyResources( context, getWorkingDirectory() ); |
| } |
| catch ( IOException e ) |
| { |
| throw new MojoExecutionException( "IOException: " + e.getMessage(), e ); |
| } |
| catch ( RendererException e ) |
| { |
| throw new MojoExecutionException( "RendererException: " + e.getMessage(), e ); |
| } |
| } |
| |
| /** |
| * Construct a default producer. |
| * |
| * @return A String in the form <code>Maven PDF Plugin v. 1.1.1, 'fo' implementation</code>. |
| */ |
| private String getDefaultGenerator() |
| { |
| return "Maven PDF Plugin v. " + pluginVersion + ", '" + implementation + "' implementation."; |
| } |
| |
| /** |
| * Write the auto-generated model to disc. |
| * |
| * @param docModel the model to write. |
| */ |
| private void debugLogGeneratedModel( final DocumentModel docModel ) |
| { |
| if ( getLog().isDebugEnabled() && project != null ) |
| { |
| final File outputDir = new File( project.getBuild().getDirectory(), "pdf" ); |
| |
| if ( !outputDir.exists() ) |
| { |
| outputDir.mkdirs(); |
| } |
| |
| final File doc = FileUtils.createTempFile( "pdf", ".xml", outputDir ); |
| final DocumentXpp3Writer xpp3 = new DocumentXpp3Writer(); |
| |
| try ( Writer writer = WriterFactory.newXmlWriter( doc ) ) |
| { |
| xpp3.write( writer, docModel ); |
| getLog().debug( "Generated a default document model: " + doc.getAbsolutePath() ); |
| } |
| catch ( IOException e ) |
| { |
| getLog().error( "Failed to write document model: " + e.getMessage() ); |
| getLog().debug( e ); |
| } |
| } |
| } |
| |
| /** |
| * Generate all Maven reports defined in <code>${project.reporting}</code> to <code>xdoc</code> source |
| * only if <code>generateReports</code> is enabled. |
| * |
| * @param locale not null |
| * @throws MojoExecutionException if any |
| * @throws IOException if any |
| * @since 1.1 |
| */ |
| private void generateMavenReports( Locale locale ) |
| throws MojoExecutionException, IOException |
| { |
| if ( !isIncludeReports() ) |
| { |
| getLog().info( "Skipped report generation." ); |
| return; |
| } |
| |
| if ( project.getReporting() == null ) |
| { |
| getLog().info( "No report was specified." ); |
| return; |
| } |
| |
| List<MavenReportExecution> reportExecutions = getReports(); |
| for ( MavenReportExecution reportExecution : reportExecutions ) |
| { |
| generateMavenReport( reportExecution, locale ); |
| } |
| |
| // copy generated site |
| copySiteDir( getGeneratedSiteDirectoryTmp(), getSiteDirectoryTmp() ); |
| copySiteDir( generatedSiteDirectory, getSiteDirectoryTmp() ); |
| } |
| |
| /** |
| * Generate the given Maven report to an xdoc source file, |
| * only if it is not an external report and the report could be generated. |
| * |
| * @param reportExecution not null |
| * @param locale not null |
| * @throws IOException if any |
| * @throws MojoExecutionException if any |
| * @since 1.1 |
| */ |
| private void generateMavenReport( MavenReportExecution reportExecution, Locale locale ) |
| throws IOException, MojoExecutionException |
| { |
| MavenReport report = reportExecution.getMavenReport(); |
| |
| String localReportName = report.getName( locale ); |
| |
| if ( !reportExecution.canGenerateReport() ) |
| { |
| getLog().info( "Skipped \"" + localReportName + "\" report." ); |
| getLog().debug( "canGenerateReport() was false." ); |
| |
| return; |
| } |
| |
| if ( report.isExternalReport() ) |
| { |
| getLog().info( "Skipped external \"" + localReportName + "\" report (not supported by pdf plugin)." ); |
| getLog().debug( "isExternalReport() was false." ); |
| |
| return; |
| } |
| |
| for ( final MavenReport generatedReport : getGeneratedMavenReports( locale ) ) |
| { |
| if ( report.getName( locale ).equals( generatedReport.getName( locale ) ) ) |
| { |
| if ( getLog().isDebugEnabled() ) |
| { |
| getLog().debug( report.getName( locale ) + " was already generated." ); |
| } |
| return; |
| } |
| } |
| |
| File outDir = new File( getGeneratedSiteDirectoryTmp(), "xdoc" ); |
| if ( !locale.getLanguage().equals( defaultLocale.getLanguage() ) ) |
| { |
| outDir = new File( new File( getGeneratedSiteDirectoryTmp(), locale.getLanguage() ), "xdoc" ); |
| } |
| outDir.mkdirs(); |
| |
| File generatedReport = new File( outDir, report.getOutputName() + ".xml" ); |
| |
| if ( siteDirectory.exists() ) |
| { |
| String excludes = getDefaultExcludesWithLocales( getAvailableLocales(), getDefaultLocale() ); |
| List<String> files = |
| FileUtils.getFileNames( siteDirectory, "*/" + report.getOutputName() + ".*", excludes, false ); |
| if ( !locale.getLanguage().equals( defaultLocale.getLanguage() ) ) |
| { |
| files = |
| FileUtils.getFileNames( new File( siteDirectory, locale.getLanguage() ), "*/" |
| + report.getOutputName() + ".*", excludes, false ); |
| } |
| |
| if ( files.size() != 0 ) |
| { |
| String displayLanguage = locale.getDisplayLanguage( Locale.ENGLISH ); |
| |
| if ( getLog().isInfoEnabled() ) |
| { |
| getLog().info( |
| "Skipped \"" + report.getName( locale ) + "\" report, file \"" |
| + report.getOutputName() + "\" already exists for the " + displayLanguage |
| + " version." ); |
| } |
| |
| return; |
| } |
| } |
| |
| if ( getLog().isInfoEnabled() ) |
| { |
| getLog().info( "Generating \"" + localReportName + "\" report." ); |
| } |
| |
| // The report will eventually generate output by itself, so we set its output directory anyway. |
| report.setReportOutputDirectory( outDir ); |
| |
| StringWriter sw = new StringWriter(); |
| |
| PdfXdocSink pdfXdocSink = null; |
| try |
| { |
| pdfXdocSink = new PdfXdocSink( sw ); |
| renderReportToSink( reportExecution, locale, pdfXdocSink ); |
| } |
| catch ( MavenReportException e ) |
| { |
| String goal = reportExecution.getPlugin().getArtifactId() + ':' + reportExecution.getPlugin().getVersion() |
| + ':' + reportExecution.getGoal(); |
| throw new MojoExecutionException( "Error generating " + goal + " report", e ); |
| } |
| finally |
| { |
| if ( pdfXdocSink != null ) |
| { |
| pdfXdocSink.close(); |
| } |
| } |
| |
| if ( getLog().isDebugEnabled() ) |
| { |
| getLog().debug( "Writing generated xdoc to " + generatedReport ); |
| } |
| writeGeneratedReport( sw.toString(), generatedReport ); |
| |
| // keep generated report xdoc only if it is valid |
| if ( isValidGeneratedReportXdoc( reportExecution.getPlugin().getId() + ':' + reportExecution.getGoal(), |
| generatedReport, localReportName ) ) |
| { |
| getGeneratedMavenReports( locale ).add( report ); |
| } |
| } |
| |
| /** |
| * see org.apache.maven.plugins.site.render.ReportDocumentRenderer#renderDocument(...) |
| * |
| * @param reportExec |
| * @param locale |
| * @param sink |
| * @throws MavenReportException |
| */ |
| private void renderReportToSink( MavenReportExecution reportExec, Locale locale, PdfXdocSink sink ) |
| throws MavenReportException |
| { |
| ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); |
| try |
| { |
| if ( reportExec.getClassLoader() != null ) |
| { |
| Thread.currentThread().setContextClassLoader( reportExec.getClassLoader() ); |
| } |
| |
| MavenReport report = reportExec.getMavenReport(); |
| |
| /*if ( report instanceof MavenMultiPageReport ) |
| { |
| // extended multi-page API |
| ( (MavenMultiPageReport) report ).generate( mainSink, multiPageSinkFactory, locale ); |
| } |
| else if ( generateMultiPage( locale, multiPageSinkFactory, mainSink ) ) |
| { |
| // extended multi-page API for Maven 2.2, only accessible by reflection API |
| } |
| else |
| {*/ |
| // old single-page-only API |
| report.generate( sink, locale ); |
| //} |
| } |
| finally |
| { |
| if ( reportExec.getClassLoader() != null ) |
| { |
| Thread.currentThread().setContextClassLoader( originalClassLoader ); |
| } |
| } |
| } |
| |
| /** |
| * @param locale not null |
| * @return the generated reports |
| * @since 1.1 |
| */ |
| private List<MavenReport> getGeneratedMavenReports( Locale locale ) |
| { |
| if ( this.generatedMavenReports == null ) |
| { |
| this.generatedMavenReports = new HashMap<>( 2 ); |
| } |
| |
| if ( this.generatedMavenReports.get( locale ) == null ) |
| { |
| this.generatedMavenReports.put( locale, new ArrayList<MavenReport>( 2 ) ); |
| } |
| |
| return this.generatedMavenReports.get( locale ); |
| } |
| |
| /** |
| * Append generated reports to the toc only if <code>generateReports</code> is enabled, for instance: |
| * <pre> |
| * <item name="Project Reports" ref="project-info"> |
| * <item name="Project License" ref="license" /> |
| * <item name="Project Team" ref="team-list" /> |
| * <item name="Continuous Integration" ref="integration" /> |
| * ... |
| * </item> |
| * </pre> |
| * |
| * @param model not null |
| * @param locale not null |
| * @see #generateMavenReports(Locale) |
| * @since 1.1 |
| */ |
| protected void appendGeneratedReports( DocumentModel model, Locale locale ) |
| { |
| if ( !isIncludeReports() ) |
| { |
| return; |
| } |
| if ( getGeneratedMavenReports( locale ).isEmpty() ) |
| { |
| return; |
| } |
| |
| final DocumentTOCItem documentTOCItem = new DocumentTOCItem(); |
| documentTOCItem.setName( i18n.getString( "pdf-plugin", locale, "toc.project-info.item" ) ); |
| documentTOCItem.setRef( "project-info" ); // see #generateMavenReports(Locale) |
| |
| List<String> addedRef = new ArrayList<>( 4 ); |
| |
| List<DocumentTOCItem> items = new ArrayList<>( 4 ); |
| |
| // append generated report defined as MavenReport |
| for ( final MavenReport report : getGeneratedMavenReports( locale ) ) |
| { |
| final DocumentTOCItem reportItem = new DocumentTOCItem(); |
| reportItem.setName( report.getName( locale ) ); |
| reportItem.setRef( report.getOutputName() ); |
| |
| items.add( reportItem ); |
| |
| addedRef.add( report.getOutputName() ); |
| } |
| |
| // append all generated reports from generated-site |
| try |
| { |
| if ( generatedSiteDirectory.exists() ) |
| { |
| String excludes = getDefaultExcludesWithLocales( getAvailableLocales(), getDefaultLocale() ); |
| List<String> generatedDirs = FileUtils.getDirectoryNames( generatedSiteDirectory, "*", excludes, |
| true ); |
| if ( !locale.getLanguage().equals( getDefaultLocale().getLanguage() ) ) |
| { |
| generatedDirs = |
| FileUtils.getFileNames( new File( generatedSiteDirectory, locale.getLanguage() ), "*", |
| excludes, true ); |
| } |
| |
| for ( final String generatedDir : generatedDirs ) |
| { |
| List<String> generatedFiles = |
| FileUtils.getFileNames( new File( generatedDir ), "**.*", excludes, false ); |
| |
| for ( final String generatedFile : generatedFiles ) |
| { |
| final String ref = generatedFile.substring( 0, generatedFile.lastIndexOf( '.' ) ); |
| |
| if ( !addedRef.contains( ref ) ) |
| { |
| final String title = |
| getGeneratedDocumentTitle( new File( generatedDir, generatedFile ) ); |
| |
| if ( title != null ) |
| { |
| final DocumentTOCItem reportItem = new DocumentTOCItem(); |
| reportItem.setName( title ); |
| reportItem.setRef( ref ); |
| |
| items.add( reportItem ); |
| } |
| } |
| } |
| } |
| } |
| } |
| catch ( IOException e ) |
| { |
| getLog().error( "IOException: " + e.getMessage() ); |
| getLog().debug( e ); |
| } |
| |
| // append to Toc |
| documentTOCItem.setItems( items ); |
| model.getToc().addItem( documentTOCItem ); |
| } |
| |
| private void saveTOC( DocumentTOC toc, Locale locale ) |
| { |
| try |
| { |
| TocFileHelper.saveTOC( getWorkingDirectory(), toc, locale ); |
| } |
| catch ( IOException e ) |
| { |
| getLog().error( "Error while writing table of contents", e ); |
| } |
| } |
| |
| /** |
| * Parse a generated Doxia file and returns its title. |
| * |
| * @param f not null |
| * @return the xdoc file title or null if an error occurs. |
| * @throws IOException if any |
| * @since 1.1 |
| */ |
| private String getGeneratedDocumentTitle( final File f ) |
| throws IOException |
| { |
| final IndexEntry entry = new IndexEntry( "index" ); |
| final IndexingSink titleSink = new IndexingSink( entry ); |
| |
| try ( Reader reader = ReaderFactory.newXmlReader( f ) ) |
| { |
| doxia.parse( reader, f.getParentFile().getName(), titleSink ); |
| } |
| catch ( ParseException e ) |
| { |
| getLog().error( "ParseException: " + e.getMessage() ); |
| getLog().debug( e ); |
| return null; |
| } |
| catch ( ParserNotFoundException e ) |
| { |
| getLog().error( "ParserNotFoundException: " + e.getMessage() ); |
| getLog().debug( e ); |
| return null; |
| } |
| |
| return titleSink.getTitle(); |
| } |
| |
| /** |
| * Parsing the generated report to see if it is correct or not. Log the error for the user. |
| * |
| * @param fullGoal not null |
| * @param generatedReport not null |
| * @param localReportName not null |
| * @return <code>true</code> if Doxia is able to parse the generated report, <code>false</code> otherwise. |
| * @since 1.1 |
| */ |
| private boolean isValidGeneratedReportXdoc( String fullGoal, File generatedReport, String localReportName ) |
| { |
| SinkAdapter sinkAdapter = new SinkAdapter(); |
| try ( Reader reader = ReaderFactory.newXmlReader( generatedReport ) ) |
| { |
| doxia.parse( reader, "xdoc", sinkAdapter ); |
| } |
| catch ( ParseException e ) |
| { |
| StringBuilder sb = new StringBuilder( 1024 ); |
| |
| sb.append( EOL ); |
| sb.append( "Error when parsing the generated report xdoc file: " ); |
| sb.append( generatedReport.getAbsolutePath() ); |
| sb.append( EOL ); |
| sb.append( e.getMessage() ); |
| sb.append( EOL ); |
| |
| sb.append( "You could:" ).append( EOL ); |
| sb.append( " * exclude all reports using -DincludeReports=false" ).append( EOL ); |
| sb.append( " * remove the " ); |
| sb.append( fullGoal ); |
| sb.append( " from the <reporting/> part. To not affect the site generation, " ); |
| sb.append( "you could create a PDF profile." ); |
| |
| sb.append( EOL ).append( "Ignoring the \"" ).append( localReportName ) |
| .append( "\" report in the PDF." ).append( EOL ); |
| |
| getLog().error( sb.toString() ); |
| getLog().debug( e ); |
| |
| return false; |
| } |
| catch ( ParserNotFoundException e ) |
| { |
| getLog().error( "ParserNotFoundException: " + e.getMessage() ); |
| getLog().debug( e ); |
| |
| return false; |
| } |
| catch ( IOException e ) |
| { |
| getLog().error( "IOException: " + e.getMessage() ); |
| getLog().debug( e ); |
| |
| return false; |
| } |
| |
| return true; |
| } |
| |
| protected List<MavenReportExecution> getReports() |
| throws MojoExecutionException |
| { |
| if ( !isMaven3OrMore() ) |
| { |
| getLog().error( "Report generation is not supported with Maven <= 2.x" ); |
| } |
| |
| MavenReportExecutorRequest mavenReportExecutorRequest = new MavenReportExecutorRequest(); |
| mavenReportExecutorRequest.setLocalRepository( localRepository ); |
| mavenReportExecutorRequest.setMavenSession( session ); |
| mavenReportExecutorRequest.setProject( project ); |
| mavenReportExecutorRequest.setReportPlugins( getReportingPlugins() ); |
| |
| MavenReportExecutor mavenReportExecutor; |
| try |
| { |
| mavenReportExecutor = (MavenReportExecutor) container.lookup( MavenReportExecutor.class.getName() ); |
| } |
| catch ( ComponentLookupException e ) |
| { |
| throw new MojoExecutionException( "could not get MavenReportExecutor component", e ); |
| } |
| return mavenReportExecutor.buildMavenReports( mavenReportExecutorRequest ); |
| } |
| |
| /** |
| * Get the report plugins from reporting section, adding if necessary (i.e. not excluded) |
| * default reports (i.e. maven-project-info-reports) |
| * |
| * @return the effective list of reports |
| * @since 1.5 |
| */ |
| private ReportPlugin[] getReportingPlugins() |
| { |
| List<ReportPlugin> reportingPlugins = reporting.getPlugins(); |
| |
| // MSITE-806: add default report plugin like done in maven-model-builder DefaultReportingConverter |
| boolean hasMavenProjectInfoReportsPlugin = false; |
| for ( ReportPlugin plugin : reportingPlugins ) |
| { |
| if ( "org.apache.maven.plugins".equals( plugin.getGroupId() ) |
| && "maven-project-info-reports-plugin".equals( plugin.getArtifactId() ) ) |
| { |
| hasMavenProjectInfoReportsPlugin = true; |
| break; |
| } |
| } |
| |
| if ( !reporting.isExcludeDefaults() && !hasMavenProjectInfoReportsPlugin ) |
| { |
| ReportPlugin mpir = new ReportPlugin(); |
| mpir.setArtifactId( "maven-project-info-reports-plugin" ); |
| reportingPlugins.add( mpir ); |
| } |
| return reportingPlugins.toArray( new ReportPlugin[reportingPlugins.size()] ); |
| } |
| |
| /** |
| * Check the current Maven version to see if it's Maven 3.0 or newer. |
| */ |
| protected static boolean isMaven3OrMore() |
| { |
| try |
| { |
| ArtifactVersion mavenVersion = new DefaultArtifactVersion( getMavenVersion() ); |
| return VersionRange.createFromVersionSpec( "[3.0,)" ).containsVersion( mavenVersion ); |
| } |
| catch ( InvalidVersionSpecificationException e ) |
| { |
| return false; |
| } |
| // return new ComparableVersion( getMavenVersion() ).compareTo( new ComparableVersion( "3.0" ) ) >= 0; |
| } |
| |
| protected static String getMavenVersion() |
| { |
| // This relies on the fact that MavenProject is the in core classloader |
| // and that the core classloader is for the maven-core artifact |
| // and that should have a pom.properties file |
| // if this ever changes, we will have to revisit this code. |
| final Properties properties = new Properties(); |
| |
| try ( InputStream in = MavenProject.class.getClassLoader().getResourceAsStream( |
| "META-INF/maven/org.apache.maven/maven-core/pom.properties" ) ) |
| { |
| properties.load( in ); |
| } |
| catch ( IOException ioe ) |
| { |
| return ""; |
| } |
| |
| return properties.getProperty( "version" ).trim(); |
| } |
| |
| // ---------------------------------------------------------------------- |
| // static methods |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * Write the given content to the given file. |
| * <br/> |
| * <b>Note</b>: try also to fix the content due to some issues in |
| * {@link org.apache.maven.reporting.AbstractMavenReport}. |
| * |
| * @param content the given content |
| * @param toFile the report file |
| * @throws IOException if any |
| * @since 1.1 |
| */ |
| private static void writeGeneratedReport( String content, File toFile ) |
| throws IOException |
| { |
| if ( StringUtils.isEmpty( content ) ) |
| { |
| return; |
| } |
| |
| try ( Writer writer = WriterFactory.newXmlWriter( toFile ) ) |
| { |
| // see PdfSink#table() |
| writer.write( StringUtils.replace( content, "<table><table", "<table" ) ); |
| } |
| } |
| |
| /** |
| * @param locales the list of locales dir to exclude |
| * @param defaultLocale the default locale. |
| * @return the comma separated list of default excludes and locales dir. |
| * @see FileUtils#getDefaultExcludesAsString() |
| * @since 1.1 |
| */ |
| private static String getDefaultExcludesWithLocales( List<Locale> locales, Locale defaultLocale ) |
| { |
| String excludesLocales = FileUtils.getDefaultExcludesAsString(); |
| for ( final Locale locale : locales ) |
| { |
| if ( !locale.getLanguage().equals( defaultLocale.getLanguage() ) ) |
| { |
| excludesLocales = excludesLocales + ",**/" + locale.getLanguage() + "/*"; |
| } |
| } |
| |
| return excludesLocales; |
| } |
| |
| // ---------------------------------------------------------------------- |
| // Inner class |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * A sink to render a Maven report as a generated xdoc file, with some known workarounds. |
| * |
| * @since 1.1 |
| */ |
| private static class PdfXdocSink |
| extends XdocSink |
| implements org.codehaus.doxia.sink.Sink |
| { |
| protected PdfXdocSink( Writer writer ) |
| { |
| super( writer ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void text( String text ) |
| { |
| // workaround to fix quotes introduced with MPIR-59 (then removed in MPIR-136) |
| super.text( StringUtils.replace( text, "\u0092", "'" ) ); |
| } |
| |
| public void tableRow() |
| { |
| // To be backward compatible: TODO add to XdocSink |
| if ( !this.tableRows ) |
| { |
| tableRows( null, false ); |
| } |
| super.tableRow( null ); |
| } |
| } |
| |
| /** |
| * Renderer Maven report similar to org.apache.maven.plugins.site.CategorySummaryDocumentRenderer |
| * |
| * @since 1.1 |
| */ |
| private static class ProjectInfoRenderer |
| extends AbstractMavenReportRenderer |
| { |
| private final List<MavenReport> generatedReports; |
| |
| private final I18N i18n; |
| |
| private final Locale locale; |
| |
| ProjectInfoRenderer( Sink sink, List<MavenReport> generatedReports, I18N i18n, Locale locale ) |
| { |
| super( sink ); |
| |
| this.generatedReports = generatedReports; |
| this.i18n = i18n; |
| this.locale = locale; |
| } |
| |
| /** {@inheritDoc} */ |
| public String getTitle() |
| { |
| return i18n.getString( "pdf-plugin", locale, "report.project-info.title" ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void renderBody() |
| { |
| sink.section1(); |
| sink.sectionTitle1(); |
| sink.text( i18n.getString( "pdf-plugin", locale, "report.project-info.title" ) ); |
| sink.sectionTitle1_(); |
| |
| sink.paragraph(); |
| sink.text( i18n.getString( "pdf-plugin", locale, "report.project-info.description1" ) + " " ); |
| sink.link( "http://maven.apache.org" ); |
| sink.text( "Maven" ); |
| sink.link_(); |
| sink.text( " " + i18n.getString( "pdf-plugin", locale, "report.project-info.description2" ) ); |
| sink.paragraph_(); |
| |
| sink.section2(); |
| sink.sectionTitle2(); |
| sink.text( i18n.getString( "pdf-plugin", locale, "report.project-info.sectionTitle" ) ); |
| sink.sectionTitle2_(); |
| |
| sink.table(); |
| |
| sink.tableRows( new int[] { Sink.JUSTIFY_LEFT, Sink.JUSTIFY_LEFT }, false ); |
| |
| String name = i18n.getString( "pdf-plugin", locale, "report.project-info.column.document" ); |
| String description = i18n.getString( "pdf-plugin", locale, "report.project-info.column.description" ); |
| |
| sink.tableRow(); |
| |
| sink.tableHeaderCell( SinkEventAttributeSet.CENTER ); |
| |
| sink.text( name ); |
| |
| sink.tableHeaderCell_(); |
| |
| sink.tableHeaderCell( SinkEventAttributeSet.CENTER ); |
| |
| sink.text( description ); |
| |
| sink.tableHeaderCell_(); |
| |
| sink.tableRow_(); |
| |
| if ( generatedReports != null ) |
| { |
| for ( final MavenReport report : generatedReports ) |
| { |
| sink.tableRow(); |
| sink.tableCell(); |
| sink.link( report.getOutputName() + ".html" ); |
| sink.text( report.getName( locale ) ); |
| sink.link_(); |
| sink.tableCell_(); |
| sink.tableCell(); |
| sink.text( report.getDescription( locale ) ); |
| sink.tableCell_(); |
| sink.tableRow_(); |
| } |
| } |
| |
| sink.tableRows_(); |
| |
| sink.table_(); |
| |
| sink.section2_(); |
| |
| sink.section1_(); |
| } |
| } |
| } |