1/*******************************************************************************
2 * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 *    Evgeny Mandrikov - initial API and implementation
10 *
11 *******************************************************************************/
12package org.jacoco.maven;
13
14import java.io.IOException;
15import java.util.List;
16import java.util.Locale;
17
18import org.apache.maven.doxia.siterenderer.Renderer;
19import org.apache.maven.plugin.MojoExecutionException;
20import org.apache.maven.plugins.annotations.Component;
21import org.apache.maven.plugins.annotations.Parameter;
22import org.apache.maven.project.MavenProject;
23import org.apache.maven.reporting.AbstractMavenReport;
24import org.apache.maven.reporting.MavenReportException;
25import org.jacoco.report.IReportGroupVisitor;
26import org.jacoco.report.IReportVisitor;
27
28/**
29 * Base class for creating a code coverage report for tests of a single project
30 * in multiple formats (HTML, XML, and CSV).
31 */
32public abstract class AbstractReportMojo extends AbstractMavenReport {
33
34	/**
35	 * Encoding of the generated reports.
36	 */
37	@Parameter(property = "project.reporting.outputEncoding", defaultValue = "UTF-8")
38	String outputEncoding;
39
40	/**
41	 * Name of the root node HTML report pages.
42	 *
43	 * @since 0.7.7
44	 */
45	@Parameter(defaultValue = "${project.name}")
46	String title;
47
48	/**
49	 * Footer text used in HTML report pages.
50	 *
51	 * @since 0.7.7
52	 */
53	@Parameter
54	String footer;
55
56	/**
57	 * Encoding of the source files.
58	 */
59	@Parameter(property = "project.build.sourceEncoding", defaultValue = "UTF-8")
60	String sourceEncoding;
61
62	/**
63	 * A list of class files to include in the report. May use wildcard
64	 * characters (* and ?). When not specified everything will be included.
65	 */
66	@Parameter
67	List<String> includes;
68
69	/**
70	 * A list of class files to exclude from the report. May use wildcard
71	 * characters (* and ?). When not specified nothing will be excluded.
72	 */
73	@Parameter
74	List<String> excludes;
75
76	/**
77	 * Flag used to suppress execution.
78	 */
79	@Parameter(property = "jacoco.skip", defaultValue = "false")
80	boolean skip;
81
82	/**
83	 * Maven project.
84	 */
85	@Parameter(property = "project", readonly = true)
86	MavenProject project;
87
88	/**
89	 * Doxia Site Renderer.
90	 */
91	@Component
92	Renderer siteRenderer;
93
94	public String getDescription(final Locale locale) {
95		return getName(locale) + " Coverage Report.";
96	}
97
98	@Override
99	public boolean isExternalReport() {
100		return true;
101	}
102
103	@Override
104	protected MavenProject getProject() {
105		return project;
106	}
107
108	@Override
109	protected Renderer getSiteRenderer() {
110		return siteRenderer;
111	}
112
113	/**
114	 * Returns the list of class files to include in the report.
115	 *
116	 * @return class files to include, may contain wildcard characters
117	 */
118	List<String> getIncludes() {
119		return includes;
120	}
121
122	/**
123	 * Returns the list of class files to exclude from the report.
124	 *
125	 * @return class files to exclude, may contain wildcard characters
126	 */
127	List<String> getExcludes() {
128		return excludes;
129	}
130
131	@Override
132	public boolean canGenerateReport() {
133		if (skip) {
134			getLog().info(
135					"Skipping JaCoCo execution because property jacoco.skip is set.");
136			return false;
137		}
138		if (!canGenerateReportRegardingDataFiles()) {
139			getLog().info(
140					"Skipping JaCoCo execution due to missing execution data file.");
141			return false;
142		}
143		if (!canGenerateReportRegardingClassesDirectory()) {
144			getLog().info(
145					"Skipping JaCoCo execution due to missing classes directory.");
146			return false;
147		}
148		return true;
149	}
150
151	abstract boolean canGenerateReportRegardingDataFiles();
152
153	abstract boolean canGenerateReportRegardingClassesDirectory();
154
155	/**
156	 * This method is called when the report generation is invoked directly as a
157	 * standalone Mojo.
158	 */
159	@Override
160	public void execute() throws MojoExecutionException {
161		if (!canGenerateReport()) {
162			return;
163		}
164		try {
165			executeReport(Locale.getDefault());
166		} catch (final MavenReportException e) {
167			throw new MojoExecutionException("An error has occurred in "
168					+ getName(Locale.ENGLISH) + " report generation.", e);
169		}
170	}
171
172	@Override
173	protected void executeReport(final Locale locale)
174			throws MavenReportException {
175		try {
176			final ReportSupport support = new ReportSupport(getLog());
177			loadExecutionData(support);
178			addFormatters(support, locale);
179			final IReportVisitor visitor = support.initRootVisitor();
180			createReport(visitor, support);
181			visitor.visitEnd();
182		} catch (final IOException e) {
183			throw new MavenReportException("Error while creating report: "
184					+ e.getMessage(), e);
185		}
186	}
187
188	abstract void loadExecutionData(final ReportSupport support)
189			throws IOException;
190
191	abstract void addFormatters(final ReportSupport support, final Locale locale)
192			throws IOException;
193
194	abstract void createReport(final IReportGroupVisitor visitor,
195			final ReportSupport support) throws IOException;
196
197}
198