Skip to content

Commit

Permalink
Fixed 4 and Implemented #3
Browse files Browse the repository at this point in the history
  • Loading branch information
sertic committed Jan 28, 2016
1 parent e765d3a commit 2e488db
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,34 @@ public class MavenSonarSputnikMojo extends AbstractMojo {
private String gerritRevision;

/**
* The Sputnik configuration property file..
* The Sputnik configuration property file.
*/
@Parameter(defaultValue = "${sputnikConfiguration}", required = true)
private File sputnikConfiguration;

/**
* The Sonar configuration property file..
* The Sonar configuration property file.
*/
@Parameter(defaultValue = "${sonarConfiguration}", required = true)
private File sonarConfiguration;

/**
* Ignore generated sources located inside the project output directory /target/*.
*/
@Parameter(defaultValue = "true", required = true)
private boolean ignoreGeneratedCode;

private Properties sputnikProperties;

private Properties sonarProperties;

private boolean isIgnored(MavenProject aProject, File aFile) {
if (ignoreGeneratedCode) {
return aFile.toString().startsWith(aProject.getBuild().getDirectory());
}
return false;
}

private void listModulesFor(String aPrefix, MavenProject aProject, int aRecursionLevel, List<MavenProject> aProjectList)
throws IOException {
StringBuilder theBuilder = new StringBuilder();
Expand Down Expand Up @@ -97,7 +110,7 @@ private void listModulesFor(String aPrefix, MavenProject aProject, int aRecursio
StringBuilder theSourceRoots = new StringBuilder();
for (String theSourceRoot : aProject.getCompileSourceRoots()) {
File theFile = new File(theSourceRoot);
if (theFile.exists()) {
if (theFile.exists() && !isIgnored(aProject, theFile)) {
String theFullName = theSourceRoot;
theFullName = theFullName.substring(aProject.getBasedir().toString().length() + 1);

Expand All @@ -111,7 +124,7 @@ private void listModulesFor(String aPrefix, MavenProject aProject, int aRecursio
StringBuilder theTestRoots = new StringBuilder();
for (String theSourceRoot : aProject.getTestCompileSourceRoots()) {
File theFile = new File(theSourceRoot);
if (theFile.exists()) {
if (theFile.exists() && !isIgnored(aProject, theFile)) {
String theFullName = theSourceRoot;
theFullName = theFullName.substring(aProject.getBasedir().toString().length() + 1);

Expand Down
110 changes: 110 additions & 0 deletions src/main/java/pl/touk/sputnik/processor/sonar/SonarProcessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package pl.touk.sputnik.processor.sonar;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import com.google.common.annotations.VisibleForTesting;

import pl.touk.sputnik.configuration.Configuration;
import pl.touk.sputnik.configuration.GeneralOption;
import pl.touk.sputnik.review.Review;
import pl.touk.sputnik.review.ReviewException;
import pl.touk.sputnik.review.ReviewFile;
import pl.touk.sputnik.review.ReviewProcessor;
import pl.touk.sputnik.review.ReviewResult;
import pl.touk.sputnik.review.Violation;

@Slf4j
public class SonarProcessor implements ReviewProcessor {

private static final String PROCESSOR_NAME = "Sonar";

private SonarRunnerBuilder sonarRunnerBuilder;
private final Configuration configuration;

public SonarProcessor(@NotNull final Configuration configuration) {
this(new SonarRunnerBuilder(), configuration);
}

public SonarProcessor(SonarRunnerBuilder sonarRunnerBuilder, @NotNull final Configuration configuration) {
this.sonarRunnerBuilder = sonarRunnerBuilder;
this.configuration = configuration;
}

@Nullable
@Override
public ReviewResult process(@NotNull Review review) {
if (review.getFiles().isEmpty()) {
return new ReviewResult();
}

try {
SonarRunner runner = sonarRunnerBuilder.prepareRunner(review, configuration);
File resultFile = runner.run();
SonarResultParser parser = new SonarResultParser(resultFile);

final Properties theSonarProperties = new Properties();
for (final String property: StringUtils.split(configuration.getProperty(GeneralOption.SONAR_PROPERTIES), ',')){
final File propertyFile = new File(StringUtils.strip(property));
log.info("Loading {}", propertyFile.getAbsolutePath());
theSonarProperties.load(new FileInputStream(propertyFile));
}

String theAdditionalFileNames = theSonarProperties.getProperty("sonar.additionalReviewCommentFiles");
if (theAdditionalFileNames != null) {
for (String theFileName : StringUtils.split(theAdditionalFileNames,",")) {
File theSingleFile = new File(resultFile.getParent(), theFileName);
if (theSingleFile.exists()) {
log.info("Adding {} to review comment", theSingleFile);
try (FileInputStream theStream = new FileInputStream(theSingleFile)) {
review.getMessages().add(IOUtils.toString(theStream) + "\n\n");
}
} else {
log.info("Skipping {} as it does not exist", theSingleFile);
}
}
}

return filterResults(parser.parseResults(), review);
}
catch (IOException e) {
throw new ReviewException("SonarResultParser error", e);
}
}

/**
* Filters a ReviewResult to keep only the violations that are about a file
* which is modified by a given review.
*/
@VisibleForTesting
ReviewResult filterResults(ReviewResult results, Review review) {
ReviewResult filteredResults = new ReviewResult();
Set<String> reviewFiles = new HashSet<>();
for (ReviewFile file : review.getFiles()) {
reviewFiles.add(file.getReviewFilename());
}
for (Violation violation : results.getViolations()) {
if (reviewFiles.contains(violation.getFilenameOrJavaClassName())) {
filteredResults.add(violation);
}
}
return filteredResults;
}

@NotNull
@Override
public String getName() {
return PROCESSOR_NAME;
}
}
85 changes: 85 additions & 0 deletions src/main/java/pl/touk/sputnik/processor/sonar/SonarRunner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package pl.touk.sputnik.processor.sonar;

import com.google.common.annotations.VisibleForTesting;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.sonar.runner.api.EmbeddedRunner;
import pl.touk.sputnik.configuration.Configuration;
import pl.touk.sputnik.configuration.GeneralOption;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Properties;

@Slf4j
@AllArgsConstructor
public class SonarRunner {

private final List<String> files;
private final EmbeddedRunner sonarEmbeddedRunner;
private final Configuration configuration;

@VisibleForTesting
static final String OUTPUT_DIR = ".sonar";

@VisibleForTesting
static final String OUTPUT_FILE = "sonar-report.json";

/**
* Load base sonar configuration files specified by GeneralOption.SONAR_PROPERTIES
* configuration key
* @return a Properties instance
* @throws IOException
*/
@VisibleForTesting
Properties loadBaseProperties() throws IOException {
final Properties props = new Properties();
setAdditionalProperties(props);
for (final String property: StringUtils.split(configuration.getProperty(GeneralOption.SONAR_PROPERTIES), ',')){
final File propertyFile = new File(StringUtils.strip(property));
log.info("Loading {}", propertyFile.getAbsolutePath());
props.load(new FileInputStream(propertyFile));
}
return props;
}

/**
* Runs Sonar.
*
* @throws IOException
* @return the json file containing the results.
*/
public File run() throws IOException {
Properties props = loadBaseProperties();

String theInclusions = props.getProperty(SonarProperties.INCLUDE_FILES);
if (theInclusions != null && StringUtils.isEmpty(theInclusions)) {
props.remove(SonarProperties.INCLUDE_FILES);
}

log.info("Sonar configuration: {}", props.toString());
sonarEmbeddedRunner.addProperties(props);
sonarEmbeddedRunner.execute();
return new File(OUTPUT_DIR, OUTPUT_FILE);
}

/**
* Set additional properties needed for sonar to run
* @param props a Properties instance
*/
@VisibleForTesting
void setAdditionalProperties(Properties props) {
props.put(SonarProperties.INCLUDE_FILES, StringUtils.join(files, ", "));
props.put(SonarProperties.ANALISYS_MODE, "incremental");
props.put(SonarProperties.SCM_ENABLED, "false");
props.put(SonarProperties.SCM_STAT_ENABLED, "false");
props.put(SonarProperties.ISSUEASSIGN_PLUGIN, "false");
props.put(SonarProperties.EXPORT_PATH, OUTPUT_FILE);
props.put(SonarProperties.VERBOSE, configuration.getProperty(GeneralOption.SONAR_VERBOSE));
props.put(SonarProperties.WORKDIR, OUTPUT_DIR);
props.put(SonarProperties.PROJECT_BASEDIR, ".");
}
}
2 changes: 1 addition & 1 deletion src/main/resources/default-sputnik.properties
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ jslint.enabled=false
jshint.enabled=false
jshint.configurationFile=jshint.json
sonar.enabled=true
sonar.verbose=true
sonar.verbose=false

0 comments on commit 2e488db

Please sign in to comment.