sonarqubesonarqube-scan

SonarQube access API from sensor


I want to execute an API call to Sonar Server from my implementation of org.sonar.api.scanner.sensor.ProjectSensor. Is there any "compliant" way to execute e.g.:

https://myserver:9001/api/rules/search?languages=java&tags=regex&f=internalKey

using e.g. the given org.sonar.api.batch.sensor.SensorContext? I could get the Host url from variables and create my own connection and parse the result... but that would be much overhead, if there is a compliant way.

Best regards

Jens


Solution

  • For anybody facing a similar issue:

    I used the java http client and the included jackson library to do my requests. Here is an example for a get request:

    1st you need some data from the SensorContext:

    context.config().get("sonar.host.url").orElse("http://localhost:9000")
    context.config().get("sonar.login").orElse("")
    

    With these values you can establish a connection:

    public static String get(String uri, String sonarLogin) throws IOException, InterruptedException {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
              .uri(URI.create(uri))
              .header("Authorization", "Basic " + Base64.getEncoder().encodeToString((sonarLogin+":").getBytes()))
              .build();
    
        HttpResponse<String> response =
              client.send(request, BodyHandlers.ofString());
        return response.body();
    }
    

    Where URI is build for my case with:

    private static String getUrl(String sonarUrl, String language, String tag) {
        StringBuilder builder = new StringBuilder(1024);
        builder.append(sonarUrl);
        if (!sonarUrl.endsWith("/")) {
            builder.append("/");
        }
        builder.append("api/rules/search?f=internalKey&ps=500");
        builder.append("&language=").append(language);
        builder.append("&tags=").append(tag);
        builder.append("&p=");
        return builder.toString();
    }
    

    The response String can be processed with Jackson as it is in JSON format. You need to create matching Java POJO's for your query to do so. For the paging (p=... ) needs to be added. The response contains a value total, and your value for p you must loop 0..x with x= ((double)total/(double)ps).intValue(); where ps is the pagesize (<=500)

    Please note: this is a very simple example. Especially the page size (ps=500) might not work for you, if you have larger amounts of data. There is also a way to transfer data via protobuf, if you need to minimize the response.