Dashboard widgets are implemented as Ruby on Rails views. Widgets must be declared with the Java extension point org.sonar.api.web.Widget.
Example of structure :
package com.foo;
import org.sonar.api.web.*;
@WidgetCategory("Labs")
@WidgetProperties({
@WidgetProperty(key = "max", type = WidgetPropertyType.INTEGER, defaultValue = "80")
})
public final class MyWidget extends AbstractRubyTemplate implements RubyRailsWidget {
public String getId() {
return "my_widget";
}
public String getTitle() {
return "My Widget";
}
protected String getTemplatePath() {
return "/com/foo/my_widget.html.erb";
}
} |
<p>This is my first widget</p> <p>Display widget property: <%= widget_properties['max'] -%></p> |
Widgets can be manually tested with the URL : |
Helpers and partials are not supported. |
The development mode reloads Ruby changes on the fly. It allows to edit code and display widget at the same time.
To enable the development mode on a widget :
RubyRailsWidget#getTemplatePath() in order to return the absolute path but not the class path.Ruby on Rails applications are supported since SonarQube3.0. |
Ruby on Rails applications allow plugins to extend the SonarQube webapp with a complete MVC stack : controllers, helpers, models and views. Contrary to widgets, it does not require to declare a Java component. Ruby sources just have to be stored in the plugin directory : /src/main/resources/org/sonar/ror/<plugin key>. This directory must also contain an empty file named init.rb.
Example for an application provided by the plugin with key 'foo' :
Controller URLs are not isolated from the core URLs used by SonarQube. You have to be careful of potential conflicts and choose controller names different than : https://github.com/SonarSource/sonar/tree/master/sonar-server/src/main/webapp/WEB-INF/app/controllers
class MyConsoleController < ApplicationController
# this is an administration console
SECTION=Navigation::SECTION_CONFIGURATION
before_filter :admin_required
# GET http://<server>/my_console/index
def index
# automatically renders the file ../views/my_console/index.html.erb
end
end |
By the default the application is not visible. Pages have to be declared with the Java extension point org.sonar.api.web.Page :
import org.sonar.api.web.NavigationSection;
import org.sonar.api.web.Page;
import org.sonar.api.web.UserRole;
@NavigationSection(NavigationSection.CONFIGURATION)
@UserRole(UserRole.ADMIN)
public final class MyConsolePage implements Page {
public String getId() {
// URL of the controller
return "/my_sample/index";
}
public String getTitle() {
return "My Console";
}
} |
The development mode reloads Ruby changes on the fly. It allows to edit code and to directly interact with the application. Only the changes on the files that exist during server startup are supported. Adding a new file requires to restart the server.
To enable the development mode on an application :
rails.env to development and jruby.max.runtimes to 3.Edit the file war/sonar-server/WEB-INF/config/environment.rb and set the absolute path to your ruby application by replacing the property config.plugin_paths :
#config.plugin_paths << "#{Java::OrgSonarServerUi::JRubyFacade.getInstance().getServerHome()}/temp/ror"
config.plugin_paths << '/absolute/path/to/sonar-foo-plugin/src/main/resources/org/sonar/ror' |
Web Services are simply packaged as applications. The only differences are that controllers are located in controllers/api/ instead of controllers/, and the class must extend Api::ApiController.
class Api::MyWebServiceController < Api::ApiController
# GET http://<server>/api/my_web_service/index
def index
respond_to do |format|
# returns {'foo': 'bar'}
format.json { render :json => jsonp({'foo' => 'bar'}) }
end
end
end |
The Java extension point org.sonar.api.web.RubyRailsWebservice is still supported but is useless since SonarQube 3.0. |
Plugins can provide static files like images, CSS or JS files. They have to be copied in src/main/resources/static and then can by accessible from the public URL :
http://<server>/static/<plugin key>/<filename> |
The URL can be generated from widgets or applications with the Ruby helper function :
url_for_static(:plugin => '<plugin key>', :path => '<filename>') |
Note that the plugin key is logged during the maven build :
[INFO] ------------------------------------------------------- [INFO] Plugin definition in update center [INFO] Key: foo [INFO] Name: Foo [INFO] Description: [INFO] Version: 1.0-SNAPSHOT |
Static files are not deployed on the fly when the development mode is enabled. The plugin has to be built and re-installed after changes. |
SonarQube integrates JFreechart Eastwood 1.1.0, a partial implementation of the Google Chart API . To know if a chart is implemented, simply replace http://chart.apis.google.com/chart?<params> by http://<sonar>/gchart?<params>.
TBD : protovis.js.