Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Info
iconfalse
titleTable of Contents
Table of Contents
maxLevel21

A plugin is a Set of Extensions

A Sonar SonarQube plugin is a set of Java objects that implement extension points. These extension points are interfaces or abstract classes which model an aspect of the system and define contracts of what needs to be implemented. They can be for example pages in the web application or sensors generating measures.

...

Code Block
titlepom.xml
langxml
<artifactId>sonar-foo-plugin</artifactId>
<packaging>sonar-plugin</packaging>
<build>
  <plugins>
    <plugin>
      <groupId>org.codehaus.sonar</groupId>
      <artifactId>sonar-packaging-maven-plugin</artifactId>
      <version>1.1<7</version>
      <extensions>true</extensions>
      <configuration>
        <pluginClass>com.mycompany.sonar.MyPlugin</pluginClass>
      </configuration>
    </plugin>
  </plugins>
</build>

The sonar-plugin packaging accepts advanced parameters.

Extension Points

Here is list of extension points available in the sonar plugin API. Please note that partial implementation of those extensions are available in the api as well. See all known sub-interfaces and implementing classes of org.sonar.api.Extension to get an exhaustive list.

Batch side

What

Since

Description

org.sonar.api.batch.CpdMapping

1.10

CPD definition to detect duplicated lines on a new language

org.sonar.api.batch.Decorator

1.10

Used to decorate resources, i.e. calculate measures from other measures. Example : the number of lines of code of a package is the sum of the lines of its classes.

org.sonar.api.resources.Language

1.10

Define a new language.

org.sonar.api.batch.maven.MavenPluginHandler

1.10

Define a Maven2 plugin to execute before analyzing the project.

org.sonar.api.measures.Metrics

1.10

List new Metrics. A metric is an instance of org.sonar.api.measure.Metric. It can be quantitative (lines of code, number of rule violations) or qualitative (code coverage, complexity by class, rules compliance). As a rule, a metric is used to store a number but it can also be used to store a text field with list of key/value pairs, an XML or even binary data.

org.sonar.api.batch.PostJob

1.10

Post-jobs are tasks executed at the end of project analysis. Examples : purge database, generate report, send emails, ...

org.sonar.api.batch.Purge

1.11

Job to delete data from database.

org.sonar.api.batch.ResourceFilter

1.12

enables to ignore certain resources. The only implementations is the exclusion pattern management. (ExcludedResourceFilter in the core plugin).

org.sonar.api.batch.Sensor

1.10

Analyze project. It creates resources (classes, packages, ...) and measures. It can make requests on other systems. See below.

org.sonar.api.rules.ViolationFilter

1.12

Enables to ignore violations. Has a very simple interface : public boolean isIgnored(Violation violation). A NoSonarFilter draft has been added to the Squid plugin.

org.sonar.api.batch.Initializer

 2.6

Batch task executed before all other tasks (sensors, decorators, post-jobs)

org.sonar.api.batch.FileFilter

 2.3

Filter to exclude some files from analysis

org.sonar.api.batch.events.*

2.8

Handle batch lifecycle events (sensor is started, stopped, ...)

org.sonar.api.batch.bootstrap.ProjectBuilder

2.9

Change project structure before analysis

Server side

What

Since

Description

org.sonar.api.charts.Chart

1.10

Image generated by JFreeChart.

org.sonar.api.web.CodeColorizerFormat

1.12

Extend the library sonar-colorizer to support new languages. By default only Java sources are colorized in Sonar.

org.sonar.api.web.Footer

1.10

Static HTML footer displayed in all pages.

org.sonar.api.resources.Language

1.10

Define a new language.

org.sonar.api.web.GwtPage

1.11

Add a page, linked from the left sidebar. The page is implemented as a GWT component. GWT RPC/servlets are not supported.

org.sonar.api.web.ResourceViewer

1.10

New view when displaying source code. It is used to add a new tab to the source viewer along with "Violations", "Sources", "Coverage", ... The new tab is implemented as a GWT component.

org.sonar.api.web.RubyRailsPage

1.11

Add a page, linked from the left sidebar. The page is implemented as a JRuby on Rails view. 

org.sonar.api.web.RubyRailsWebservice

1.11

Experimental. Used to define new web services, written in JRuby on Rails. 

org.sonar.api.web.RubyRailsWidget

1.11

New widget in project dashboards. It is implements as a JRuby on Rails template.

org.sonar.api.rules.RuleRepository

2.3

Define a new repository of rules, i.e. a list of coding rules to publish into the global referential

org.sonar.api.profiles.ProfileDefinition

2.3

Programmatically define a Quality profile

org.sonar.api.profiles.ProfileImporter

2.3

Import a Quality profile, generally used when end-users create a profile by uploading a file

org.sonar.api.profiles.ProfileExporter

2.3

Export a Quality profile in a specific format, for example Checkstyle configuration format

org.sonar.api.qualitymodel.ModelDefinition

2.3

Define a new Quality model, like SQALE

org.sonar.api.security.LoginPasswordAuthenticator

1.12

Delegates authentication of users to external system

org.sonar.api.platform.ServerStartHandler

 2.2

Handle server startup notification

org.sonar.api.platform.ServerStoptHandler

 2.2

Handle server shutdown notification

org.sonar.api.notifications.NotificationChannel

2.10

Channel to publish notifications. An example is the Email channel.

org.sonar.api.notifications.NotificationDispatcher

2.10

Provides logic to determine which users are interested in receiving notification. Example : notify me when when someone changes review assigned to me or created by me.

