Writing Your Own SonarQube Plug-ins – Part 1: Preparing the Project

Since a few weeks ago I’ve been spending some free time on writing my own custom plug-in for SonarQube (formerly Sonar, www.sonarqube.org). SonarQube is a code analysis tool and dashboard, that lets you not only inspect code as you go, but also publish and track all metrics in a dashboard, manage your quality reviews, define action plans, and much more.

Custom plug-ins enhance SonarQube functionality in multiple ways: a plug-in may support static analysis of new languages, add new metrics to the tool, or change the way that information is presented (widgets, views) and managed (action plans, peer reviews).

Creating new plug-ins is not complex, given that you know what to do – documentation is not as complete as it should, you get pieces and bits here and there, but at the end you need to take a look to existing sources and make all the connections. Based on my own experiences I’ve decided to write a few posts documenting the process, with the hope that it can be of help to others. 🙂

EDIT: Source code for the simple plug-in shown during these posts can be obtained from GitHub here: https://github.com/deors/deors.plugins.sonarqube.idemetadata

Part 1 – Preparing the Project

Now you have an idea for a plug-in – what’s next? You need to setup a project that will hold all plug-in code and configuration. SonarQube plug-in projects can be easily configured using Maven, with the added benefit that you leverage the well known project folder structure and dependency management mechanism.

A SonarQube plug-in has three requirements, in terms of Maven configuration, that makes them different to a regular Java project:

  1. A special type of packaging, sonar-plugin. This custom packaging is used to fine tune the project life-cycle without requiring us to tweak plug-in configuration within the pom.xml file.
  2. A dependency with SonarQube plug-in API. Artefact coordinates are: org.codehaus.sonar:sonar-plugin-api:3.7.3 – replace version with the one that is right for your plug-in, taking into consideration compatibility.
  3. A build plug-in that will take care of the specifics of packaging the plug-in for deployment into a SonarQube installation. The plug-in coordinates are: org.codehaus.sonar:sonar-packaging-maven-plugin:1.7 – 1.7 is the latest one. Configuration for the SonarQube packaging plug-in should include at least the plug-in key (an unique identifier for this plug-in) and the plug-in main class (more about this later).

Putting this all together, the POM for the plug-in project looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<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">

    <groupId>com.wordpress.deors</groupId>
    <artifactId>tools.sonarqube.idemetadata</artifactId>
    <packaging>sonar-plugin</packaging>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.codehaus.sonar</groupId>
            <artifactId>sonar-plugin-api</artifactId>
            <version>3.7.3</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.sonar</groupId>
                <artifactId>sonar-packaging-maven-plugin</artifactId>
                <version>1.7</version>
                <extensions>true</extensions>
                <configuration>
                    <pluginKey>idemetadata</pluginKey>
                    <pluginClass>deors.tools.sonarqube.idemetadata.IDEMetadataPlugin</pluginClass>
                    <pluginName>Sonar IDE Metadata plugin</pluginName>
                    <pluginDescription>Gathers and displays information from IDE metadata files, including project type (based on natures/facets) and dependencies.</pluginDescription>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

The Plug-in Main Class

The entry point for every SonarQube plug-in is a class that extends the org.sonar.api.SonarPlugin abstract class. A plug-in is modelled as a list of extensions (implementations of the interface org.sonar.api.Extension).

The SonarQube plug-in main class unique purpose is to define which extensions are contributed by the plug-in – widgets, sensors, decorators, metrics. In this case I was building a plug-in that contributed a set of custom metrics, a sensor (component that scans the code, gathers the metrics and stores them in SonarQube) and a widget (a dashboard view used to present the gathered information to users). The final code was like this (package, import and Javadocs omitted):

public class IDEMetadataPlugin extends SonarPlugin {
    public List<Class<? extends Extension>> getExtensions() {
        return Arrays.asList(
            IDEMetadataMetrics.class,
            IDEMetadataSensor.class,
            IDEMetadataDashboardWidget.class);
    }
}

Very simple definition, and once done, we are ready to go.

Going forward, in part 2 I will explain how to define metrics and the sensor class, in part 3 I will explain how to create widgets and finally in part 4 I will explain how to execute the plug-in in development mode and how to install it in your production SonarQube instance, with the help of JRebel to speed up development.

Advertisements