All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.mojo.clirr.ClirrReport Maven / Gradle / Ivy

Go to download

Clirr is a tool that checks Java libraries for binary and source compatibility with older releases. Basically you give it two sets of jar files and Clirr dumps out a list of changes in the public API. The clirr-maven-plugin can be configured to break the build, if it detects incompatible api changes. In a continuous integration process, the clirr-maven-plugin can automatically prevent accidental introduction of binary or source compatibility problems. Additionally, the plugin can generate a report as part of the generated site.

There is a newer version: 2.8
Show newest version
package org.codehaus.mojo.clirr;

/*
 * Copyright 2006 The Codehaus
 *
 * Licensed 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 net.sf.clirr.core.Severity;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.doxia.module.xhtml.decoration.render.RenderingContext;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.doxia.site.decoration.Body;
import org.apache.maven.doxia.site.decoration.DecorationModel;
import org.apache.maven.doxia.site.decoration.Skin;
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.siterenderer.sink.SiteRendererSink;
import org.apache.maven.model.ReportPlugin;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.reporting.MavenReport;
import org.apache.maven.reporting.MavenReportException;
import org.codehaus.plexus.i18n.I18N;
import org.codehaus.plexus.util.PathTool;
import org.codehaus.plexus.util.StringUtils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

/**
 * Generate a report from the Clirr output.
 *
 * @author Brett Porter
 * @goal clirr
 * @execute phase="compile"
 */
