《底层到底做了什么》--- sonar-maven-plugin底层原理

sonar-maven-plugin是sonar在maven中的插件,可以执行sonar命令来执行代码分析功能。

上源码

/**
 * Analyze project. SonarQube server must be started.
 */
@Mojo(name = "sonar", requiresDependencyResolution = ResolutionScope.TEST, aggregator = true)

public class SonarQubeMojo extends AbstractMojo {

SonarQubeMojo是入口类,继承maven的AbstractMojo,表示是一个maven plugin对象。
注释说明使用这个plugin,要先启动SonarQube服务。
从@Mojo,这个plugin定义了一个maven goal:“sonar”,用在Test阶段,支持多模块聚合。


public class SonarQubeMojo extends AbstractMojo {
  @Override
  public void execute() throws MojoExecutionException, MojoFailureException {

//---
    ScannerFactory runnerFactory = new ScannerFactory(logHandler, getLog(), runtimeInformation, mojoExecution, session, envProps, propertyDecryptor);

    EmbeddedScanner runner = runnerFactory.create();
    new ScannerBootstrapper(getLog(), session, runner, mavenProjectConverter, propertyDecryptor).execute();
  }


 

在execute方法里,核心方法是创建EmbeddedScanner扫描器。


public class ScannerFactory {
  public EmbeddedScanner create() {
    setProxySystemProperties();
    EmbeddedScanner scanner = EmbeddedScanner.create("ScannerMaven", mojoExecution.getVersion() + "/" + runtimeInformation.getMavenVersion(), logOutput);
}

在create方法里,调用EmbeddedScanner的create方法。

EmbeddedScanner在sonar-scanner-api包。


public class EmbeddedScanner {
    public static EmbeddedScanner create(String app, String version, LogOutput logOutput, System2 system2) {
        Logger logger = new LoggerAdapter(logOutput);
        return (new EmbeddedScanner(new IsolatedLauncherFactory(logger), logger, logOutput, system2)).setGlobalProperty("sonar.scanner.app", app).setGlobalProperty("sonar.scanner.appVersion", version);
    }


public class IsolatedLauncherFactory implements Closeable {
    public IsolatedLauncherFactory(Logger logger) {
        this("org.sonarsource.scanner.api.internal.batch.BatchIsolatedLauncher", new TempCleaning(logger), logger);
    }

在EmbeddedScanner的创建过程中,通过IsolatedLauncherFactory创建Launcher,Launcher是实际执行的扫描器,默认是BatchIsolatedLauncher。

BatchIsolatedLauncher在sonar-scanner-api-batch包里。


public class BatchIsolatedLauncher implements IsolatedLauncher {

  private final BatchFactory factory;
  @Override
  public void execute(Map properties, org.sonarsource.scanner.api.internal.batch.LogOutput logOutput) {
    factory.createBatch(properties, logOutput).execute();
  }

execute方法创建一个Batch,在sonar-scanner-engine包里,这个包是sonarqube项目的submodule。


public final class Batch {

    private GlobalContainer bootstrapContainer;

    public synchronized Batch execute() {
        this.configureLogging();
        this.doStart();
        boolean threw = true;

        try {
            this.doExecuteTask(this.globalProperties);
            threw = false;
        } finally {
            this.doStop(threw);
        }

        return this;
    }


    private Batch doStart() {
        try {
            this.bootstrapContainer = GlobalContainer.create(this.globalProperties, this.components);
            this.bootstrapContainer.startComponents();
        } catch (RuntimeException var2) {
            throw this.handleException(var2);
        }

        this.started = true;
        return this;
    }


    private Batch doExecuteTask(Map analysisProperties, Object... components) {
        try {
            this.bootstrapContainer.executeTask(analysisProperties, components);
            return this;
        } catch (RuntimeException var4) {
            throw this.handleException(var4);
        }
    }

Batch的核心是bootstrapContainer。

execute方法先doStart创建bootstrapContainer,然后doExecuteTask,调用bootstrapContainer.executeTask。


public class GlobalContainer extends ComponentContainer {


    public void executeTask(Map taskProperties, Object... components) {
        long startTime = System.currentTimeMillis();
        (new TaskContainer(this, taskProperties, components)).execute();
        LOG.info("Task total time: {}", formatTime(System.currentTimeMillis() - startTime));
    }

executeTask方法里创建 TaskContainer 执行。


public class TaskContainer extends ComponentContainer {



public class ComponentContainer implements Container {
    private MutablePicoContainer pico;


    public void execute() {
        boolean threw = true;

        try {
            this.startComponents();
            threw = false;
        } finally {
            this.stopComponents(threw);
        }

    }


    public ComponentContainer startComponents() {
        try {
            this.doBeforeStart();
            this.pico.start();
            this.doAfterStart();
            return this;
        } catch (Exception var2) {
            throw PicoUtils.propagate(var2);
        }
    }

execute实际在父类ComponentContainer里,TaskContainer的里实现了ComponentContainer的doBeforeStart、doAfterStart方法。

ComponentContainer是在sonar-core里,这个包是sonarqube项目的submodule。

查找这里还没有找到实际执行分析的类,尝试从包角度分析。

虽在包sonarqube项目里找到sonar-application,这是一个服务,引入sonar-java-plugin,后者实现了sonar-plugin-api-impl接口,是实际执行java代码分析的包。

还没找到从sonar-coresonar-java-plugin,待后续

你可能感兴趣的:(《底层到底做了什么》--- sonar-maven-plugin底层原理)