Maven findbugs:check - Output Summary Of Bugs
Asked Answered
T

4

7

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?

Titos answered 11/8, 2009 at 22:49 Comment(3)
I actually can't understand why this feature was not implemented first in the plugin... Strange.Unilobed
Submitted a ticket: sourceforge.net/tracker/…Unilobed
Added a related answer in stackoverflow.com/questions/28982149Protolithic
B
3

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">
  <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>
Bearwood answered 12/8, 2009 at 9:0 Comment(1)
Dumb question: Why do you define executions in your findbugs-maven-plugin declaration?Harangue
U
4

I use this hack, based on maven-groovy-plugin:

<plugin>
  <groupId>org.codehaus.groovy.maven</groupId>
  <artifactId>gmaven-plugin</artifactId>
  <version>1.0-rc-5-SNAPSHOT</version>
  <executions>
    <execution>
      <phase>prepare-package</phase>
      <goals>
        <goal>execute</goal>
      </goals>
      <configuration>
        <source>
          def file = new File("${project.build.directory}/findbugsXml.xml")
          if (!file.exists()) {
            fail("Findbugs XML report is absent: " + file.getPath())
          }
          def xml = new XmlParser().parse(file)
          def bugs = xml.BugInstance
          def total = bugs.size()
          if (total &gt; 0) {
            log.info("Total bugs: " + total)
            for (i in 0..total-1) {
              def bug = bugs[i]
              log.info(
                bug.LongMessage.text()
                + " " + bug.Class.'@classname'
                + " " + bug.Class.SourceLine.Message.text()
              )
            }
          }
        </source>
      </configuration>
    </execution>
  </executions>
</plugin>
Unilobed answered 18/11, 2010 at 9:10 Comment(0)
B
3

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">
  <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>
Bearwood answered 12/8, 2009 at 9:0 Comment(1)
Dumb question: Why do you define executions in your findbugs-maven-plugin declaration?Harangue
U
3

Following along from the concepts above I have raised this issue on the maven findbugs issue tracker. http://jira.codehaus.org/browse/MFINDBUGS-118. 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
Unidirectional answered 30/6, 2010 at 4:13 Comment(2)
The link to JIRA bug is brokenUnilobed
Just use version 2.5 or greater of the plugin.Teniafuge
U
0

You can do this with Violations Maven Plugin. It is configured with patterns to identify report files on the filesystem. It needs to run after findbugs, or any other static code analysis tool.

It will

  • Print the violations in the build log.
  • Optionally fail the build if number of violations found is higher then a configured number.
Urinate answered 26/12, 2017 at 19:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.