mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-03-28 20:02:16 +01:00
initial version of the ReportAggregationMojo
Former-commit-id: e15575413d625c6b5c5f3d73f5a739e1890eec27
This commit is contained in:
@@ -0,0 +1,340 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-maven.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.maven;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import org.apache.maven.doxia.sink.Sink;
|
||||||
|
import org.apache.maven.doxia.sink.SinkFactory;
|
||||||
|
import org.apache.maven.plugin.AbstractMojo;
|
||||||
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
|
import org.apache.maven.plugin.MojoFailureException;
|
||||||
|
import org.apache.maven.plugins.annotations.Component;
|
||||||
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
|
import org.apache.maven.project.MavenProject;
|
||||||
|
import org.apache.maven.reporting.MavenMultiPageReport;
|
||||||
|
import org.apache.maven.reporting.MavenReportException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* This is an abstract reporting mojo that enables report aggregation. Some of the code in the this class was copied
|
||||||
|
* from the CoberturaReportMojo (http://mojo.codehaus.org/cobertura-maven-plugin/, version 2.6). The authors of the
|
||||||
|
* CoberturaReportMojo were <a href="will.gwaltney@sas.com">Will Gwaltney</a> and
|
||||||
|
* <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>. There working example of how to do report aggregation was
|
||||||
|
* invaluable.</p>
|
||||||
|
* <p>
|
||||||
|
* An important point about using this abstract class is that it is intended for one to write some form of serialized
|
||||||
|
* data (via the {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#writeDataFile() }; note that the
|
||||||
|
* <code>writeDataFile()</code> function is called automatically after either {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#executeNonAggregateReport(org.apache.maven.doxia.sink.Sink,
|
||||||
|
* org.apache.maven.doxia.sink.SinkFactory, java.util.Locale)
|
||||||
|
* } or {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#executeAggregateReport(org.apache.maven.doxia.sink.Sink,
|
||||||
|
* org.apache.maven.doxia.sink.SinkFactory, java.util.Locale)
|
||||||
|
* } are called. When <code>executeAggregateReport()</code> is implemented, one can call {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#getChildDataFiles()
|
||||||
|
* } to obtain a list of the data files to aggregate.</p>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||||
|
*/
|
||||||
|
public abstract class ReportAggregationMojo extends AbstractMojo implements MavenMultiPageReport {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Maven Project Object.
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
private MavenProject project;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger field reference.
|
||||||
|
*/
|
||||||
|
private static final Logger logger = Logger.getLogger(ReportAggregationMojo.class.getName());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of Maven project of the current build
|
||||||
|
*/
|
||||||
|
@Parameter(readonly = true, required = true, property = "reactorProjects")
|
||||||
|
private List<MavenProject> reactorProjects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate aggregate reports in multi-module projects.
|
||||||
|
*/
|
||||||
|
@Parameter(property = "aggregate", defaultValue = "false")
|
||||||
|
private boolean aggregate;
|
||||||
|
|
||||||
|
private Map< MavenProject, List< MavenProject>> projectChildren;
|
||||||
|
|
||||||
|
protected void preExecute() throws MojoExecutionException, MojoFailureException {
|
||||||
|
if (this.canGenerateAggregateReport()) {
|
||||||
|
buildAggregateInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void performExecute() throws MojoExecutionException, MojoFailureException;
|
||||||
|
|
||||||
|
protected void postExecute() throws MojoExecutionException, MojoFailureException {
|
||||||
|
writeDataFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void execute() throws MojoExecutionException, MojoFailureException {
|
||||||
|
try {
|
||||||
|
preExecute();
|
||||||
|
performExecute();
|
||||||
|
} finally {
|
||||||
|
postExecute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs prior to the site report generation.
|
||||||
|
*
|
||||||
|
* @throws MavenReportException if a maven report exception occurs
|
||||||
|
*/
|
||||||
|
protected void preGenerate() throws MavenReportException {
|
||||||
|
if (canGenerateAggregateReport()) {
|
||||||
|
buildAggregateInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes after the site report has been generated.
|
||||||
|
*
|
||||||
|
* @throws MavenReportException if a maven report exception occurs
|
||||||
|
*/
|
||||||
|
protected void postGenerate() throws MavenReportException {
|
||||||
|
writeDataFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the non aggregate report.
|
||||||
|
*
|
||||||
|
* @param sink the sink to write the report to
|
||||||
|
* @param sinkFactory the sink factory
|
||||||
|
* @param locale the locale to use when generating the report
|
||||||
|
* @throws MavenReportException if a maven report exception occurs
|
||||||
|
*/
|
||||||
|
protected abstract void executeNonAggregateReport(Sink sink, SinkFactory sinkFactory, Locale locale) throws MavenReportException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the aggregate Site Report.
|
||||||
|
*
|
||||||
|
* @param sink the sink to write the report to
|
||||||
|
* @param sinkFactory the sink factory
|
||||||
|
* @param locale the locale to use when generating the report
|
||||||
|
* @throws MavenReportException if a maven report exception occurs
|
||||||
|
*/
|
||||||
|
protected abstract void executeAggregateReport(Sink sink, SinkFactory sinkFactory, Locale locale) throws MavenReportException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the Dependency-Check Site Report.
|
||||||
|
*
|
||||||
|
* @param sink the sink to write the report to
|
||||||
|
* @param locale the locale to use when generating the report
|
||||||
|
* @throws MavenReportException if a maven report exception occurs
|
||||||
|
*/
|
||||||
|
public final void generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException {
|
||||||
|
generate((Sink) sink, null, locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the Dependency-Check Site Report.
|
||||||
|
*
|
||||||
|
* @param sink the sink to write the report to
|
||||||
|
* @param sinkFactory the sink factory
|
||||||
|
* @param locale the locale to use when generating the report
|
||||||
|
* @throws MavenReportException if a maven report exception occurs
|
||||||
|
*/
|
||||||
|
public final void generate(Sink sink, SinkFactory sinkFactory, Locale locale) throws MavenReportException {
|
||||||
|
try {
|
||||||
|
preGenerate();
|
||||||
|
if (canGenerateNonAggregateReport()) {
|
||||||
|
executeNonAggregateReport(sink, sinkFactory, locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canGenerateAggregateReport()) {
|
||||||
|
executeAggregateReport(sink, sinkFactory, locale);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
postGenerate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not the mojo can generate a non-aggregate report for this project.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if a non-aggregate report can be generated, otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
protected abstract boolean canGenerateNonAggregateReport();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not we can generate any aggregate reports at this time.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if an aggregate report can be generated, otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
protected abstract boolean canGenerateAggregateReport();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the data file's names.
|
||||||
|
*
|
||||||
|
* @return the data file's name
|
||||||
|
*/
|
||||||
|
protected abstract String getDataFileName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the data file to disk in the target directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected abstract void writeDataFile();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collects the information needed for building aggregate reports.
|
||||||
|
*/
|
||||||
|
private void buildAggregateInfo() {
|
||||||
|
if (projectChildren != null) {
|
||||||
|
// already did this work
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.warning("building aggregate info");
|
||||||
|
boolean test = reactorProjects == null;
|
||||||
|
logger.warning("Reactor is " + test);
|
||||||
|
|
||||||
|
// build parent-child map
|
||||||
|
projectChildren = new HashMap<MavenProject, List<MavenProject>>();
|
||||||
|
for (MavenProject proj : reactorProjects) {
|
||||||
|
List<MavenProject> depList = projectChildren.get(proj.getParent());
|
||||||
|
if (depList == null) {
|
||||||
|
depList = new ArrayList<MavenProject>();
|
||||||
|
projectChildren.put(proj.getParent(), depList);
|
||||||
|
}
|
||||||
|
depList.add(proj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list containing all the recursive, non-pom children of the given project, never <code>null</code>.
|
||||||
|
*
|
||||||
|
* @return a list of child projects
|
||||||
|
*/
|
||||||
|
protected List<MavenProject> getAllChildren() {
|
||||||
|
return getAllChildren(project);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list containing all the recursive, non-pom children of the given project, never <code>null</code>.
|
||||||
|
*
|
||||||
|
* @param parentProject the parent project to collect the child project references
|
||||||
|
* @return a list of child projects
|
||||||
|
*/
|
||||||
|
private List<MavenProject> getAllChildren(MavenProject parentProject) {
|
||||||
|
List<MavenProject> children = projectChildren.get(parentProject);
|
||||||
|
if (children == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MavenProject> result = new ArrayList<MavenProject>();
|
||||||
|
for (MavenProject child : children) {
|
||||||
|
if (isMultiModule(child)) {
|
||||||
|
result.addAll(getAllChildren(child));
|
||||||
|
} else {
|
||||||
|
result.add(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns any existing output files from the current projects children.
|
||||||
|
*
|
||||||
|
* @param projects the list of projects to obtain the output files from
|
||||||
|
* @return a list of output files
|
||||||
|
*/
|
||||||
|
protected List<File> getChildDataFiles() {
|
||||||
|
List<MavenProject> projects = getAllChildren();
|
||||||
|
return getDataFiles(projects);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns any existing output files from the given list of projects.
|
||||||
|
*
|
||||||
|
* @param projects the list of projects to obtain the output files from
|
||||||
|
* @return a list of output files
|
||||||
|
*/
|
||||||
|
protected List<File> getDataFiles(List<MavenProject> projects) {
|
||||||
|
List<File> files = new ArrayList<File>();
|
||||||
|
for (MavenProject proj : projects) {
|
||||||
|
if (isMultiModule(proj)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
File outputFile = new File(proj.getBasedir(), getDataFileName());
|
||||||
|
if (outputFile.exists()) {
|
||||||
|
files.add(outputFile);
|
||||||
|
} else {
|
||||||
|
if (!isMultiModule(project)) {
|
||||||
|
final String msg = String.format("Unable to aggregate data for '%s' - missing data file '%s'",
|
||||||
|
proj.getName(), outputFile.getPath());
|
||||||
|
logger.warning(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if the project has pom packaging
|
||||||
|
*
|
||||||
|
* @param mavenProject Project to test
|
||||||
|
* @return True if it has a pom packaging
|
||||||
|
*/
|
||||||
|
private boolean isMultiModule(MavenProject mavenProject) {
|
||||||
|
return "pom".equals(mavenProject.getPackaging());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if the project has pom packaging
|
||||||
|
*
|
||||||
|
* @param mavenProject Project to test
|
||||||
|
* @return True if it has a pom packaging
|
||||||
|
*/
|
||||||
|
protected boolean isMultiModule() {
|
||||||
|
return "pom".equals(project.getPackaging());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the current project is the last project in a multi-module build. If the maven build is not a
|
||||||
|
* multi-module project then this will always return true.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the current project is the last project in a multi-module build; otherwise
|
||||||
|
* <code>false</code>
|
||||||
|
*/
|
||||||
|
protected boolean isLastProject() {
|
||||||
|
return project.equals(reactorProjects.get(reactorProjects.size() - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not the mojo is configured to perform report aggregation.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if report aggregation is enabled; otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
public boolean isAggregate() {
|
||||||
|
return aggregate;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user