Browse Source

SONAR-1772: Remove the use of the Maven Findbugs plugin to directly pilot the Findbugs library

tags/2.6
Godin 13 years ago
parent
commit
7e212fe31c

+ 40
- 2
plugins/sonar-findbugs-plugin/pom.xml View File

@@ -17,11 +17,50 @@
<findbugs.version>1.3.9</findbugs.version>
</properties>
<dependencyManagement>
<!-- Change versions for dependencies provided by sonar-plugin-api -->
<dependencies>
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>xalan</groupId>
<artifactId>xalan</artifactId>
<version>2.6.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-plugin-api</artifactId>
<version>${project.version}</version>
<exclusions>
<exclusion>
<groupId>xalan</groupId>
<artifactId>xalan</artifactId>
</exclusion>
<exclusion>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
</exclusion>
<exclusion>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
</exclusion>
<exclusion>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>findbugs</artifactId>
<version>${findbugs.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.sonar</groupId>
@@ -63,12 +102,11 @@
<plugin>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-packaging-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<pluginKey>findbugs</pluginKey>
<pluginName>Findbugs</pluginName>
<pluginDescription><![CDATA[Analyze Java code with <a href="http://findbugs.sourceforge.net/">Findbugs</a> ${findbugs.version}.]]></pluginDescription>
<pluginClass>org.sonar.plugins.findbugs.FindbugsPlugin</pluginClass>
<useChildFirstClassLoader>true</useChildFirstClassLoader>
</configuration>
</plugin>
<plugin>

+ 67
- 0
plugins/sonar-findbugs-plugin/src/main/java/org/sonar/plugins/findbugs/FindbugsConfiguration.java View File

@@ -0,0 +1,67 @@
package org.sonar.plugins.findbugs;

import org.sonar.api.BatchExtension;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.SonarException;
import org.sonar.plugins.findbugs.xml.ClassFilter;
import org.sonar.plugins.findbugs.xml.FindBugsFilter;
import org.sonar.plugins.findbugs.xml.Match;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;

/**
* @since 2.4
*/
public class FindbugsConfiguration implements BatchExtension {

private Project project;
private RulesProfile profile;
private FindbugsProfileExporter exporter;

public FindbugsConfiguration(Project project, RulesProfile profile, FindbugsProfileExporter exporter) {
this.project = project;
this.profile = profile;
this.exporter = exporter;
}

public File getTargetXMLReport() {
if (project.getConfiguration().getBoolean(FindbugsConstants.GENERATE_XML_KEY, FindbugsConstants.GENERATE_XML_DEFAULT_VALUE)) {
return new File(project.getFileSystem().getSonarWorkingDirectory(), "findbugs-result.xml");
}
return null;
}

public edu.umd.cs.findbugs.Project getFindbugsProject() {
try {
edu.umd.cs.findbugs.Project findbugsProject = new edu.umd.cs.findbugs.Project();
for (File dir : project.getFileSystem().getSourceDirs()) {
findbugsProject.addSourceDir(dir.getAbsolutePath());
}
findbugsProject.addFile(project.getFileSystem().getBuildOutputDir().getAbsolutePath());
findbugsProject.setCurrentWorkingDirectory(project.getFileSystem().getBuildDir());
return findbugsProject;
} catch (Exception e) {
throw new SonarException(e);
}
}

public File saveIncludeConfigXml() throws IOException {
StringWriter conf = new StringWriter();
exporter.exportProfile(profile, conf);
return project.getFileSystem().writeToWorkingDirectory(conf.toString(), "findbugs-include.xml");
}

public File saveExcludeConfigXml() throws IOException {
FindBugsFilter findBugsFilter = new FindBugsFilter();
if (project.getExclusionPatterns() != null) {
for (String exclusion : project.getExclusionPatterns()) {
ClassFilter classFilter = new ClassFilter(FindbugsAntConverter.antToJavaRegexpConvertor(exclusion));
findBugsFilter.addMatch(new Match(classFilter));
}
}
return project.getFileSystem().writeToWorkingDirectory(findBugsFilter.toXml(), "findbugs-exclude.xml");
}
}

+ 6
- 0
plugins/sonar-findbugs-plugin/src/main/java/org/sonar/plugins/findbugs/FindbugsConstants.java View File

@@ -27,4 +27,10 @@ public final class FindbugsConstants {
public static final String REPOSITORY_NAME = "Findbugs";
public static final String PLUGIN_NAME = "Findbugs";
public static final String PLUGIN_KEY = CoreProperties.FINDBUGS_PLUGIN;

/**
* @since 2.4
*/
public static final String GENERATE_XML_KEY = "sonar.findbugs.generateXml";
public static final boolean GENERATE_XML_DEFAULT_VALUE = true; // TODO should be false
}

+ 85
- 0
plugins/sonar-findbugs-plugin/src/main/java/org/sonar/plugins/findbugs/FindbugsExecutor.java View File

@@ -0,0 +1,85 @@
package org.sonar.plugins.findbugs;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.NullOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.BatchExtension;
import org.sonar.api.utils.SonarException;
import org.sonar.api.utils.TimeProfiler;

import edu.umd.cs.findbugs.*;
import edu.umd.cs.findbugs.annotations.Priority;
import edu.umd.cs.findbugs.config.UserPreferences;

import java.io.File;
import java.io.OutputStream;
import java.io.PrintStream;

/**
* @since 2.4
*/
public class FindbugsExecutor implements BatchExtension {
private static Logger LOG = LoggerFactory.getLogger(FindbugsExecutor.class);

private FindbugsConfiguration configuration;

public FindbugsExecutor(FindbugsConfiguration configuration) {
this.configuration = configuration;
}

public File execute() {
TimeProfiler profiler = new TimeProfiler().start("Execute Findbugs");
ClassLoader initialClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(FindBugs2.class.getClassLoader());

OutputStream xmlOutput = null;
try {
final FindBugs2 engine = new FindBugs2();

Project project = configuration.getFindbugsProject();
engine.setProject(project);

XMLBugReporter xmlBugReporter = new XMLBugReporter(project);
xmlBugReporter.setPriorityThreshold(Priority.LOW.getPriorityValue());
// xmlBugReporter.setErrorVerbosity(BugReporter.SILENT);

File xmlReport = configuration.getTargetXMLReport();
if (xmlReport != null) {
LOG.info("Findbugs output report: " + xmlReport.getAbsolutePath());
xmlOutput = FileUtils.openOutputStream(xmlReport);
} else {
xmlOutput = new NullOutputStream();
}
xmlBugReporter.setOutputStream(new PrintStream(xmlOutput));

engine.setBugReporter(xmlBugReporter);

engine.setProject(project);

engine.setDetectorFactoryCollection(DetectorFactoryCollection.instance());
UserPreferences userPreferences = UserPreferences.createDefaultUserPreferences();
userPreferences.setEffort(UserPreferences.EFFORT_DEFAULT);

engine.addFilter(configuration.saveIncludeConfigXml().getAbsolutePath(), true);
engine.addFilter(configuration.saveExcludeConfigXml().getAbsolutePath(), false);

engine.setUserPreferences(userPreferences);
engine.setAnalysisFeatureSettings(FindBugs.DEFAULT_EFFORT);

engine.finishSettings();

engine.execute();

profiler.stop();
return xmlReport;
} catch (Exception e) {
throw new SonarException("Can not execute Findbugs", e);
} finally {
IOUtils.closeQuietly(xmlOutput);
Thread.currentThread().setContextClassLoader(initialClassLoader);
}
}

}

+ 56
- 0
plugins/sonar-findbugs-plugin/src/main/java/org/sonar/plugins/findbugs/FindbugsNativeSensor.java View File

@@ -0,0 +1,56 @@
package org.sonar.plugins.findbugs;

import org.apache.commons.lang.StringUtils;
import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.JavaFile;
import org.sonar.api.resources.Project;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.rules.Violation;

import java.util.List;

/**
* EXPERIMENTAL!
*
* @since 2.4
*/
public class FindbugsNativeSensor implements Sensor {

private RulesProfile profile;
private RuleFinder ruleFinder;
private FindbugsExecutor executor;

public FindbugsNativeSensor(RulesProfile profile, RuleFinder ruleFinder, FindbugsExecutor executor) {
this.profile = profile;
this.ruleFinder = ruleFinder;
this.executor = executor;
}

public boolean shouldExecuteOnProject(Project project) {
return project.getFileSystem().hasJavaSourceFiles()
&& ( !profile.getActiveRulesByRepository(FindbugsConstants.REPOSITORY_KEY).isEmpty() || project.getReuseExistingRulesConfig())
&& project.getPom() != null && !StringUtils.equalsIgnoreCase(project.getPom().getPackaging(), "ear");
}

public void analyse(Project project, SensorContext context) {
FindbugsXmlReportParser reportParser = new FindbugsXmlReportParser(executor.execute());
List<FindbugsXmlReportParser.Violation> fbViolations = reportParser.getViolations();
for (FindbugsXmlReportParser.Violation fbViolation : fbViolations) {
Rule rule = ruleFinder.findByKey(FindbugsConstants.REPOSITORY_KEY, fbViolation.getType());
JavaFile resource = new JavaFile(fbViolation.getSonarJavaFileKey());
if (context.getResource(resource) != null) {
Violation violation = Violation.create(rule, resource).setLineId(fbViolation.getStart()).setMessage(fbViolation.getLongMessage());
context.saveViolation(violation);
}
}
}

@Override
public String toString() {
return getClass().getSimpleName();
}

}

+ 4
- 2
plugins/sonar-findbugs-plugin/src/main/java/org/sonar/plugins/findbugs/FindbugsPlugin.java View File

@@ -69,8 +69,10 @@ public class FindbugsPlugin implements Plugin {

public List<Class<? extends Extension>> getExtensions() {
List<Class<? extends Extension>> list = new ArrayList<Class<? extends Extension>>();
list.add(FindbugsSensor.class);
list.add(FindbugsMavenPluginHandler.class);
list.add(FindbugsNativeSensor.class);
list.add(FindbugsConfiguration.class);
list.add(FindbugsExecutor.class);
// list.add(FindbugsMavenPluginHandler.class);
list.add(FindbugsRuleRepository.class);
list.add(FindbugsProfileExporter.class);
list.add(FindbugsProfileImporter.class);

+ 42
- 0
plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FindbugsExecutorTest.java View File

@@ -0,0 +1,42 @@
package org.sonar.plugins.findbugs;

import org.apache.commons.io.FileUtils;
import org.junit.Test;

import edu.umd.cs.findbugs.Project;

import java.io.File;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.junit.internal.matchers.StringContains.containsString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class FindbugsExecutorTest {

@Test
public void canGenerateXMLReport() throws Exception {
FindbugsConfiguration conf = mockConf();
File report = new File("target/test-tmp/findbugs-report.xml");
when(conf.getTargetXMLReport()).thenReturn(report);
FindbugsExecutor executor = new FindbugsExecutor(conf);
executor.execute();

assertThat(report.exists(), is(true));
assertThat(FileUtils.readFileToString(report), containsString("<BugInstance"));
}

private FindbugsConfiguration mockConf() throws Exception {
FindbugsConfiguration conf = mock(FindbugsConfiguration.class);
Project project = new Project();
project.addFile(new File("test-resources/classes").getCanonicalPath());
project.addSourceDir(new File("test-resources/src").getCanonicalPath());
project.setCurrentWorkingDirectory(new File("test-resources"));
when(conf.getFindbugsProject()).thenReturn(project);
when(conf.saveExcludeConfigXml()).thenReturn(new File("test-resources/findbugs-exclude.xml"));
when(conf.saveIncludeConfigXml()).thenReturn(new File("test-resources/findbugs-include.xml"));
return conf;
}

}

BIN
plugins/sonar-findbugs-plugin/test-resources/classes/Hello.class View File


+ 1
- 0
plugins/sonar-findbugs-plugin/test-resources/findbugs-exclude.xml View File

@@ -0,0 +1 @@
<FindBugsFilter/>

+ 1129
- 0
plugins/sonar-findbugs-plugin/test-resources/findbugs-include.xml
File diff suppressed because it is too large
View File


+ 13
- 0
plugins/sonar-findbugs-plugin/test-resources/src/Hello.java View File

@@ -0,0 +1,13 @@
class Hello {

static String name;
public void methodWithViolations(String n) {
name = n;
}
@Override
public boolean equals(Object obj) {
return false;
}
}

Loading…
Cancel
Save