前言
某天,来一需求,由于业务线使用ThreadLocal后经常忘记remove,导致出现一些故障。为了可以尽早发现这种使用错误的现象,想在公司使用的sonar上新加一个规则用于检查ThreadLocal。
接下来开始了苦逼的扩展sonar插件。。。。。
no文档,no demo,goole搜到的资料也是寥寥数语,怎么办。。。。。
打开sonar的官方文档,虽然介绍不是很清楚,先看看吧,再想想怎么来实现。
注:sonar官方文档
要写代码还得先看看已有的plugin的代码,因为是扩展java的检查规则,还是看java plugin的source code吧
注:sonar-java source code github site
看代码。。。。。。根本看不懂啊,readme也没有,debug吧,最好的方式,那怎么开始远程debug呢。
如何开始远程debug
debug的方式有好多种,本文主要说说mvn debug方式,怎么用mvn来进行debug。
集成开发环境:IDEA
首先,在idea里添加远程debug remote,设置host为localhost,port:8000
其次,在本地启动sonar,在待检查的工程执行命令mvnDebug sonar:sonar
回到idea里开始远程debug
好,如何开始一次debug大约就是这样,那么,问题来了,断点应该加在哪里???不得不说一下sonar的基本流程了,在说sonar的基本流程之前,先说说sonar的domain吧。
sonar domain
从我了解的数据库的表为点来做一个简单的介绍吧:
public void execute(Project project) {
eventBus.fireEvent(new ProjectAnalysisEvent(project, true));
mavenPluginsConfigurator.execute(project);
mavenPhaseExecutor.execute(project);
initializersExecutor.execute();
persistenceManager.setDelayedMode(true);
sensorsExecutor.execute(sensorContext);
decoratorsExecutor.execute();
persistenceManager.dump();
persistenceManager.setDelayedMode(false);
if (project.isRoot()) {
if (updateStatusJob != null) {
updateStatusJob.execute();
}
postJobsExecutor.execute(sensorContext);
}
cleanMemory();
eventBus.fireEvent(new ProjectAnalysisEvent(project, false));
}
看到这里,大家应该知道debug开始的断点加在哪里,明显是加在实现Sensor接口的类的analysis方法里。
sonar plugin扩展
从上面的代码可以看出plugin的扩展点应该是:sensor,decorator和postjob
接下来详细说一下如何来扩展写一个自己的plugin吧。
详细的一些内容可以参见:sonar plugin扩展
demo:threadLocal plugin
第一步,扩展SonarPlugin,这是plugin的入口,并指定相关plugin所需要的一些class
public class JavaExtensionRulesPlugin extends SonarPlugin {
@Override
public List getExtensions() {
return Arrays.asList(相关扩展类.class);
}
}
第二步,定义自己的rule,包括自己rule所在的repostory
public class JavaExtensionRulesDefinition implements RulesDefinition {
@Override
public void define(Context context) {
NewRepository repository = context.createRepository(RulesList.REPOSITORY_KEY, Java.KEY);
repository.setName(RulesList.REPOSITORY_KEY);
AnnotationBasedRulesDefinition.load(repository, Java.KEY, RulesList.getChecks());
repository.done();
}
}
public class JavaExtensionRulesCheckRegistrar implements CheckRegistrar {
@Override
public void register(RegistrarContext registrarContext) {
registrarContext.registerClassesForRepository(RulesList.REPOSITORY_KEY, Arrays.asList(checkClasses()),
Arrays.asList(testCheckClasses()));
}
/**
* Lists all the checks provided by the plugin
*/
public static Class extends JavaCheck>[] checkClasses() {
return new Class[] { ThreadLocalRemoveRule.class };
}
/**
* Lists all the test checks provided by the plugin
*/
public static Class extends JavaCheck>[] testCheckClasses() {
return new Class[] {};
}
}
需要注意的是:自己扩展plugin,需要告诉检查的那些文件(文件名以什么结尾,java是检查以.java和.jav结尾的文件),不然检查文件的时候sonarqube不知道检查什么文件。我踩过这个坑。
第四步,下面该扩展Sensor了,sensor里包含了文件的扫描,各个rule的check,详细的可以参照前文给出的github demo。
到这里还没完,还有很重要的一步没有做呢,自己的规则不要忘了自己来制定哦,具体怎么制定,参照demo里的threadlocal-plugin-checks这个子工程。
做完上面这些,差不多可以结束了,接下来想要你的plugin生效还需要把plugin打成jar包并添加到sonarqube/extensions/plugins下,重启sonar,就可以了。
接下来说说我在扩展plugin的时候遇到的坑:
org.apache.maven.plugins
maven-dependency-plugin
copy-dependencies
process-resources
copy-dependencies
true
${project.build.outputDirectory}
annotations,jsr305,fb-contrib,sonar-threadlocal-plugin
org.sonarsource.sonar-packaging-maven-plugin
sonar-packaging-maven-plugin
1.15
true
org.sonarqube.extension.plugin.JavaExtensionRulesPlugin
org.apache.maven.plugins
maven-compiler-plugin
3.3
1.7
Failed to execute goal com.mycila.maven-license-plugin:maven-license-plugin:1.10.b1:check (enforce-license-headers) on project threadlocal-plugins: Some files do not have the expected license header -> [H
elp 1]
出现这个错误是因为在打包时会检查每一个类的头部有没有用注释写一段东西,类似于这样:
This bundle contains Java Service Wrapper scripts and binaries version 3.2.3 from Tanukisoftware published
under the following license:
Copyright (c) 2001 Silver Egg Technology
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sub-license, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
http://web.archive.org/web/20070622164715/wrapper.tanukisoftware.org/doc/english/license.html
我比较懒,提供一个跳过license检查的方式吧:在mvn的命令尾部加上:
-Dlicense.skip=true
就可以成功的跳过检查了;
activate之后,是这样子的:
再次在待检查工程执行mvn sonar:sonar,你的rule生效了。
后记
到这里基本就结束了,希望对大家的开发有所帮助,有什么问题的也可以留言问我。