Skip to content
This repository has been archived by the owner on Apr 22, 2022. It is now read-only.

Commit

Permalink
NetBeans Module projects support, patch provided by Graeme Ingleby. Thx!
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanlermitage committed Jan 16, 2015
1 parent fed3951 commit 88acaf9
Show file tree
Hide file tree
Showing 11 changed files with 591 additions and 366 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## JaCoCoverage Change Log

### Version 1.5.0.20150116.2200 (2015-01-16)
* GitHub #10 add NetBeans Module projects support, provided by __Graeme Ingleby__.

### Version 1.4.0.20141122.2340 (2014-11-22)
* GitHub #24 add Java Web/EE/EJB/EAR projects support.

Expand Down
74 changes: 37 additions & 37 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
## JaCoCoverage Documentation

### What Is JaCoCoverage
The JaCoCoverage Plugin is a Netbeans plugin that enhances the existing NetBeans functionality with new code coverage features. In other words, you can launch your program or test it and JaCoCoverage will provide you coverage information by highlighting your source code files and providing various types of reports (currently, textual and HTML). This way, you can easily know what piece of code has been executed or not.

### How It Works
The JaCoCoverage Plugin is based on JaCoCo: a library created by the [EclEmma team](http://www.eclemma.org/jacoco/). This library is able to generate coverage data when you launch a Java program.
More precsisely, JaCoCoverage uses the JaCoCo Java Agent to enable coverage collections (i.e. a JaCoCo Java Agent is attached to your program).
When your program terminates, JaCoCo generates coverage data and JaCoCoverage assures the coverage information integration in your NetBeans IDE.
JaCoCo and JaCoCoverage support Java 7 and are also tested with Java 6. It may work with Java 5 too. The EclEmma team is currently working on Java 8 support.

### Media
NetBeans Java editor showing highlighted code. You can see covered, partially covered and not covered code, and annotations in the left margin:

![Screenshot](http://netbeanscolors.org/files/jacococoverage_editor.png)

A context menu is enabled for supported projects. It allows you to run and test your programs with JaCoCoverage:

![Screenshot](http://netbeanscolors.org/files/jacococoverage_menu.png)

JaCoCoverage is configurable:

![Screenshot](http://netbeanscolors.org/files/jacococoverage_options.png)

A short textual coverage report:

![Screenshot](http://netbeanscolors.org/files/jacococoverage_consolereport.png)

A complete HTML coverage report:

![Screenshot](http://netbeanscolors.org/files/jacococoverage_htmlreport.png)

### Author
* Jonathan Lermitage (<jonathan.lermitage@gmail.com>)

### License
[WTFPL](http://www.wtfpl.net) License. In other words, you can do what you want: this project is entirely OpenSource, Free and Gratis.
## JaCoCoverage Documentation

### What Is JaCoCoverage
The JaCoCoverage Plugin is a Netbeans plugin that enhances the existing NetBeans functionality with new code coverage features. In other words, you can launch your program or test it and JaCoCoverage will provide you coverage information by highlighting your source code files and providing various types of reports (currently, textual and HTML). This way, you can easily know what piece of code has been executed or not.

### How It Works
The JaCoCoverage Plugin is based on JaCoCo: a library created by the [EclEmma team](http://www.eclemma.org/jacoco/). This library is able to generate coverage data when you launch a Java program.
More precsisely, JaCoCoverage uses the JaCoCo Java Agent to enable coverage collections (i.e. a JaCoCo Java Agent is attached to your program).
When your program terminates, JaCoCo generates coverage data and JaCoCoverage assures the coverage information integration in your NetBeans IDE.
JaCoCo and JaCoCoverage support Java 7 and 8 and are also tested with Java 6. It may work with Java 5 too.

### Media
NetBeans Java editor showing highlighted code. You can see covered, partially covered and not covered code, and annotations in the left margin:

![Screenshot](http://netbeanscolors.org/files/jacococoverage_editor.png)

A context menu is enabled for supported projects. It allows you to run and test your programs with JaCoCoverage:

![Screenshot](http://netbeanscolors.org/files/jacococoverage_menu.png)

JaCoCoverage is configurable:

![Screenshot](http://netbeanscolors.org/files/jacococoverage_options.png)

A short textual coverage report:

![Screenshot](http://netbeanscolors.org/files/jacococoverage_consolereport.png)

A complete HTML coverage report:

![Screenshot](http://netbeanscolors.org/files/jacococoverage_htmlreport.png)

### Author
* Jonathan Lermitage (<jonathan.lermitage@gmail.com>)

### License
[WTFPL](http://www.wtfpl.net) License. In other words, you can do what you want: this project is entirely OpenSource, Free and Gratis.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,8 @@ For details on previous and current versions, please check the [Changelog](https
### Author
* Jonathan Lermitage (<jonathan.lermitage@gmail.com>)

### Contributor
* Graeme Ingleby - provided NetBeans Module support

### License
[WTFPL](http://www.wtfpl.net) License. In other words, you can do what you want: this project is entirely OpenSource, Free and Gratis.
12 changes: 6 additions & 6 deletions tikione-jacocoexec-analyzer/manifest.mf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Manifest-Version: 1.0
AutoUpdate-Show-In-Client: false
OpenIDE-Module: fr.tikione.jacocoexec.analyzer/1
OpenIDE-Module-Localizing-Bundle: fr/tikione/jacocoexec/analyzer/Bundle.properties
OpenIDE-Module-Specification-Version: 1.3.3.20130929.1404
Manifest-Version: 1.0
AutoUpdate-Show-In-Client: false
OpenIDE-Module: fr.tikione.jacocoexec.analyzer/1
OpenIDE-Module-Localizing-Bundle: fr/tikione/jacocoexec/analyzer/Bundle.properties
OpenIDE-Module-Specification-Version: 1.5.0.20150116.2200

Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package fr.tikione.jacocoexec.analyzer;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import org.jacoco.core.analysis.Analyzer;
import org.jacoco.core.analysis.CoverageBuilder;
import org.jacoco.core.analysis.IBundleCoverage;
import org.jacoco.core.tools.ExecFileLoader;
import org.jacoco.report.DirectorySourceFileLocator;
import org.jacoco.report.FileMultiReportOutput;
import org.jacoco.report.IReportGroupVisitor;
import org.jacoco.report.IReportVisitor;
import org.jacoco.report.MultiSourceFileLocator;
import org.jacoco.report.html.HTMLFormatter;
import org.jacoco.report.xml.XMLFormatter;

/**
* @author Graeme Ingleby
*/
public class JacocoNBModuleReportGenerator {

private static final String DEF_ENCODING = "UTF-8";

private final IReportVisitor visitor;
private final IReportGroupVisitor groupVisitor;
private final File executionDataFile;
private final ExecFileLoader execFileLoader;

public JacocoNBModuleReportGenerator(File executationDataFile, File reportdir, boolean xmlReport) throws IOException {
this.executionDataFile = executationDataFile;
execFileLoader = new ExecFileLoader();
execFileLoader.load(executionDataFile);

if (xmlReport) {
XMLFormatter xmlformatter = new XMLFormatter();
xmlformatter.setOutputEncoding(DEF_ENCODING);
visitor = xmlformatter.createVisitor(new FileOutputStream(reportdir));
} else {
HTMLFormatter htmlFormater = new HTMLFormatter();
visitor = htmlFormater.createVisitor(new FileMultiReportOutput(reportdir));
}
visitor.visitInfo(execFileLoader.getSessionInfoStore().getInfos(), execFileLoader.getExecutionDataStore().getContents());
groupVisitor = visitor.visitGroup("JaCoCo Coverage Report");
}

public void processNBModule(String projectName, List<String> classDirectories, List<String> sourceDirectories) throws IOException {
CoverageBuilder coverageBuilder = new CoverageBuilder();
Analyzer analyzer = new Analyzer(execFileLoader.getExecutionDataStore(), coverageBuilder);

for (String classDirectory : classDirectories) {
analyzer.analyzeAll(new File(classDirectory));
}

IBundleCoverage bundleCoverage = coverageBuilder.getBundle(projectName);

MultiSourceFileLocator sourceLocator = new MultiSourceFileLocator(4);
for (String sourceDirectory : sourceDirectories) {
sourceLocator.add(new DirectorySourceFileLocator(new File(sourceDirectory), DEF_ENCODING, 4));
}

groupVisitor.visitBundle(bundleCoverage, sourceLocator);
}

public void end() throws IOException {
visitor.visitEnd();
}
}
2 changes: 1 addition & 1 deletion tikione-jacocoverage-plugin/manifest.mf
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ Manifest-Version: 1.0
OpenIDE-Module: fr.tikione.jacocoverage.plugin/1
OpenIDE-Module-Layer: fr/tikione/jacocoverage/plugin/layer.xml
OpenIDE-Module-Localizing-Bundle: fr/tikione/jacocoverage/plugin/Bundle.properties
OpenIDE-Module-Specification-Version: 1.4.0.20141122.2340
OpenIDE-Module-Specification-Version: 1.5.0.20150116.2200
OpenIDE-Module-Needs: org.openide.filesystems.FileUtil.toFileObject
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
* <br/>See <a href="http://wiki.netbeans.org/DevFaqAddGlobalContext">DevFaqAddGlobalContext</a> for global context and project tweaks.
*
* @author Jonathan Lermitage
* @author Graeme Ingleby
*/
@SuppressWarnings("CloneableImplementsClone")
public abstract class ActionJacocoOnAntTaskJ2SE
Expand All @@ -56,6 +57,8 @@ public abstract class ActionJacocoOnAntTaskJ2SE

private static final Logger LOGGER = Logger.getLogger(ActionJacocoOnAntTaskJ2SE.class.getName());

private static final String DEFAULT_EXCLUDES = "com.sun.*:org.apache.*:org.netbeans.*:junit.*:sun.*:org.openide.*:org.junit.*";

/** The Ant task to launch. */
private final String antTask;

Expand Down Expand Up @@ -134,9 +137,17 @@ private void runJacocoJavaagent(final Project project)
}
}

antTaskJavaagentParam = "\"" + NBUtils.getJacocoAgentJar().getAbsolutePath()
+ "\"=includes=*:" + NBUtils.getProjectJavaPackagesAsStr(project, prjProps, ":", ".*")
+ ",destfile=\"" + binreport.getAbsolutePath() + "\"" + exclude.toString();
// GWI patch: If NetBeans Module Project - use different JavaAgent settings
final boolean isNBModule = Utils.isProjectSupported(NBUtils.getSelectedProject(), NBProjectTypeEnum.NBMODULE);
if (isNBModule) {
String excludes = prjProps.getProperty("jacoco.excludes");
antTaskJavaagentParam = "\"" + NBUtils.getJacocoAgentJar().getAbsolutePath()
+ "\"=destfile=\"" + binreport.getAbsolutePath() + "\"" + (excludes == null ? "" : ",excludes=" + excludes);
} else {
antTaskJavaagentParam = "\"" + NBUtils.getJacocoAgentJar().getAbsolutePath()
+ "\"=includes=*:" + NBUtils.getProjectJavaPackagesAsStr(project, prjProps, ":", ".*")
+ ",destfile=\"" + binreport.getAbsolutePath() + "\"" + exclude.toString();
}

FileObject scriptToExecute = project.getProjectDirectory().getFileObject("build", "xml");
if (scriptToExecute == null) { // Fix for GitHub #16.
Expand All @@ -157,7 +168,12 @@ private void runJacocoJavaagent(final Project project)
String prjJvmArgs;
final boolean isJ2EE = Utils.isProjectSupported(NBUtils.getSelectedProject(),
NBProjectTypeEnum.J2EE, NBProjectTypeEnum.J2EE_EAR, NBProjectTypeEnum.J2EE_EJB, NBProjectTypeEnum.J2EE_WEB);
if (isJ2EE) {

// GWI patch: If NetBeans Module Project - use different JavaAgent settings
if (isNBModule) {
prjJvmArgs = Utils.getProperty(prjProps, "test.run.args");
targetProps.put("test.run.args", prjJvmArgs + " -javaagent:" + antTaskJavaagentParam);
} else if (isJ2EE) {
prjJvmArgs = Utils.getProperty(prjProps, "runmain.jvmargs");
targetProps.put("runmain.jvmargs", prjJvmArgs + " -javaagent:" + antTaskJavaagentParam);
} else {
Expand Down Expand Up @@ -194,7 +210,14 @@ public void run() {
classDir = new File(prjDir + Utils.getProperty(prjProps, "build.classes.dir") + File.separator);
}
File srcDir = new File(prjDir + Utils.getProperty(prjProps, "src.dir") + File.separator);
JaCoCoReportAnalyzer.toXmlReport(binreport, xmlreport, classDir, srcDir);

// GWI patch: If NBModule create a different XML Report
if (isNBModule) {
NBJaCoCoExtension.toXmlReport(binreport, xmlreport, project);
} else {
JaCoCoReportAnalyzer.toXmlReport(binreport, xmlreport, classDir, srcDir);
}

final Map<String, JavaClass> coverageData = JaCoCoXmlReportParser.getCoverageData(xmlreport);
new File(prjDir + Globals.JACOCOVERAGE_DATA_DIR).mkdirs();

Expand All @@ -211,7 +234,15 @@ public void run() {
}
if (enblHtmlReport) {
reportdir.mkdirs();
String report = JaCoCoReportAnalyzer.toHtmlReport(binreport, reportdir, classDir, srcDir, prjname);

// GWI patch: If NetBeans Module Project - use different HTML Report
String report;
if (isNBModule) {
report = NBJaCoCoExtension.toHTMLReport(binreport, reportdir, project);
} else {
report = JaCoCoReportAnalyzer.toHtmlReport(binreport, reportdir, classDir, srcDir, prjname);
}

if (openHtmlReport) {
try {
HtmlBrowser.URLDisplayer.getDefault().showURL(Utilities.toURI(new File(report)).toURL());
Expand All @@ -221,8 +252,22 @@ public void run() {
}
}
if (enblHighlight) {
for (final JavaClass jclass : coverageData.values()) {
NBUtils.colorDoc(project, jclass, cfg.isEnblHighlightingExtended(), srcDir);

// GWI patch: GWI-Modified: New Coloring Code
if (isNBModule) {
for (final JavaClass jclass : coverageData.values()) {
try {
NBUtils.colorDoc(project, jclass, cfg.isEnblHighlightingExtended(), srcDir);
} catch (Throwable e) {
Logger.getGlobal().log(Level.SEVERE,
"Failed to color: {0} {1}",
new Object[]{jclass.getClassName(), srcDir});
}
}
} else {
for (final JavaClass jclass : coverageData.values()) {
NBUtils.colorDoc(project, jclass, cfg.isEnblHighlightingExtended(), srcDir);
}
}
}
keepJaCoCoWorkfiles(binreport, xmlreport, prjDir, cfg.getJaCoCoWorkfilesRule());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package fr.tikione.jacocoverage.plugin.action;

import fr.tikione.jacocoexec.analyzer.JacocoNBModuleReportGenerator;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.Sources;
import org.netbeans.spi.project.SubprojectProvider;
import org.openide.util.Exceptions;

/**
* @author Graeme Ingleby
*/
public class NBJaCoCoExtension {

private JacocoNBModuleReportGenerator reportGenerator;

public static String toHTMLReport(File binreport, File reportdir, Project project) {
return (new NBJaCoCoExtension()).myReportGeneration(binreport, reportdir, project);
}

public static void toXmlReport(File binreport, File reportfile, Project project) {
(new NBJaCoCoExtension()).myXmlReportGeneration(binreport, reportfile, project);
}

/**
* XML Generation.
*
* @param jacocoExecFile
* @param reportdir
* @param project
*/
public void myXmlReportGeneration(File jacocoExecFile, File reportdir, Project project) {
try {
reportGenerator = new JacocoNBModuleReportGenerator(jacocoExecFile, reportdir, true);
processProject(project);
reportGenerator.end();
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}

/**
* HTML Generation.
*
* @param jacocoExecFile
* @param reportdir
* @param project
* @return
*/
public String myReportGeneration(File jacocoExecFile, File reportdir, Project project) {
try {
reportGenerator = new JacocoNBModuleReportGenerator(jacocoExecFile, reportdir, false);
processProject(project);
reportGenerator.end();
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
return new File(reportdir, "index.html").getAbsolutePath();
}

public void processProject(Project project) throws FileNotFoundException, IOException {
List<String> moduleClassDirectories = new ArrayList<>(8);
List<String> moduleSourceDirectories = new ArrayList<>(8);

String prjDir = project.getProjectDirectory().getPath();

File classDir = new File(prjDir + "/build/classes");
if (classDir.exists()) {
moduleClassDirectories.add(classDir.getPath());
}

Sources source = ProjectUtils.getSources(project);
SourceGroup[] groups = source.getSourceGroups("java");
for (SourceGroup group : groups) {
moduleSourceDirectories.add(group.getRootFolder().getPath());
}
File genDir = new File(prjDir + "/build/classes-generated");
if (genDir.exists()) {
moduleSourceDirectories.add(genDir.getPath());
}

reportGenerator.processNBModule(project.getProjectDirectory().getName(), moduleClassDirectories, moduleSourceDirectories);
processSubprojects(project);
}

public void processSubprojects(Project project) throws IOException {
SubprojectProvider subs = project.getLookup().lookup(SubprojectProvider.class);
if (subs != null) {
Set<? extends Project> subProjects = subs.getSubprojects();
for (Project p : subProjects) {
processProject(p);
}
}
}
}
Loading

0 comments on commit 88acaf9

Please sign in to comment.