import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import org.sonar.gwt.ui.Page;
+import org.sonar.wsclient.gwt.AbstractCallback;
+import org.sonar.wsclient.gwt.Sonar;
+import org.sonar.wsclient.services.Measure;
import org.sonar.wsclient.services.Resource;
+import org.sonar.wsclient.services.ResourceQuery;
public class SampleViewerPanel extends Page {
+ private Label label;
+
@Override
protected Widget doOnResourceLoad(Resource resource) {
- return new Label("This is a sample");
+ label = new Label("Loading value");
+ loadMeasureFromServer(resource);
+ return label;
+ }
+
+ // Ajax call to web service
+ private void loadMeasureFromServer(Resource resource) {
+ ResourceQuery query = ResourceQuery.createForResource(resource, "random");
+ Sonar.getInstance().find(query, new AbstractCallback<Resource>() {
+ @Override
+ protected void doOnResponse(Resource result) {
+ Measure measure = result.getMeasure("random");
+ if (measure==null || measure.getValue()==null) {
+ label.setText("No random value");
+ } else {
+ label.setText("Random value inserted during analysis: " + measure.getValue());
+ }
+ }
+ });
}
}
\ No newline at end of file
+++ /dev/null
-package com.mycompany.sonar.standard;
-
-import org.sonar.api.web.Footer;
-
-public final class SampleFooter implements Footer {
- public String getHtml() {
- return "<p>Sample footer - <em>This is static HTML</em></p>";
- }
-}
package com.mycompany.sonar.standard;
+import com.mycompany.sonar.standard.batch.RandomDecorator;
+import com.mycompany.sonar.standard.batch.SampleSensor;
+import com.mycompany.sonar.standard.rules.SampleQualityProfile;
+import com.mycompany.sonar.standard.rules.SampleRuleRepository;
+import com.mycompany.sonar.standard.ui.SampleFooter;
+import com.mycompany.sonar.standard.ui.SampleRubyWidget;
import org.sonar.api.SonarPlugin;
import java.util.Arrays;
// This is where you're going to declare all your Sonar extensions
public List getExtensions() {
return Arrays.asList(
- SampleMetrics.class, SampleSensor.class, SampleRubyWidget.class,
+ // Definitions
+ SampleRuleRepository.class, SampleMetrics.class, SampleQualityProfile.class,
+
+ // Batch
+ SampleSensor.class, RandomDecorator.class,
// UI
- SampleFooter.class);
+ SampleFooter.class, SampleRubyWidget.class);
}
}
\ No newline at end of file
+++ /dev/null
-package com.mycompany.sonar.standard;
-
-import org.sonar.api.web.*;
-
-@UserRole(UserRole.USER)
-@Description("Show how to use Ruby Widget API")
-@WidgetProperties({
- @WidgetProperty(key="param1",
- description="This is a mandatory parameter",
- optional=false
- ),
- @WidgetProperty(key="max",
- description="max threshold",
- type=WidgetPropertyType.INTEGER,
- defaultValue="80"
- ),
- @WidgetProperty(key="param2",
- description="This is an optional parameter"
- ),
- @WidgetProperty(key="floatprop",
- description="test description"
- )
-})
-public class SampleRubyWidget extends AbstractRubyTemplate implements RubyRailsWidget {
-
- public String getId() {
- return "sample";
- }
-
- public String getTitle() {
- return "Sample";
- }
-
- @Override
- protected String getTemplatePath() {
- return "/sample_ruby_widget.html.erb";
- }
-}
\ No newline at end of file
+++ /dev/null
-package com.mycompany.sonar.standard;
-
-import org.apache.commons.lang.math.RandomUtils;
-import org.sonar.api.batch.Sensor;
-import org.sonar.api.batch.SensorContext;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.resources.Project;
-
-public class SampleSensor implements Sensor {
-
- public boolean shouldExecuteOnProject(Project project) {
- // this sensor is executed on any type of project
- return true;
- }
-
- public void analyse(Project project, SensorContext sensorContext) {
- saveLabelMeasure(sensorContext);
- saveNumericMeasure(sensorContext);
- }
-
- private void saveNumericMeasure(SensorContext context) {
- // Sonar API includes many libraries like commons-lang and google-collections
- context.saveMeasure(SampleMetrics.RANDOM, RandomUtils.nextDouble());
- }
-
- private void saveLabelMeasure(SensorContext context) {
- Measure measure = new Measure(SampleMetrics.MESSAGE, "Hello World!");
- context.saveMeasure(measure);
- }
-}
--- /dev/null
+package com.mycompany.sonar.standard.batch;
+
+import com.mycompany.sonar.standard.SampleMetrics;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.math.RandomUtils;
+import org.sonar.api.batch.Decorator;
+import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.measures.MeasureUtils;
+import org.sonar.api.resources.Java;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.resources.Scopes;
+
+public class RandomDecorator implements Decorator {
+
+ public boolean shouldExecuteOnProject(Project project) {
+ // Execute only on Java projects
+ return StringUtils.equals(project.getLanguageKey(), Java.KEY);
+ }
+
+ public void decorate(Resource resource, DecoratorContext context) {
+ // This method is executed on the whole tree of resources.
+ // Bottom-up navigation : Java methods -> Java classes -> files -> packages -> modules -> project
+ if (Scopes.isBlockUnit(resource)) {
+ // Sonar API includes many libraries like commons-lang and google-collections
+ double value = RandomUtils.nextDouble();
+
+ // Add a measure to the current Java method
+ context.saveMeasure(SampleMetrics.RANDOM, value);
+
+ } else {
+ // we sum random values on resources different than method
+ context.saveMeasure(SampleMetrics.RANDOM, MeasureUtils.sum(true, context.getChildrenMeasures(SampleMetrics.RANDOM)));
+ }
+ }
+}
--- /dev/null
+package com.mycompany.sonar.standard.batch;
+
+import com.mycompany.sonar.standard.SampleMetrics;
+import org.sonar.api.batch.Sensor;
+import org.sonar.api.batch.SensorContext;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.resources.Project;
+
+public class SampleSensor implements Sensor {
+
+ public boolean shouldExecuteOnProject(Project project) {
+ // This sensor is executed on any type of projects
+ return true;
+ }
+
+ public void analyse(Project project, SensorContext sensorContext) {
+ Measure measure = new Measure(SampleMetrics.MESSAGE, "Hello World!");
+ sensorContext.saveMeasure(measure);
+ }
+}
--- /dev/null
+package com.mycompany.sonar.standard.rules;
+
+import org.sonar.api.profiles.ProfileDefinition;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.resources.Java;
+import org.sonar.api.rules.RulePriority;
+import org.sonar.api.utils.ValidationMessages;
+
+public class SampleQualityProfile extends ProfileDefinition {
+
+ private SampleRuleRepository ruleRepository;
+
+ // The component ruleRepository is injected at runtime
+ public SampleQualityProfile(SampleRuleRepository ruleRepository) {
+ this.ruleRepository = ruleRepository;
+ }
+
+ @Override
+ public RulesProfile createProfile(ValidationMessages validation) {
+ RulesProfile profile = RulesProfile.create("Sample profile", Java.KEY);
+ profile.activateRule(ruleRepository.getRule1(), RulePriority.MAJOR);
+ profile.activateRule(ruleRepository.getRule1(), null);
+ return profile;
+ }
+}
--- /dev/null
+package com.mycompany.sonar.standard.rules;
+
+import org.sonar.api.resources.Java;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RulePriority;
+import org.sonar.api.rules.RuleRepository;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class SampleRuleRepository extends RuleRepository {
+
+ public static final String REPOSITORY_KEY = "sample";
+
+ public SampleRuleRepository() {
+ super(REPOSITORY_KEY, Java.KEY);
+ setName("Sample");
+ }
+
+ @Override
+ public List<Rule> createRules() {
+ // This method is called when server is started. It's used to register rules into database.
+ // Definition of rules can be loaded from any sources, like XML files.
+ return Arrays.asList(
+ getRule1(),
+ getRule2());
+ }
+
+ public Rule getRule1() {
+ return Rule.create(REPOSITORY_KEY, "fake1", "Fake one").setSeverity(RulePriority.CRITICAL);
+ }
+
+ public Rule getRule2() {
+ return Rule.create(REPOSITORY_KEY, "fake2", "Fake two").setDescription("Description of fake two");
+ }
+}
--- /dev/null
+package com.mycompany.sonar.standard.ui;
+
+import org.sonar.api.web.Footer;
+
+public final class SampleFooter implements Footer {
+ public String getHtml() {
+ return "<p>Sample footer - <em>This is static HTML</em></p>";
+ }
+}
--- /dev/null
+package com.mycompany.sonar.standard.ui;
+
+import org.sonar.api.web.*;
+
+@UserRole(UserRole.USER)
+@Description("Show how to use Ruby Widget API")
+@WidgetCategory("Sample")
+@WidgetProperties({
+ @WidgetProperty(key="param1",
+ description="This is a mandatory parameter",
+ optional=false
+ ),
+ @WidgetProperty(key="max",
+ description="max threshold",
+ type=WidgetPropertyType.INTEGER,
+ defaultValue="80"
+ ),
+ @WidgetProperty(key="param2",
+ description="This is an optional parameter"
+ ),
+ @WidgetProperty(key="floatprop",
+ description="test description"
+ )
+})
+public class SampleRubyWidget extends AbstractRubyTemplate implements RubyRailsWidget {
+
+ public String getId() {
+ return "sample";
+ }
+
+ public String getTitle() {
+ return "Sample";
+ }
+
+ @Override
+ protected String getTemplatePath() {
+ return "/sample_ruby_widget.html.erb";
+ }
+}
\ No newline at end of file