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-core到sonar-java-plugin,待后续