public class ClirrReport
    extends AbstractClirrMojo
    implements MavenReport
{
    /**
     * Specifies the directory where the report will be generated.
     *
     * @parameter default-value="${project.reporting.outputDirectory}"
     * @required
     */
    private File outputDirectory;

    /**
     * @component
     */
    private Renderer siteRenderer;

    /**
     * Whether to show the summary of the number of errors, warnings and informational messages.
     *
     * @parameter property="showSummary" default-value="true"
     */
    private boolean showSummary;

    /**
     * Whether to render the HTML report or not.
     *
     * @parameter property="htmlReport" default-value="true"
     */
    private boolean htmlReport;

    /**
     * Link the violation line numbers to the source Xref. This will create links
     * if the JXR Plugin is being used.
     *
     * @parameter property="linkXRef" default-value="true"
     */
    private boolean linkXRef;

    /**
     * Location of the Xrefs to link to.
     *
     * @parameter property="xrefLocation" default-value="${project.build.directory}/site/xref"
     */
    private File xrefLocation;

    /**
     * @component
     */
    private I18N i18n;

    public String getCategoryName()
    {
        return MavenReport.CATEGORY_PROJECT_REPORTS;
    }

    public void setReportOutputDirectory( File file )
    {
        outputDirectory = file;
    }

    public File getReportOutputDirectory()
    {
        return outputDirectory;
    }

    public boolean isExternalReport()
    {
        return false;
    }

    private File getSkinArtifactFile()
        throws MojoFailureException, MojoExecutionException
    {
        Skin skin = Skin.getDefaultSkin();

        String version = skin.getVersion();
        Artifact artifact;
        try
        {
            if ( version == null )
            {
                version = Artifact.RELEASE_VERSION;
            }
            VersionRange versionSpec = VersionRange.createFromVersionSpec( version );
            artifact = factory.createDependencyArtifact( skin.getGroupId(), skin.getArtifactId(), versionSpec, "jar",
                                                         null, null );

            resolver.resolve( artifact, project.getRemoteArtifactRepositories(), localRepository );
        }
        catch ( InvalidVersionSpecificationException e )
        {
            throw new MojoFailureException( "The skin version '" + version + "' is not valid: " + e.getMessage() );
        }
        catch ( ArtifactResolutionException e )
        {
            throw new MojoExecutionException( "Unable to find skin", e );
        }
        catch ( ArtifactNotFoundException e )
        {
            throw new MojoFailureException( "The skin does not exist: " + e.getMessage() );
        }

        return artifact.getFile();
    }

    @Override
    protected void doExecute()
        throws MojoExecutionException, MojoFailureException
    {
        if ( !canGenerateReport() )
        {
            return;
        }

        // TODO: push to a helper? Could still be improved by taking more of the site information from the site plugin
        try
        {
            DecorationModel model = new DecorationModel();
            model.setBody( new Body() );
            Map attributes = new HashMap();
            attributes.put( "outputEncoding", "UTF-8" );
            Locale locale = Locale.getDefault();
            SiteRenderingContext siteContext = siteRenderer.createContextForSkin( getSkinArtifactFile(), attributes,
                                                                                  model, getName( locale ), locale );

            RenderingContext context = new RenderingContext( outputDirectory, getOutputName() + ".html" );

            SiteRendererSink sink = new SiteRendererSink( context );
            generate( sink, locale );

            outputDirectory.mkdirs();

            Writer writer = new FileWriter( new File( outputDirectory, getOutputName() + ".html" ) );

            siteRenderer.generateDocument( writer, sink, siteContext );

            siteRenderer.copyResources( siteContext, new File( project.getBasedir(), "src/site/resources" ),
                                        outputDirectory );
        }
        catch ( RendererException e )
        {
            throw new MojoExecutionException(
                "An error has occurred in " + getName( Locale.ENGLISH ) + " report generation.", e );
        }
        catch ( IOException e )
        {
            throw new MojoExecutionException(
                "An error has occurred in " + getName( Locale.ENGLISH ) + " report generation.", e );
        }
        catch ( MavenReportException e )
        {
            throw new MojoExecutionException(
                "An error has occurred in " + getName( Locale.ENGLISH ) + " report generation.", e );
        }
    }

    public void generate( Sink sink, Locale locale )
        throws MavenReportException
    {
        if ( !canGenerateReport() )
        {
            getLog().info( "Not generating report as there are no sources to compare" );
        }
        else
        {
            doReport( sink, locale );
        }
    }

    private void doReport( Sink sink, Locale locale )
        throws MavenReportException
    {
        Severity minSeverity = convertSeverity( this.minSeverity );
        ResourceBundle bundle = getBundle( locale );
        if ( minSeverity == null )
        {
            getLog().warn( bundle.getString( "report.clirr.error.invalid.minseverity" ) + ": '" + this
                .minSeverity + "'." );
        }

        if ( !htmlReport && xmlOutputFile == null && textOutputFile == null && !logResults )
        {
            getLog().error( bundle.getString( "report.clirr.error.noreports" ) );
        }
        else
        {
            ClirrDiffListener listener;
            try
            {
                listener = executeClirr( minSeverity );
            }
            catch ( MissingPreviousException e )
            {
                getLog().error( bundle.getString( "report.clirr.error.nopredecessor" ) );
                return;
            }
            catch ( MojoExecutionException e )
            {
                throw new MavenReportException( e.getMessage(), e );
            }
            catch ( MojoFailureException e )
            {
                throw new MavenReportException( e.getMessage() );
            }

            if ( htmlReport )
            {
                ClirrReportGenerator generator = new ClirrReportGenerator( sink, i18n, bundle, locale );

                generator.setEnableSeveritySummary( showSummary );

                generator.setMinSeverity( minSeverity );

                generator.setCurrentVersion( project.getVersion() );

                if ( comparisonVersion != null )
                {
                    generator.setComparisonVersion( comparisonVersion );
                }

                if ( linkXRef )
                {
                    String relativePath =
                        PathTool.getRelativePath( outputDirectory.getAbsolutePath(), xrefLocation.getAbsolutePath() );
                    if ( StringUtils.isEmpty( relativePath ) )
                    {
                        relativePath = ".";
                    }
                    relativePath = relativePath + "/" + xrefLocation.getName();
                    if ( xrefLocation.exists() )
                    {
                        // XRef was already generated by manual execution of a lifecycle binding
                        generator.setXrefLocation( relativePath );
                    }
                    else
                    {
                        // Not yet generated - check if the report is on its way
                        for ( Iterator reports = project.getReportPlugins().iterator(); reports.hasNext(); )
                        {
                            ReportPlugin report = (ReportPlugin) reports.next();

                            String artifactId = report.getArtifactId();
                            if ( "maven-jxr-plugin".equals( artifactId ) || "jxr-maven-plugin".equals( artifactId ) )
                            {
                                generator.setXrefLocation( relativePath );
                            }
                        }
                    }

                    if ( generator.getXrefLocation() == null )
                    {
                        getLog().warn( "Unable to locate Source XRef to link to - DISABLED" );
                    }
                }
                generator.generateReport( listener );
            }
        }
    }

    public String getDescription( Locale locale )
    {
        return getBundle( locale ).getString( "report.clirr.description" );
    }

    public String getName( Locale locale )
    {
        return getBundle( locale ).getString( "report.clirr.name" );
    }

    public String getOutputName()
    {
        return "clirr-report";
    }

    private ResourceBundle getBundle( Locale locale )
    {
        return ResourceBundle.getBundle( "clirr-report", locale, getClass().getClassLoader() );
    }

    public boolean canGenerateReport()
    {
        try
        {
            return canGenerate();
        }
        catch ( MojoFailureException e )
        {
            getLog().error( "Can't generate Clirr report: " + e.getMessage() );
            return false;
        }
        catch ( MojoExecutionException e )
        {
            getLog().error( "Can't generate Clirr report: " + e.getMessage(), e );
            return false;
        }
    }

    // eventually, we must replace this with the o.a.m.d.s.Sink class as a parameter
    public void generate( org.codehaus.doxia.sink.Sink sink, Locale locale )
        throws MavenReportException
    {
        generate( (Sink) sink, locale );

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy