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? I’m unfamiliar with the scope/lifecycle of my plugin objects. Are they unique per scan or per SonarQube server instance?

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.
        }
    }
}

Hi Andrew,

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.
        }
    }
}
3 Likes

Thank you for the explanation and solution! I also posted this question on StackOverflow. If you post your answer there, I’ll be happy to accept it.

I’m confused about the use of getScannerContext() in MyPostAnalysisTask.finished()

Where is that method defined or how should I implement it?

My code is wrong, I will fix it, but basically I was talking about:
https://github.com/SonarSource/sonar-enterprise/blob/8c967ce3557173869a99a28bd2083a1ee56ed8a5/sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/PostProjectAnalysisTask.java#L122

1 Like

Thank you for your help. I have published my plugin here: https://github.com/aensley/sonar-teams-notifier

Hopefully this will help someone else!