Reporter.java
/*
* Licensed to the Apache Software Foundation (ASF) under one *
* or more contributor license agreements. See the NOTICE file *
* distributed with this work for additional information *
* regarding copyright ownership. The ASF licenses this file *
* to you 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. *
*/
package org.apache.rat;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.commons.io.function.IOSupplier;
import org.apache.rat.api.RatException;
import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
import org.apache.rat.report.RatReport;
import org.apache.rat.report.claim.ClaimStatistic;
import org.apache.rat.report.xml.XmlReportFactory;
import org.apache.rat.report.xml.writer.IXmlWriter;
import org.apache.rat.report.xml.writer.XmlWriter;
import org.w3c.dom.Document;
/**
* Class that executes the report as defined in a {@link ReportConfiguration} and stores
* the result for later handling.
*/
public class Reporter {
/** Format used for listing licenses. */
private static final String LICENSE_FORMAT = "%s:\t%s%n\t\t%s%n";
/** The XML output document */
private Document document;
/** Statistics generated as the report was built */
private ClaimStatistic statistic;
/** The configuration for the report */
private final ReportConfiguration configuration;
/**
* Create the reporter.
*
* @param configuration the configuration to use.
*/
public Reporter(final ReportConfiguration configuration) {
this.configuration = configuration;
}
/**
* Executes the report and builds the output.
* This method will build the internal XML document if it does not already exist.
* If this method or either of the {@link #output()} methods have already been called this method will return
* the previous results.
* @return the claim statistics.
* @throws RatException on error.
*/
public ClaimStatistic execute() throws RatException {
if (document == null || statistic == null) {
try {
if (configuration.hasSource()) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Writer outputWriter = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
try (IXmlWriter writer = new XmlWriter(outputWriter)) {
statistic = new ClaimStatistic();
RatReport report = XmlReportFactory.createStandardReport(writer, statistic, configuration);
report.startReport();
configuration.getSources().build().run(report);
report.endReport();
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream);
}
} else {
document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
statistic = new ClaimStatistic();
}
} catch (Exception e) {
throw RatException.makeRatException(e);
}
}
return statistic;
}
/**
* Get the claim statistics from the run.
*
* @return the claim statistics.
*/
public ClaimStatistic getClaimsStatistic() {
return statistic;
}
/**
* Outputs the report using the stylesheet and output specified in the configuration.
* @return the Claim statistic from the run.
* @throws RatException on error.
*/
public ClaimStatistic output() throws RatException {
return output(configuration.getStyleSheet(), configuration.getOutput());
}
/**
* Outputs the report to the specified output using the stylesheet. It is safe to call this method more than once
* in order to generate multiple reports from the same run.
*
* @param stylesheet the style sheet to use for XSLT formatting.
* @param output the output stream to write to.
* @return the Claim statistic for the run.
* @throws RatException on error.
*/
public ClaimStatistic output(final IOSupplier<InputStream> stylesheet, final IOSupplier<OutputStream> output) throws RatException {
ClaimStatistic result = execute();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer;
try (OutputStream out = output.get();
InputStream styleIn = stylesheet.get()) {
transformer = tf.newTransformer(new StreamSource(styleIn));
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.transform(new DOMSource(document),
new StreamResult(new OutputStreamWriter(out, StandardCharsets.UTF_8)));
return result;
} catch (TransformerException | IOException e) {
throw new RatException(e);
}
}
/**
* Lists the licenses on the configured output stream.
* @param configuration The configuration for the system
* @param filter the license filter that specifies which licenses to output.
* @throws IOException if PrintWriter can not be retrieved from configuration.
*/
public static void listLicenses(final ReportConfiguration configuration, final LicenseFilter filter) throws IOException {
try (PrintWriter pw = configuration.getWriter().get()) {
pw.format("Licenses (%s):%n", filter);
configuration.getLicenses(filter)
.forEach(lic -> pw.format(LICENSE_FORMAT, lic.getLicenseFamily().getFamilyCategory(),
lic.getLicenseFamily().getFamilyName(), lic.getNote()));
pw.println();
}
}
/**
* Writes a text summary of issues with the run.
* @param appendable the appendable to write to.
* @throws IOException on error.
*/
public void writeSummary(final Appendable appendable) throws IOException {
appendable.append("RAT summary:").append(System.lineSeparator());
for (ClaimStatistic.Counter counter : ClaimStatistic.Counter.values()) {
appendable.append(" ").append(counter.displayName()).append(": ")
.append(Integer.toString(getClaimsStatistic().getCounter(counter)))
.append(System.lineSeparator());
}
}
/**
* Gets the document that was generated during execution.
* @return the document that was generated during execution.
*/
public Document getDocument() {
return document;
}
}