Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a sourcesPaths array tag that will add multiple Sources to the … #43

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 117 additions & 9 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,50 @@
.DS_Store

# Created by .ignore support plugin (hsz.mobi)
### Eclipse template
*.pydevproject
.metadata
.gradle
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
*.log

# Eclipse Core
.project

# External tool builders
.externalToolBuilders/

# Locally stored "Eclipse launch configurations"
*.launch

# CDT-specific
.cproject

# JDT-specific (Eclipse Java Development Tools)
.classpath

# Java annotation processor (APT)
.factorypath

# PDT-specific
.buildpath

# sbteclipse plugin
.target

# TeXlipse plugin
.texlipse


### Java template
*.class

# Mobile Tools for Java (J2ME)
Expand All @@ -11,15 +58,76 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

# maven

### NetBeans template
nbproject/private/
build/
nbbuild/
dist/
nbdist/
nbactions.xml
nb-configuration.xml
.nb-gradle/


### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion

*.iml

## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:

# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries

# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml

# Gradle:
# .idea/gradle.xml
# .idea/libraries

# Mongo Explorer plugin:
# .idea/mongoSettings.xml

## File-based project format:
*.ipr
*.iws

## Plugin-specific files:

# IntelliJ
/out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties


### Maven template
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties

# eclipse files
.settings/
.project
.classpath
bin/

# MacOS X files
.DS_Store
/bin/
24 changes: 24 additions & 0 deletions conversion/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,28 @@
<packaging>jar</packaging>
<url>http://www.qualinsight.com/</url>
<description>Cobertura coverage report conversion to SonarQube generic coverage report format.</description>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
</dependency>
<dependency>
<groupId>net.sourceforge.cobertura</groupId>
<artifactId>cobertura</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<configuration>
<sources>
<source>./src/main/resources/com/qualinsight/mojo/cobertura/transformation/sonarqube.xsd</source>
</sources>
<packageName>com.qualinsight.mojo.sonar.model</packageName>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* qualinsight-mojo-cobertura
* Copyright (c) 2015-2017, QualInsight
* http://www.qualinsight.com/
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, you can retrieve a copy
* from <http://www.gnu.org/licenses/>.
*/
package com.qualinsight.mojo.cobertura.transformation;

import org.apache.maven.plugin.MojoExecutionException;

import java.io.File;

/**
* @author pfrank
*/
public interface CoberturaToSonarQubeReportConverter {
void convertReport(final String[] sourcesPaths, final String projectPath) throws MojoExecutionException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*
* qualinsight-mojo-cobertura
* Copyright (c) 2015-2017, QualInsight
* http://www.qualinsight.com/
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, you can retrieve a copy
* from <http://www.gnu.org/licenses/>.
*/
package com.qualinsight.mojo.cobertura.transformation;

import com.qualinsight.mojo.sonar.model.CoverageType;
import com.qualinsight.mojo.sonar.model.FileType;
import com.qualinsight.mojo.sonar.model.LineToCoverType;
import com.qualinsight.mojo.sonar.model.ObjectFactory;

import net.sourceforge.cobertura.coveragedata.ClassData;
import net.sourceforge.cobertura.coveragedata.CoverageData;
import net.sourceforge.cobertura.coveragedata.LineData;
import net.sourceforge.cobertura.coveragedata.ProjectData;

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;

import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

/**
* @author pfrank
*/
public class JaxbCoberturaToSonarQubeReportConverter implements CoberturaToSonarQubeReportConverter {
public static final String SONAR_JAXB_PACKAGE = "com.qualinsight.mojo.sonar.model";
private final Log log;
private final ProjectData projectData;
private final File destinationSonarXmlFile;
private JAXBContext jaxbContext;

public JaxbCoberturaToSonarQubeReportConverter(final Log log, final ProjectData projectData, final File destinationSonarXmlFile){
if(log == null){
throw new IllegalArgumentException("Log cannot be null");
}
if(projectData == null){
throw new IllegalArgumentException("ProjectData cannot be null");
}
if(destinationSonarXmlFile == null){
throw new IllegalArgumentException("File destinationSonarXmlFile cannot be null.");
}

this.log = log;
this.projectData = projectData;
this.destinationSonarXmlFile = destinationSonarXmlFile;
try {
this.jaxbContext = JAXBContext.newInstance(SONAR_JAXB_PACKAGE);
}catch(JAXBException je){
throw new IllegalStateException(je);
}
}

@Override
public void convertReport(
final String[] sourcesPaths,
final String projectPath) throws MojoExecutionException {
try {
//There is no real lookup but the project doesn't have Tuple or KeyValuePair
final Map<String, String> sonarSourcesPathPrefixMap = new HashMap<String, String>();
for(String sourcesPath : sourcesPaths){
sonarSourcesPathPrefixMap.put(sourcesPath, sourcesPath.substring(projectPath.length()));
}

final Marshaller marshaller = jaxbContext.createMarshaller();
final ObjectFactory factory = new ObjectFactory();

final CoverageType coverageType = new CoverageType();
coverageType.setVersion(1);

@SuppressWarnings("unchecked")
final Collection<ClassData> classData = (Collection<ClassData>) projectData.getClasses();
for(ClassData classDatum : classData){
final FileType fileType = new FileType();
coverageType.getFile().add(fileType);

//Important to set this correctly for HTML reports to be able to link to source code files properly
fileType.setPath(findPrefix(sonarSourcesPathPrefixMap, classDatum.getSourceFileName()) + classDatum.getSourceFileName());

LineData lineData;
LineToCoverType lineToCoverType;
for(CoverageData line : classDatum.getLines()){
lineData = (LineData)line;
lineToCoverType = new LineToCoverType();
fileType.getLineToCover().add(lineToCoverType);

lineToCoverType.setLineNumber(lineData.getLineNumber());
lineToCoverType.setCoveredBranches(lineData.getNumberOfCoveredBranches());
lineToCoverType.setBranchesToCover(lineData.getNumberOfValidBranches());
lineToCoverType.setCovered(lineData.isCovered());
}
}

final JAXBElement<CoverageType> coverageTypeJAXBElement = factory.createCoverage(coverageType);
marshaller.marshal(coverageTypeJAXBElement, destinationSonarXmlFile);
}catch(JAXBException je){
throw new MojoExecutionException("Marshalling problem", je);
}

}

/**
* Find the correct file prefix path for the given sourceFileName, choose the first one if no file exists that matches
* the prefixes present in the project
*
* @param sonarSourcesPathPrefixMap
* @param sourceFileName
* @return
*/
String findPrefix(final Map<String, String> sonarSourcesPathPrefixMap, final String sourceFileName){
String defaultPrefix = null;
File fileToCheck;
for(Map.Entry<String, String> sonarSourcesPathPrefixEntry : sonarSourcesPathPrefixMap.entrySet()){
fileToCheck = new File(sonarSourcesPathPrefixEntry.getKey() + sourceFileName);
if(fileToCheck.exists()){
return sonarSourcesPathPrefixEntry.getValue();
}else {
//Should we even bother defaulting?
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The entire defaulting thing here can potentially be removed and just returning a default "" and just know that the file name is not going to resolve because we don't know what it is.

//Default to the first encountered prefix
if(defaultPrefix == null){
defaultPrefix = sonarSourcesPathPrefixEntry.getValue();
}
}
}

return defaultPrefix;
}
}
Loading