Search code examples
javasonarqubesonarscanner

SonarQube Plugin Post Analysis Task only when Scanner Parameter set


I'm developing a plugin for SonarQube that will run a custom post analysis task, but only if a named scanner parameter is supplied to the sonar-scanner command. Can I do something like this?

public class MyPlugin implements Plugin {
    @Override
    public void define(Context context) {
        context.addExtension(MyPostAnalysisTask.class);
    }
}

public class MyPostAnalysisTask implements PostProjectAnalysisTask, Sensor {

    private String param = "";

    @Override
    public void describe(SensorDescriptor descriptor) {
        descriptor.name(getClass().getName());
    }

    @Override
    public void execute(SensorContext context) {
        // Get command line param.
        Optional<String> param = context.config().get('my.param.name');
        if (param.isPresent()) {
            this.param = param.get();
        }
    }

    @Override
    public void finished(final ProjectAnalysis analysis) {
        if (!this.param.isEmpty()) {
            // Perform custom post analysis task.
        }
    }
}

I'm unfamiliar with the scope/lifecycle of my plugin objects. Are they unique per scan or per SonarQube server instance?


Solution

  • Sensor is a scanner side extension point. It will run during the analysis on your build agent. PostProjectAnalysisTask is a server side extension point, that will be instantiated/called at the end of the analysis report processing. You can’t share state like you did using a class attribute, since at runtime two classes will be instantiated on different JVM.

    I think it is better to implement the two extension points in separate classes, and use the scanner context to pass values between scanner side and server side:

    public class MyPlugin implements Plugin {
        @Override
        public void define(Context context) {
            context.addExtensions(
                MySensor.class, 
                MyPostAnalysisTask.class);
        }
    }
    
    public class MySensor implements Sensor {
    
        @Override
        public void describe(SensorDescriptor descriptor) {
            descriptor.name(getClass().getName());
        }
    
        @Override
        public void execute(SensorContext context) {
            // Get command line param.
            Optional<String> param = context.config().get("my.param.name");
            if (param.isPresent()) {
                context.addContextProperty("my.context.key", param.get());
            }
        }
    }
    
    public class MyPostAnalysisTask implements PostProjectAnalysisTask {
    
        @Override
        public void finished(final ProjectAnalysis analysis) {
            if (analysis.getScannerContext().getProperties().containsKey("my.context.key")) {
                // Perform custom post analysis task.
            }
        }
    }