views:

488

answers:

2

Does anybody know how to configure the maven findbugs plugin to output a summary of the bugs to the console (similar to the pmd plugin)?

At present findbugs:check just prints out how many bugs there are in total and I need to check the individual modules target/findbugs directory and each findbugs.xml file to fix the issues.

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>2.0.1</version>                              
<configuration>
        <xmlOutput>true</xmlOutput>
        <xmlOutputDirectory>findbugsreports</xmlOutputDirectory>
        <findbugsXmlOutput>true</findbugsXmlOutput>
        <findbugsXmlOutputDirectory>target/site/findbugsreports</findbugsXmlOutputDirectory>
        <debug>true</debug>
</configuration> 
</plugin>

Ideally it would be good to get a summary report back on the command line. Any ideas?

+2  A: 

There isn't currently a means to do this using the standard plugin. You can create a plugin to read the findbugsChecks.xml and output the information you need though.

The code below will output the total bugs found and the bugs per package for any project with a findbugsChecks.xml in the output directory. You can configure the name of the file it reads by setting the findBugsChecks property on the configuration:

package name.seller.rich;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

/**
 * @goal stats
 */
public class FindbugsStatsMojo extends AbstractMojo {

    /**
     * Where to read the findbugs stats from
     * 
     * @parameter expression="${findbugsChecks}"
     *            default-value="${project.build.directory}/findbugsCheck.xml"
     */
    private File findbugsChecks;

    /**
     * Output the Findbus stats for the project to the console.
     */
    public void execute() throws MojoExecutionException, MojoFailureException {
        if (findbugsChecks != null && findbugsChecks.exists()) {
            try {
                Xpp3Dom dom = Xpp3DomBuilder.build(new FileReader(
                        findbugsChecks));

                // get the summary and output it
                Xpp3Dom summaryDom = dom.getChild("FindBugsSummary");

                // output any information needed
                getLog().info(
                        "Total bug count:"
                                + summaryDom.getAttribute("total_bugs"));

                Xpp3Dom[] packageDoms = summaryDom.getChildren("PackageStats");

                getLog().info(packageDoms.length + " package(s)");
                for (int i = 0; i < packageDoms.length; i++) {
                    String info = new StringBuilder().append("package ")
                            .append(packageDoms[i].getAttribute("package"))
                            .append(": types:").append(
                                    packageDoms[i].getAttribute("total_types"))
                            .append(", bugs:").append(
                                    packageDoms[i].getAttribute("total_bugs"))
                            .toString();
                    getLog().info(info);
                }
            } catch (FileNotFoundException e) {
                throw new MojoExecutionException(
                        "Findbugs checks file missing", e);
            } catch (XmlPullParserException e) {
                throw new MojoExecutionException(
                        "Unable to parse Findbugs checks file", e);
            } catch (IOException e) {
                throw new MojoExecutionException(
                        "Unable to read Findbugs checks file", e);
            }
        }
    }
}

To package this code, add it to the src/main/java folder of a Mavenproject with a POM like this:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"&gt;
  <modelVersion>4.0.0</modelVersion>
  <groupId>name.seller.rich</groupId>
  <artifactId>maven-findbugs-stats-plugin</artifactId>
  <packaging>maven-plugin</packaging>
  <version>0.0.1</version>
  <dependencies>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-core</artifactId>
      <version>2.2.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-plugin-api</artifactId>
      <version>2.2.0</version>
    </dependency>
  </dependencies>
</project>

Then run mvn install to install the plugin.

To actually use it, you can run it as an additional goal on the command line, or bind it to your project to run as part of the standard lifecycle.

Here's the command to run from the commandline (assuming the project has previously been compiled:

mvn findbugs:check name.seller.rich:maven-findbugs-stats-plugin:0.0.1:stats

To bind the configurations to your project so it will be run on each build, use the following configuration:

<build>
  <plugins>
    <plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>findbugs-maven-plugin</artifactId>
  <version>2.1</version>
  <executions>
    <execution>
      <id>check</id>
      <phase>package</phase>
      <goals>
        <goal>check</goal>
      </goals>
    </execution>
  </executions>                              
  <configuration>
    <xmlOutput>true</xmlOutput>
    <xmlOutputDirectory>findbugsreports</xmlOutputDirectory>
    <findbugsXmlOutput>true</findbugsXmlOutput>
    <findbugsXmlOutputDirectory>${findbugsOutputDirectory}</findbugsXmlOutputDirectory>
    <debug>true</debug>
    <failOnError>false</failOnError>
  </configuration> 
    </plugin>
    <plugin>
    <groupId>name.seller.rich</groupId>
    <artifactId>maven-findbugs-stats-plugin</artifactId>
    <executions>
      <execution>
        <id>stats</id>
        <phase>package</phase>
        <goals>
          <goal>stats</goal>
        </goals>
      </execution>
    </executions>
    </plugin>
  </plugins>
</build>
Rich Seller
+1  A: 

Following along from the concepts above I have raised this issue on the maven findbugs issue tracker. http://jira.codehaus.org/browse/MFINDBUGS-115. I have also coded and submitted a patch that shows total bugs for each project. It could easily be modified to get other details.

The code ignores projects specified as producing POM outputs and also ignores projects whose POMs specify true in their findbugs configuration. We are running a large multi-module maven build with the patch applied.

With the patch applied you run mvn findbugs:check and you get something like the following output (output obfuscated to protect the guilty :):

[INFO] Summary
[INFO] -------
[INFO] C:\PATH\Abstraction\PalDefinitions\target/findbugsXml.xml  4
[INFO] C:\PATH\System\target/findbugsXml.xml  19
[INFO] C:\PATH\ApplicationLayer\target/findbugsXml.xml  13
[INFO] C:\PATH\Support\ServiceStub\target/findbugsXml.xml  11
[INFO] C:\PATH\Support\MultiPlatform\target/findbugsXml.xml  10
[INFO] C:\PATH\Support\Serializer\target/findbugsXml.xml  19
[INFO] C:\PATH\Support\Brander\target/findbugsXml.xml  19
[INFO] C:\PATH\PlatformAbstraction\Pal1\target/findbugsXml.xml  8
[INFO] C:\PATH\PlatformAbstraction\Pal2\target/findbugsXml.xml  0
[INFO] C:\PATH\PlatformAbstraction\Pal3\target/findbugsXml.xml  0
[INFO] C:\PATH\PlatformAbstraction\Pal4\target/findbugsXml.xml  0
[INFO] C:\PATH\Framework\Common\target/findbugsXml.xml  12
[INFO] C:\PATH\Framework\legacyFramework\target/findbugsXml.xml  7
[INFO] C:\PATH\Framework\UIFramework\target/findbugsXml.xml  7
[INFO] C:\PATH\ExecutionLayer\Stub\target/findbugsXml.xml  0
[INFO] C:\PATH\ExecutionLayer\BB\BB\target/findbugsXml.xml  1
[INFO] TOTAL = 130
[INFO] -------
[INFO] Number of bugs 130 falls BELOW summaryThreshold 260. Check OK