An extension point is a point in the application where plugin code can be invoked, such as webapp page or code analyzer. Extension points are generally interfaces that can be implemented by plugins. Implementations have to be declared in the method org.sonar.api.SonarPlugin#getExtensions() and are then injected in the IoC container.

The extension points are listed and documented in the Javadoc. See http://docs.sonarsource.org/latest/apidocs/index.html?org/sonar/api/Extension.html.

Sensor or Decorator?

There are two extensions extension points that enables allow plugins to save measures: Sensor and Decorator. A common problem when writing a plugin is to decide which one to use.

Sensor

A Sensor is invoked once during the analysis of a project. The sensor can invoke a maven plugin, parse a flat file, connect to a web server... For example the Cobertura Sensor invokes the Codehaus Cobertura MOJO. Then the generated XML file is parsed is able to parse the cobertura XML report file generated during execution of your tests and used to save the first-level of measures on resources (project, package or class).
A sensor has can access and save measures on the whole tree of resources. Sensor are generally used to add measure at the lowest level of the resource tree.

Decorator

Decorators are triggered once all sensors have completed. Their decorate method is called on every resource of a certain level bottom up. Decorators can load (SELECT) read and save (INSERT) measures. The call is contextual, i.e it is only possible to access the resource and its children.
Decorators are generally used either to consolidate / aggregate at higher levels, measures that have been added saved by Sensors at the lowest level.

How to

...

Reuse Existing Components

Extensions are registered in an IoC container, with constructor injection. To communicate with other extensions or with existing components provided by the API, just declare them in the constructor of your extension. For example to get references on DatabaseSession or RulesProfile:

...

Warning

You should never directly instantiate classes which implements implement BatchComponent or ServerComponent , because they should be retrieved as an IoC dependency. Otherwise it leads to issues with backward compatibility.

How to

...

Quickly Start the Plugin

As described in the Getting Started page, you can build sources, copy the JAR file to the directory extensions/plugins/ and restart the server. But this approach can quickly become tedious. The following solutions help to edit code without leaving your development environment:

Changes on Java code

The sonar-dev-maven-plugin allows to lets you start a Sonar SonarQube server and to deploy the your plugin. 

Once the server is launched, hit http://localhost:9000. By default, the in-process database (H2, or Derby prior to Sonar SonarQube 3.2) is used but you can specify to use a local MySQL instance instead with the property "-Dsonar.database=mysql". In that case, the sonar schema must exist in the MySQL DB along with the user sonar/sonar (login/password) who which must have all rights on the sonar schema.

Code Block
# Note that SonarQube versions greater than or equal 4.0 are not supported yet
mvn install org.codehaus.sonar:sonar-dev-maven-plugin::start-war -Dsonar.runtimeVersion=3.7.2.14

Then you can feed the database by inspecting projects:

Code Block
mvn sonar:sonar
Info
titleNote for Mac OS

Add the property -Djava.io.tmpdir=/tmp to the mvn command.

Note
titleLimitation

Changes on Java code are not reloaded dynamically. You need to rebuild the plugin and to re-execute sonar-dev-maven-plugin.

Debug Java batch

Simply run mvnDebug sonar:sonar and attach your IDE to the remote process. Example in Intellij Idea : Run -> Edit configurations -> Add new configuration -> Remote.

...

Debugging 

We've gathered all our debugging tips into this page.

 

How to Use External Libraries

A plugin benefits from all the dependencies provided by the API. Execute the following command on your plugin to list them:

...

  • Libraries used for GWT compilation must be defined with scope provided
  • The plugin classloader is a child of the Sonar classloader, with a parent-first delegation model. There are two consequences:
    1. Sonar libraries are automatically inherited. Their versions can not be changed.
    2. There are side-effects on some libraries, for example the classloader must be explicitely set be explicitly set for XStream:
    Code Block
    java
    java
    XStream xstream = new XStream();
    xstream.setClassLoader(getClass().getClassLoader());

How to

...

Log

SLF4J is used as a simple facade of various logging frameworks (log4j, commons-log, logback, java.util.logging). It's simple to use:

...

Read the SLF4J manual for more details.

How to

...

Get Configuration

The component org.sonar.api.config.Settings provides properties for batch extensions (global/project settings, command-line parameters, system properties) and server extensions (global settings, system properties, file $SONAR_HOME/conf/sonar.properties). It replaces Apache Commons Configuration that is deprecated since release 2.12.

...

Persistent properties are also accessible from the Web Service named 'properties'. To exclude some properties from anonymous requests, add the suffix ".secured" to the key (my.property.secured). It can be useful for license keys for example.

Steps to cover a new language

  1. Write the grammar. This is the hardest part.
  2. Write a parser (a parser simply takes a grammar, an input, and will parse it, yielding a parse tree).
  3. Test your grammar, to ensure it is able to parse your real-life language files.
  4. Write a few parse tree visitors. Some visitors will compute metrics, while others will enforce coding rules. A dozen or so visitors is sufficient for an initial release.
  5. Write a SonarQube sensor to launch the visitors. It should query the API to get the list of source files, the list of active coding rules in the quality profile, and the API to save metrics and issues.
See also: SSLR.

Tips and Tricks

  • For generating charts use d3.js, which is packaged with SonarQube since version 4.1.
  • To create "template" rules (rules that can be duplicated by the user) set the rule's cardinality field to MULTIPLE
  • To access a constant from a Java class in a .erb file, use Java::OrgSonarPluginsPlug::MyConfiguration::MY_CONSTANT