From 90dd8c5b8b3897c6af236a14030c1f33d0ba29de Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Mon, 6 Jul 2026 13:53:24 +0100 Subject: [PATCH 01/17] initial code --- .../resources/ReportTest/RAT_14/verify.groovy | 3 +- .../src/main/java/org/apache/rat/Report.java | 10 +- .../org/apache/rat/ReportConfiguration.java | 154 +++++++++- .../main/java/org/apache/rat/Reporter.java | 233 +++++++++++---- .../apache/rat/commandline/StyleSheets.java | 8 +- .../config/exclusion/ExclusionProcessor.java | 100 +++++++ .../configuration/XMLConfigurationReader.java | 4 +- .../rat/report/claim/ClaimStatistic.java | 124 +++++++- .../apache/rat/ReporterOptionsProvider.java | 269 +++++++++--------- .../org/apache/rat/ReporterOptionsTest.java | 12 +- .../java/org/apache/rat/ReporterTest.java | 22 +- .../java/org/apache/rat/mp/RatCheckMojo.java | 29 +- .../java/org/apache/rat/mp/RatReportMojo.java | 5 +- .../java/org/apache/rat/anttasks/Report.java | 8 +- 14 files changed, 738 insertions(+), 243 deletions(-) diff --git a/apache-rat-core/src/it/resources/ReportTest/RAT_14/verify.groovy b/apache-rat-core/src/it/resources/ReportTest/RAT_14/verify.groovy index 226394df0..0a46a22f9 100644 --- a/apache-rat-core/src/it/resources/ReportTest/RAT_14/verify.groovy +++ b/apache-rat-core/src/it/resources/ReportTest/RAT_14/verify.groovy @@ -68,7 +68,8 @@ ReportConfiguration configuration = OptionCollection.parseCommands(src, myArgs, assertNotNull(configuration) configuration.validate(DefaultLog.getInstance().&error) Reporter reporter = new Reporter(configuration) -ClaimStatistic statistic = reporter.execute() +Reporter.Output output = reporter.execute() +ClaimStatistic statistic = output.getStatistic() assertEquals(3, statistic.getCounter(ClaimStatistic.Counter.APPROVED)) assertEquals(2, statistic.getCounter(ClaimStatistic.Counter.ARCHIVES)) diff --git a/apache-rat-core/src/main/java/org/apache/rat/Report.java b/apache-rat-core/src/main/java/org/apache/rat/Report.java index 5f5f4cb35..3c366fab7 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/Report.java +++ b/apache-rat-core/src/main/java/org/apache/rat/Report.java @@ -51,15 +51,15 @@ public static void main(final String[] args) throws Exception { ReportConfiguration configuration = OptionCollection.parseCommands(new File("."), args, Report::printUsage); if (configuration != null) { configuration.validate(DefaultLog.getInstance()::error); - Reporter reporter = new Reporter(configuration); - reporter.output(); - reporter.writeSummary(DefaultLog.getInstance().asWriter()); + Reporter.Output output = new Reporter(configuration).execute(); + output.format(configuration); + output.writeSummary(DefaultLog.getInstance().asWriter()); if (configuration.getClaimValidator().hasErrors()) { - configuration.getClaimValidator().logIssues(reporter.getClaimsStatistic()); + configuration.getClaimValidator().logIssues(output.getStatistic()); throw new RatDocumentAnalysisException(format("Issues with %s", String.join(", ", - configuration.getClaimValidator().listIssues(reporter.getClaimsStatistic())))); + configuration.getClaimValidator().listIssues(output.getStatistic())))); } } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java index 579095824..8f5d6fb17 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java +++ b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java @@ -35,19 +35,25 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.SortedSet; import java.util.function.Consumer; +import javax.xml.parsers.DocumentBuilder; + import org.apache.commons.collections4.set.UnmodifiableSortedSet; import org.apache.commons.io.function.IOSupplier; import org.apache.commons.io.output.CloseShieldOutputStream; +import org.apache.commons.lang3.StringUtils; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.api.RatException; import org.apache.rat.commandline.StyleSheets; import org.apache.rat.config.AddLicenseHeaders; import org.apache.rat.config.exclusion.ExclusionProcessor; import org.apache.rat.config.exclusion.StandardCollection; import org.apache.rat.config.results.ClaimValidator; +import org.apache.rat.configuration.XMLConfigurationReader; import org.apache.rat.configuration.builders.AnyBuilder; import org.apache.rat.document.DocumentName; import org.apache.rat.document.DocumentNameMatcher; @@ -56,12 +62,19 @@ import org.apache.rat.license.ILicenseFamily; import org.apache.rat.license.LicenseSetFactory; import org.apache.rat.license.LicenseSetFactory.LicenseFilter; +import org.apache.rat.report.RatReport; import org.apache.rat.report.Reportable; +import org.apache.rat.report.claim.ClaimStatistic; +import org.apache.rat.report.xml.writer.XmlWriter; import org.apache.rat.utils.DefaultLog; import org.apache.rat.utils.Log.Level; import org.apache.rat.utils.ReportingSet; +import org.apache.rat.utils.StandardXmlFactory; import org.apache.rat.walker.FileListWalker; import org.apache.rat.walker.ReportableListWalker; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + /** * A configuration object is used by the front end to invoke the @@ -183,6 +196,10 @@ public ReportConfiguration() { reportables = new ArrayList<>(); } + public Serde serde() { + return new Serde(); + } + /** * Report the excluded files to the appendable object. * @param appendable the appendable object to write to. @@ -252,7 +269,7 @@ public IHeaderMatcher getGeneratedMatcher() { /** * Retrieves the archive processing type. - * @return the archive processing type. + * @return The archive processing type. */ public Processing getArchiveProcessing() { return archiveProcessing == null ? Defaults.ARCHIVE_PROCESSING : archiveProcessing; @@ -268,7 +285,7 @@ public void setArchiveProcessing(final Processing archiveProcessing) { /** * Retrieves the archive processing type. - * @return the archive processing type. + * @return The archive processing type. */ public Processing getStandardProcessing() { return standardProcessing == null ? Defaults.STANDARD_PROCESSING : standardProcessing; @@ -285,7 +302,7 @@ public void setStandardProcessing(final Processing standardProcessing) { /** * Set the log level for reporting collisions in the set of license families. *

NOTE: should be set before licenses or license families are added.

- * @param level the log level to use. + * @param level The log level to use. */ public void logFamilyCollisions(final Level level) { licenseSetFactory.logFamilyCollisions(level); @@ -293,7 +310,7 @@ public void logFamilyCollisions(final Level level) { /** * Sets the reporting option for duplicate license families. - * @param state the ReportingSet.Option to use for reporting. + * @param state The ReportingSet.Option to use for reporting. */ public void familyDuplicateOption(final ReportingSet.Options state) { licenseSetFactory.familyDuplicateOption(state); @@ -301,7 +318,7 @@ public void familyDuplicateOption(final ReportingSet.Options state) { /** * Sets the log level for reporting license collisions. - * @param level the log level. + * @param level The log level. */ public void logLicenseCollisions(final Level level) { licenseSetFactory.logLicenseCollisions(level); @@ -907,4 +924,131 @@ static IODescriptor input(final File file) { return new IODescriptor<>(file.toString(), () -> new FileInputStream(file)); } } + + /** + * Serializes the ReportConfiguration into an XML document that can be deserialzed by the Serde. + * Deserialized ReportConfigurations can not be executed as the reportable objects a simply named placeholders + * and do not have access to the original object. + */ + public class Serde { + /** + * Writes the configuration as an XML document to the appendable. + * + * @param appendable the Appendable to write to. + * @throws IOException on error. + */ + public void serialize(final Appendable appendable) throws IOException { + try (XmlWriter writer = new XmlWriter(appendable)) { + writer.startElement("ReportConfiguration") + .attribute("addingLicenses", Boolean.toString(addingLicenses)) + .attribute("addingLicensesForced", Boolean.toString(addingLicensesForced)) + .attribute("listFamilies", listFamilies.name()) + .attribute("listLicenses", listLicenses.name()) + .attribute("dryRun", Boolean.toString(dryRun)) + .attribute("archiveProcessing", getArchiveProcessing().name()) + .attribute("standardProcessing", getStandardProcessing().name()) + .attribute("stylesheet", styleSheet.name()) + .attribute("output", out.name()); + if (StringUtils.isNotEmpty(copyrightMessage)) { + writer.startElement("copyrightMessage").content(copyrightMessage).closeElement(); + } + writer.startElement("sources"); + for (File f : sources) { + writer.startElement("source").attribute("name", f.toString()).closeElement(); + } + writer.closeElement("sources").startElement("reportables"); + for (Reportable reportable : reportables) { + writer.startElement("reportable") + .attribute("baseName", reportable.name().getBaseName()) + .attribute("name", reportable.name().toString()) + .attribute("class", reportable.getClass().getName()).closeElement(); + } + writer.closeElement(); + + exclusionProcessor.serde().serialize(writer); + + writer.startElement("claimValidator"); + for (ClaimStatistic.Counter counter : ClaimStatistic.Counter.values()) { + writer.startElement("claimCounter") + .attribute("name", counter.name()).attribute("min", Integer.toString(claimValidator.getMin(counter))) + .attribute("max", Integer.toString(claimValidator.getMax(counter))).closeElement(); + } + writer.closeElement(); + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new IOException(e); + } + } + + public void deserialize(final IOSupplier inputStreamSupplier, final DocumentName workingDirectory) throws IOException { + DocumentBuilder builder = StandardXmlFactory.documentBuilder(); + org.w3c.dom.Document document; + try (InputStream stream = inputStreamSupplier.get()) { + document = builder.parse(stream); + } catch (SAXException e) { + throw new IOException("Unable to read input", e); + } + Node node = document.getDocumentElement(); + if (!node.getNodeName().equals("ReportConfiguration")) { + throw new IOException("Invalid ReportConfiguration"); + } + Map attributes = XMLConfigurationReader.attributes(node); + addingLicenses = Boolean.parseBoolean(attributes.get("addingLicenses")); + addingLicensesForced = Boolean.parseBoolean(attributes.get("addingLicensesForced")); + listFamilies = LicenseFilter.valueOf(attributes.get("listFamilies")); + listLicenses = LicenseFilter.valueOf(attributes.get("listLicenses")); + dryRun = Boolean.parseBoolean(attributes.get("dryRun")); + archiveProcessing = Processing.valueOf(attributes.get("archiveProcessing")); + standardProcessing = Processing.valueOf(attributes.get("standardProcessing")); + String styleName = attributes.get("stylesheet"); + if (styleName != null) { + styleSheet = StyleSheets.getStyleSheet(styleName); + } + String outputName = attributes.get("output"); + if (outputName != null) { + if (outputName.equals(ReportConfiguration.SYSTEM_OUT.name())) { + out = ReportConfiguration.SYSTEM_OUT; + } else { + out = IODescriptor.output(outputName, workingDirectory); + } + } + + XMLConfigurationReader.nodeListConsumer(document.getElementsByTagName("copyrightMessage"), + lNode -> setCopyrightMessage(lNode.getTextContent())); + + XMLConfigurationReader.nodeListConsumer(document.getElementsByTagName("source"), lNode -> { + Map nAttributes = XMLConfigurationReader.attributes(lNode); + addSource(new File(nAttributes.get("name"))); + }); + + // Deserialize the reportables. + XMLConfigurationReader.nodeListConsumer(document.getElementsByTagName("reportable"), lNode -> { + Map nAttributes = XMLConfigurationReader.attributes(lNode); + DocumentName documentName = DocumentName.builder().setBaseName(nAttributes.get("baseName")) + .setName(nAttributes.get("name")).build(); + addSource(new DeserializedReportable(documentName)); + }); + + exclusionProcessor.serde().deserialize(document.getElementsByTagName("ExclusionProcessor").item(0)); + + XMLConfigurationReader.nodeListConsumer(document.getElementsByTagName("claimCounter"), lNode -> { + Map nAttributes = XMLConfigurationReader.attributes(lNode); + ClaimStatistic.Counter counter = ClaimStatistic.Counter.valueOf(nAttributes.get("name")); + claimValidator.setMin(counter, Integer.parseInt(nAttributes.get("min"))); + claimValidator.setMax(counter, Integer.parseInt(nAttributes.get("max"))); + }); + } + } + + /** + * A record that identifies a deserialized reportable. Deserialized reportables are not executable. + * @param name the name of the reportable. + */ + private record DeserializedReportable(DocumentName name) implements Reportable { + @Override + public void run(final RatReport report) throws RatException { + throw new RatException("Attempt to run a deserialized reportable"); + } + } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/Reporter.java b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java index 5cf396d9c..4ccd3c722 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/Reporter.java +++ b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java @@ -18,22 +18,24 @@ */ package org.apache.rat; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; 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.io.StringReader; import java.nio.charset.StandardCharsets; +import javax.xml.parsers.DocumentBuilder; import javax.xml.transform.TransformerException; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.io.function.IOSupplier; import org.apache.rat.api.RatException; +import org.apache.rat.document.DocumentName; import org.apache.rat.license.LicenseSetFactory.LicenseFilter; import org.apache.rat.report.RatReport; import org.apache.rat.report.claim.ClaimStatistic; @@ -41,6 +43,8 @@ import org.apache.rat.report.xml.writer.XmlWriter; import org.apache.rat.utils.StandardXmlFactory; import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; /** * Class that executes the report as defined in a {@link ReportConfiguration} and stores @@ -48,18 +52,21 @@ */ public class Reporter { - /** Format used for listing licenses. */ + /** + * 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 */ + /** + * The configuration for the report + */ private final ReportConfiguration configuration; + /** + * The output from the execution. + */ + private Output output; + /** * Create the reporter. * @@ -71,72 +78,135 @@ public Reporter(final ReportConfiguration 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. + * + * @return the Output object. * @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 (XmlWriter 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 = StandardXmlFactory.documentBuilder().parse(inputStream); - } else { - document = StandardXmlFactory.documentBuilder().newDocument(); - statistic = new ClaimStatistic(); + public Output execute() throws RatException { + try { + Output.Builder builder = Output.builder().configuration(configuration); + if (configuration.hasSource()) { + StringBuilder sb = new StringBuilder(); + try (XmlWriter writer = new XmlWriter(sb)) { + writer.startDocument(); + ClaimStatistic statistic = new ClaimStatistic(); + builder.statistic(statistic); + RatReport report = XmlReportFactory.createStandardReport(writer, statistic, configuration); + report.startReport(); + configuration.getSources().build().run(report); + report.endReport(); + InputSource inputSource = new InputSource(new StringReader(sb.toString())); + builder.document(StandardXmlFactory.documentBuilder().parse(inputSource)); } - } catch (Exception e) { - throw RatException.makeRatException(e); + } else { + builder.document = StandardXmlFactory.documentBuilder().newDocument(); + builder.statistic(new ClaimStatistic()); } + this.output = builder.build(); + return output; + } catch (Exception e) { + throw RatException.makeRatException(e); } - return statistic; } + /** + * Gets the output from the last {@link #execute} call or {@code null} if {@link #execute} has not been called. + * @return the output + */ + public Output getOutput() { + return output; + } + + /** + * 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(); + } + } + + /** + * The output from a report run. + */ + public static final class Output { + /** The XML output document */ + private final Document document; + /** + * The claim statics from the execution that generated the document. + * May be empty if the Document was read from disk. + */ + private final ClaimStatistic statistic; + /** + * The configuration that generated the document + */ + private final ReportConfiguration configuration; + + /** + * Create an output with statistics. + * @param builder the Builder + */ + private Output(final Builder builder) { + this.document = builder.document; + this.statistic = builder.statistic == null ? new ClaimStatistic() : builder.statistic; + this.configuration = builder.configuration == null ? new ReportConfiguration() : builder.configuration; + } + + public static Builder builder() { + return new Builder(); + } + + /** + * Gets the document that was generated during execution. + * @return the document that was generated during execution. + */ + public Document getDocument() { + return document; + } + /** * Get the claim statistics from the run. * * @return the claim statistics. */ - public ClaimStatistic getClaimsStatistic() { + public ClaimStatistic getStatistic() { return statistic; } + public ReportConfiguration getConfiguration() { + return configuration; + } /** - * Outputs the report using the stylesheet and output specified in the configuration. - * @return the Claim statistic from the run. + * Formats the report to the output and using the stylesheet found in the report configuration. + * + * @param config s RAT report configuration. * @throws RatException on error. */ - public ClaimStatistic output() throws RatException { - return output(configuration.getStyleSheet(), configuration.getOutput()); + public void format(final ReportConfiguration config) throws RatException { + format(config.getStyleSheet(), config.getOutput()); } /** - * Outputs the report to the specified output using the stylesheet. It is safe to call this method more than once + * Formats 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 stylesheet, final IOSupplier output) throws RatException { - ClaimStatistic result = execute(); + public void format(final IOSupplier stylesheet, final IOSupplier output) throws RatException { + try (OutputStream out = output.get(); InputStream styleIn = stylesheet.get()) { StandardXmlFactory.createTransformer(styleIn).transform(new DOMSource(document), new StreamResult(new OutputStreamWriter(out, StandardCharsets.UTF_8))); - return result; } catch (TransformerException | IOException e) { throw new RatException(e); } @@ -167,16 +237,77 @@ 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(Integer.toString(statistic.getCounter(counter))) .append(System.lineSeparator()); } } + public static final class Builder { + /** The document that was generated */ + private Document document; + /** + * The claim statistic from the execution that generated the document. + * May be empty if the Document was read from disk. + */ + private ClaimStatistic statistic; /** - * Gets the document that was generated during execution. - * @return the document that was generated during execution. + * The configuration that generated the document */ - public Document getDocument() { - return document; + private ReportConfiguration configuration; + + public Builder document(final Document document) { + this.document = document; + return this; + } + + public Builder document(final String fileName, final DocumentName workingDirectory) { + DocumentBuilder builder = StandardXmlFactory.documentBuilder(); + File inputFile = workingDirectory.resolve(fileName).asFile(); + try (InputStream inputStream = new FileInputStream(inputFile)) { + this.document = builder.parse(inputStream); + } catch (SAXException | IOException e) { + throw new ConfigurationException("Unable to read file: " + inputFile, e); + } + return this; + } + + public Output build() { + return new Output(this); + } + + public Builder statistic(final ClaimStatistic statistic) { + this.statistic = statistic; + return this; + } + + public Builder statistic(final String fileName, final DocumentName workingDirectory) { + File sourceFile = workingDirectory.resolve(fileName).asFile(); + try { + ClaimStatistic newStatistic = new ClaimStatistic(); + newStatistic.serde().deserialize(() -> new FileInputStream(sourceFile)); + this.statistic = newStatistic; + return this; + } catch (IOException e) { + throw new ConfigurationException("Unable to read file: " + sourceFile, e); + } + } + + public Builder configuration(final ReportConfiguration configuration) { + this.configuration = configuration; + return this; + } + + public Builder configuration(final String fileName, final DocumentName workingDirectory) { + File configurationFile = workingDirectory.resolve(fileName).asFile(); + try { + ReportConfiguration config = new ReportConfiguration(); + config.serde().deserialize(() -> new FileInputStream(configurationFile), workingDirectory); + this.configuration = config; + return this; + } catch (IOException e) { + throw new ConfigurationException("Unable to read file: " + configurationFile, e); + } + } + } } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/commandline/StyleSheets.java b/apache-rat-core/src/main/java/org/apache/rat/commandline/StyleSheets.java index b56e0dde7..ea0c11133 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/commandline/StyleSheets.java +++ b/apache-rat-core/src/main/java/org/apache/rat/commandline/StyleSheets.java @@ -71,8 +71,8 @@ public enum StyleSheets { } /** - * Gets the IOSupplier for a style sheet. - * @return an IOSupplier for the sheet. + * Gets the IODescriptor for a style sheet. + * @return an IODescriptor for the sheet. */ public ReportConfiguration.IODescriptor getStyleSheet() { URL url = StyleSheets.class.getClassLoader().getResource(format("org/apache/rat/%s.xsl", name)); @@ -81,9 +81,9 @@ public ReportConfiguration.IODescriptor getStyleSheet() { } /** - * Gets the IOSupplier for a style sheet. + * Gets the IODescriptor for a style sheet. * @param name the short name for or the path to a style sheet. - * @return the IOSupplier for the style sheet. + * @return the IODescriptor for the style sheet. */ public static ReportConfiguration.IODescriptor getStyleSheet(final String name) { URL url = StyleSheets.class.getClassLoader().getResource(format("org/apache/rat/%s.xsl", name)); diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java index d7b5862be..2a6085845 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java @@ -22,15 +22,22 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.TreeSet; +import java.util.function.Predicate; import java.util.stream.Collectors; +import org.apache.commons.lang3.NotImplementedException; +import org.apache.rat.configuration.XMLConfigurationReader; import org.apache.rat.document.DocumentName; import org.apache.rat.document.DocumentNameMatcher; +import org.apache.rat.report.xml.writer.XmlWriter; import org.apache.rat.utils.DefaultLog; import org.apache.rat.utils.ExtendedIterator; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; import static java.lang.String.format; @@ -74,6 +81,10 @@ public ExclusionProcessor() { excludedCollections = new HashSet<>(); } + public Serde serde() { + return new Serde(); + } + /** Reset the {@link #lastMatcher} and {@link #lastMatcherBaseDir} to start again */ private void resetLastMatcher() { lastMatcher = null; @@ -336,5 +347,94 @@ private void extractPaths(final MatcherSet.Builder matcherBuilder) { } } } + /** + * Serializes and deserializes the ExclusionProcessor to XML document + */ + public class Serde { + /** The pattern attribute name */ + private static final String PATTERN = "pattern"; + /** THe name attribute name */ + private static final String NAME = "name"; + + /** + * Serialize the ExclusionProcessor to XML writer. + * @param writer the writer to serialize to. + * @throws IOException on Error + */ + public void serialize(final XmlWriter writer) throws IOException { + writer.startElement("ExclusionProcessor"); + + for (String pattern : excludedPatterns) { + writer.startElement("excludedPattern").attribute(PATTERN, pattern).closeElement(); + } + for (StandardCollection obj : excludedCollections) { + writer.startElement("excludedCollection").attribute(NAME, obj.name()).closeElement(); + } + for (DocumentNameMatcher obj : excludedPaths) { + writer.startElement("excludedPath").attribute(NAME, obj.toString()).closeElement(); + } + + for (String pattern : includedPatterns) { + writer.startElement("includedPattern").attribute(PATTERN, pattern).closeElement(); + } + for (StandardCollection obj : includedCollections) { + writer.startElement("includedCollection").attribute(NAME, obj.name()).closeElement(); + } + for (DocumentNameMatcher obj : includedPaths) { + writer.startElement("includedPath").attribute(NAME, obj.toString()).closeElement(); + } + + for (StandardCollection obj : fileProcessors) { + writer.startElement("fileProcessor").attribute(NAME, obj.name()).closeElement(); + } + writer.closeElement(); + } + + /** + * Deserialize from XML Document node to ExclusionProcessor + * @param xmlNode the node to deserialize from. + */ + public void deserialize(final Node xmlNode) { + final NodeList children = xmlNode.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + Map attributes = XMLConfigurationReader.attributes(child); + StandardCollection collection; + switch (child.getNodeName()) { + case "excludedPattern": + excludedPatterns.add(attributes.get(PATTERN)); + break; + case "excludedCollection": + collection = StandardCollection.valueOf(attributes.get(NAME)); + excludedCollections.add(collection); + break; + case "excludedPath": + excludedPaths.add(new DocumentNameMatcher(attributes.get(NAME), + (Predicate) x -> { + throw new NotImplementedException("Deserialized ExclusionProcessor can not evaluate paths"); + })); + break; + case "includedPattern": + includedPatterns.add(attributes.get(PATTERN)); + break; + case "includedCollection": + collection = StandardCollection.valueOf(attributes.get(NAME)); + includedCollections.add(collection); + break; + case "includedPath": + includedPaths.add(new DocumentNameMatcher(attributes.get(NAME), + (Predicate) x -> { + throw new NotImplementedException("Deserialized ExclusionProcessor can not evaluate paths"); + })); + break; + case "fileProcessor": + fileProcessors.add(StandardCollection.valueOf(attributes.get(NAME))); + break; + default: + throw new NotImplementedException(String.format("Deserialization for `%s` is not implemented", child.getNodeName())); + } + } + } + } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/XMLConfigurationReader.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/XMLConfigurationReader.java index ac11bdd5a..04b9fbe45 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/XMLConfigurationReader.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/XMLConfigurationReader.java @@ -173,7 +173,7 @@ public void read(final URI... uris) { * @param list the NodeList to process * @param consumer the consumer to apply to each node in the list. */ - private void nodeListConsumer(final NodeList list, final Consumer consumer) { + public static void nodeListConsumer(final NodeList list, final Consumer consumer) { for (int i = 0; i < list.getLength(); i++) { consumer.accept(list.item(i)); } @@ -199,7 +199,7 @@ public void add(final Document newDoc) { * @param node The node to process * @return the map of attributes on the node. */ - private Map attributes(final Node node) { + public static Map attributes(final Node node) { NamedNodeMap nnm = node.getAttributes(); Map result = new HashMap<>(); for (int i = 0; i < nnm.getLength(); i++) { diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java index 62572916c..38b538eec 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java @@ -19,14 +19,24 @@ package org.apache.rat.report.claim; +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import javax.xml.parsers.DocumentBuilder; + +import org.apache.commons.io.function.IOSupplier; import org.apache.commons.lang3.StringUtils; import org.apache.rat.api.Document; +import org.apache.rat.configuration.XMLConfigurationReader; +import org.apache.rat.report.xml.writer.XmlWriter; +import org.apache.rat.utils.StandardXmlFactory; +import org.xml.sax.SAXException; /** * This class provides a numerical overview about @@ -100,7 +110,7 @@ public int getDefaultMinValue() { * @return displayName of the counter, capitalized and without underscores. */ public String displayName() { - return StringUtils.capitalize(name().replaceAll("_", " ").toLowerCase(Locale.ROOT)); + return StringUtils.capitalize(name().replace("_", " ").toLowerCase(Locale.ROOT)); } } @@ -113,6 +123,9 @@ public String displayName() { /** Map of counter type to value */ private final ConcurrentHashMap counterMap = new ConcurrentHashMap<>(); + public Serde serde() { + return new Serde(); + } /** * Converts null counter to 0. * @@ -141,6 +154,15 @@ public void incCounter(final Counter counter, final int value) { counterMap.compute(counter, (k, v) -> v == null ? new IntCounter().increment(value) : v.increment(value)); } + /** + * Increments the counts for the counter. + * @param counter the counter to increment. + * @param value the value to increment the counter by. + */ + public void setCounter(final Counter counter, final int value) { + counterMap.put(counter, new IntCounter().increment(value)); + } + /** * Gets the counts for the Document.Type. * @param documentType the Document.Type to get the counter for. @@ -288,5 +310,105 @@ public IntCounter increment(final int count) { public int value() { return value; } + + @Override + public String toString() { + return String.valueOf(value); + } + } + + /** + * Serialze and deserialze the claim Statistic. + */ + public class Serde { + /** The count attribute string */ + private static final String COUNT = "count"; + /** the name attribute string */ + private static final String NAME = "name"; + + /** + * Serializes the claim statistic into an appendable. + * @param appendable the appendable to write to + * @throws IOException on error. + */ + public void serialize(final Appendable appendable) throws IOException { + try (XmlWriter writer = new XmlWriter(appendable)) { + writer.startDocument().startElement("ClaimStatistic") + .startElement("licenseNameMap"); + for (Map.Entry entry : licenseNameMap.entrySet()) { + if (entry.getValue().value > 0) { + writer.startElement("licenseName") + .attribute(COUNT, entry.getValue().toString()) + .attribute(NAME, entry.getKey()).closeElement(); + } + } + writer.closeElement() + .startElement("licenseFamilyCategoryMap"); + for (Map.Entry entry : licenseFamilyCategoryMap.entrySet()) { + if (entry.getValue().value > 0) { + writer.startElement("familyCategory") + .attribute(COUNT, entry.getValue().toString()) + .attribute(NAME, entry.getKey()).closeElement(); + } + } + writer.closeElement() + .startElement("documentTypeMap"); + for (Map.Entry entry : documentTypeMap.entrySet()) { + if (entry.getValue().value > 0) { + writer.startElement("documentType") + .attribute(COUNT, entry.getValue().toString()) + .attribute(NAME, entry.getKey().name()).closeElement(); + } + } + writer.closeElement() + .startElement("counterMap"); + for (Map.Entry entry : counterMap.entrySet()) { + if (entry.getValue().value > 0) { + writer.startElement("counter") + .attribute(COUNT, entry.getValue().toString()) + .attribute(NAME, entry.getKey().name()).closeElement(); + } + } + writer.closeElement(); + } + } + + /** + * Deserializes a ClaimStatistic from an input stream. + * @param inputStreamSupplier the supplier of the input stream to deserialize from. + * @throws IOException on error. + */ + public void deserialize(final IOSupplier inputStreamSupplier) throws IOException { + DocumentBuilder builder = StandardXmlFactory.documentBuilder(); + org.w3c.dom.Document document; + try (InputStream stream = inputStreamSupplier.get()) { + document = builder.parse(stream); + + } catch (SAXException e) { + throw new IOException("Unable to read input", e); + } + + XMLConfigurationReader.nodeListConsumer(document.getElementsByTagName("licenseName"), node -> { + Map attributes = XMLConfigurationReader.attributes(node); + incLicenseNameCount(attributes.get(NAME), Integer.parseInt(attributes.get(COUNT))); + }); + + XMLConfigurationReader.nodeListConsumer(document.getElementsByTagName("familyCategory"), node -> { + Map attributes = XMLConfigurationReader.attributes(node); + incLicenseCategoryCount(attributes.get(NAME), Integer.parseInt(attributes.get(COUNT))); + }); + + XMLConfigurationReader.nodeListConsumer(document.getElementsByTagName("documentType"), node -> { + Map attributes = XMLConfigurationReader.attributes(node); + Document.Type type = Document.Type.valueOf(attributes.get(NAME)); + incCounter(type, Integer.parseInt(attributes.get(COUNT))); + }); + + XMLConfigurationReader.nodeListConsumer(document.getElementsByTagName("counter"), node -> { + Map attributes = XMLConfigurationReader.attributes(node); + Counter type = Counter.valueOf(attributes.get(NAME)); + setCounter(type, Integer.parseInt(attributes.get(COUNT))); + }); + } } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsProvider.java b/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsProvider.java index bd9e4fd63..30905e90d 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsProvider.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsProvider.java @@ -65,6 +65,7 @@ import static org.apache.rat.commandline.Arg.HELP_LICENSES; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Fail.fail; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @@ -133,9 +134,9 @@ private void validateNoArgSetup() throws IOException, RatException { try { ReportConfiguration config = generateConfig(Collections.emptyList()); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); + Reporter.Output output = reporter.execute(); ClaimValidator validator = config.getClaimValidator(); - assertThat(validator.listIssues(claimStatistic)).isEmpty(); + assertThat(validator.listIssues(output.getStatistic())).isEmpty(); } finally { DefaultLog.setInstance(null); } @@ -160,8 +161,8 @@ private void editLicenseTest(final Option option) { FileUtils.delete(resultFile); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); - assertThat(claimStatistic).isNotNull(); + Reporter.Output output = reporter.execute(); + assertThat(output.getStatistic()).isNotNull(); String contents = String.join("\n", IOUtils.readLines(new FileReader(testFile))); assertThat(contents).isEqualTo("class NoLicense {}"); assertThat(resultFile).exists(); @@ -214,9 +215,9 @@ private void execLicensesDeniedTest(final Option option, final String[] args) { ReportConfiguration config = generateConfig(ImmutablePair.of(option, args)); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); + Reporter.Output output = reporter.execute(); ClaimValidator validator = config.getClaimValidator(); - assertThat(validator.listIssues(claimStatistic)).containsExactly("UNAPPROVED"); + assertThat(validator.listIssues(output.getStatistic())).containsExactly("UNAPPROVED"); }); } @@ -243,14 +244,8 @@ private void noDefaultsTest(final Option option) { ReportConfiguration config = generateConfig(ImmutablePair.of(option, null)); Reporter reporter = new Reporter(config); - try { - reporter.execute(); - fail("Should have thrown exception"); - } catch (RatException e) { - ClaimStatistic claimStatistic = reporter.getClaimsStatistic(); - ClaimValidator validator = config.getClaimValidator(); - assertThat(validator.listIssues(claimStatistic)).containsExactlyInAnyOrder("DOCUMENT_TYPES", "LICENSE_CATEGORIES", "LICENSE_NAMES", "STANDARDS"); - } + assertThatThrownBy(reporter::execute) + .isInstanceOf(RatException.class); }); } @@ -276,16 +271,16 @@ protected void counterMaxTest() { ReportConfiguration config = generateConfig(Collections.emptyList()); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); + Reporter.Output output = reporter.execute(); ClaimValidator validator = config.getClaimValidator(); - assertThat(validator.listIssues(claimStatistic)).containsExactly("UNAPPROVED"); + assertThat(validator.listIssues(output.getStatistic())).containsExactly("UNAPPROVED"); arg[0] = "Unapproved:1"; config = generateConfig(ImmutablePair.of(option, arg)); reporter = new Reporter(config); - claimStatistic = reporter.execute(); + output = reporter.execute(); validator = config.getClaimValidator(); - assertThat(validator.listIssues(claimStatistic)).isEmpty(); + assertThat(validator.listIssues(output.getStatistic())).isEmpty(); }); } @@ -301,16 +296,16 @@ protected void counterMinTest() { ReportConfiguration config = generateConfig(Collections.emptyList()); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); + Reporter.Output output = reporter.execute(); ClaimValidator validator = config.getClaimValidator(); - assertThat(validator.listIssues(claimStatistic)).containsExactly("UNAPPROVED"); + assertThat(validator.listIssues(output.getStatistic())).containsExactly("UNAPPROVED"); arg[0] = "Unapproved:1"; config = generateConfig(ImmutablePair.of(option, arg)); reporter = new Reporter(config); - claimStatistic = reporter.execute(); + output = reporter.execute(); validator = config.getClaimValidator(); - assertThat(validator.listIssues(claimStatistic)).isEmpty(); + assertThat(validator.listIssues(output.getStatistic())).isEmpty(); }); } @@ -329,16 +324,16 @@ private void execExcludeTest(final Option option, final String[] args, final boo ReportConfiguration config = generateConfig(Collections.emptyList()); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(5); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(addIgnored ? 1 : 0); + Reporter.Output output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(5); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(addIgnored ? 1 : 0); // filter out source config = generateConfig(ImmutablePair.of(option, args)); reporter = new Reporter(config); - claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(addIgnored ? 4 : 3); + output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(addIgnored ? 4 : 3); }); } @@ -381,16 +376,16 @@ protected void inputExcludeSizeTest() { ReportConfiguration config = generateConfig(Collections.emptyList()); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(3); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(0); + Reporter.Output output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(3); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(0); // filter out source config = generateConfig(ImmutablePair.of(option, args)); reporter = new Reporter(config); - claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(1); + output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(1); }); } @@ -415,15 +410,15 @@ protected void inputExcludeStdTest() { ReportConfiguration config = generateConfig(Collections.emptyList()); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(5); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(4); + Reporter.Output output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(5); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(4); config = generateConfig(ImmutablePair.of(option, args)); reporter = new Reporter(config); - claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(4); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(5); + output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(4); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(5); }); } @@ -471,16 +466,16 @@ protected void inputExcludeParsedScmTest() { ReportConfiguration config = generateConfig(Collections.emptyList()); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(11); + Reporter.Output output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(11); // .gitignore is ignored by default as it is hidden but not counted - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(0); config = generateConfig(ImmutablePair.of(option, args)); reporter = new Reporter(config); - claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(3); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(8); + output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(3); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(8); }); } @@ -499,25 +494,25 @@ private void execIncludeTest(final Option option, final String[] args, boolean a ReportConfiguration config = generateConfig(Collections.emptyList()); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(4); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(addIgnored ? 1 : 0); + Reporter.Output output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(4); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(addIgnored ? 1 : 0); // verify exclude removes most files. config = generateConfig(ImmutablePair.of(excludeOption, EXCLUDE_ARGS)); reporter = new Reporter(config); - claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); + output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); // .gitignore is ignored by default as it is hidden but not counted - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(addIgnored ? 4 : 3); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(addIgnored ? 4 : 3); // verify include pust them back config = generateConfig(ImmutablePair.of(option, args), ImmutablePair.of(excludeOption, EXCLUDE_ARGS)); reporter = new Reporter(config); - claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(3); + output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(3); // .gitignore is ignored by default as it is hidden but not counted - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(addIgnored ? 2 : 1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(addIgnored ? 2 : 1); }); } @@ -569,15 +564,15 @@ protected void inputIncludeStdTest() { ReportConfiguration config = generateConfig(Collections.singletonList(excludes)); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(3); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(5); + Reporter.Output output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(3); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(5); config = generateConfig(excludes, ImmutablePair.of(option, args)); reporter = new Reporter(config); - claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(7); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(1); + output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(7); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(1); }); } @@ -594,15 +589,15 @@ protected void inputSourceTest() { ReportConfiguration config = generateConfig(); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(3); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(0); + Reporter.Output output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(3); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(0); config = generateConfig(ImmutablePair.of(option, new String[]{inputFile.getAbsolutePath()})); reporter = new Reporter(config); - claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(0); + output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(0); }); } @@ -624,18 +619,18 @@ private void execLicenseFamiliesApprovedTest(final Option option, final String[] ReportConfiguration config = addCatzLicense(generateConfig()); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); + Reporter.Output output = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(0); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); config = addCatzLicense(generateConfig(arg1)); reporter = new Reporter(config); - claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); + output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); }); } @@ -664,17 +659,17 @@ private void execLicenseFamiliesDeniedTest(final Option option, final String[] a ReportConfiguration config = generateConfig(); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); + Reporter.Output output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); config = generateConfig(arg1); reporter = new Reporter(config); - claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(0); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); + output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); }); } @@ -704,26 +699,26 @@ private void configTest(final Option option) { ReportConfiguration config = generateConfig(); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); + Reporter.Output output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); config = generateConfig(arg1); reporter = new Reporter(config); - claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(2); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); + output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(2); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); Pair arg2 = ImmutablePair.of(Arg.CONFIGURATION_NO_DEFAULTS.find("configuration-no-defaults"), null); config = generateConfig(arg1, arg2); reporter = new Reporter(config); - claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); + output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); }); } @@ -749,17 +744,17 @@ protected void execLicensesApprovedTest(final Option option, String[] args) { ReportConfiguration config = generateConfig(); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); + Reporter.Output output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); config = generateConfig(arg1); reporter = new Reporter(config); - claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(2); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); + output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(2); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); }); } @@ -793,17 +788,17 @@ protected void scanHiddenDirectoriesTest() { ReportConfiguration config = generateConfig(); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); + Reporter.Output output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); config = generateConfig(arg1); reporter = new Reporter(config); - claimStatistic = reporter.execute(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); + output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); }); } @@ -817,11 +812,11 @@ private void outTest(final Option option) { ReportConfiguration config = generateConfig(ImmutablePair.of(option, args)); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.output(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); - + Reporter.Output output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); + output.format(config); String actualText = TextUtils.readFile(outFile); TextUtils.assertContainsExactly(1, "Apache License 2.0: 1 ", actualText); TextUtils.assertContainsExactly(1, "STANDARD: 1 ", actualText); @@ -857,11 +852,11 @@ private void styleSheetTest(final Option option) { args[0] = sheet.arg(); ReportConfiguration config = generateConfig(ImmutablePair.of(option, args)); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.output(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(0); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); - + Reporter.Output output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); + output.format(config); String actualText = baos.toString(StandardCharsets.UTF_8); switch (sheet) { case MISSING_HEADERS: @@ -887,11 +882,11 @@ private void styleSheetTest(final Option option) { args[0] = file.getAbsolutePath(); ReportConfiguration config = generateConfig(ImmutablePair.of(option, args)); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.output(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(0); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); - + Reporter.Output output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); + output.format(config); String actualText = baos.toString(StandardCharsets.UTF_8); TextUtils.assertContainsExactly(1, "Hello world", actualText); } catch (IOException | RatException e) { @@ -929,11 +924,11 @@ protected void xmlTest() { ReportConfiguration config = generateConfig(ImmutablePair.of(option, null)); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.output(); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(0); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); - + Reporter.Output output = reporter.execute(); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); + output.format(config); String actualText = baos.toString(StandardCharsets.UTF_8); TextUtils.assertContainsExactly(1, "", actualText); @@ -960,12 +955,12 @@ protected void logLevelTest() { ReportConfiguration config = generateConfig(); Reporter reporter = new Reporter(config); - reporter.output(); + reporter.execute(); TextUtils.assertNotContains("DEBUG", baos.toString(StandardCharsets.UTF_8)); config = generateConfig(ImmutablePair.of(option, new String[]{"debug"})); reporter = new Reporter(config); - reporter.output(); + reporter.execute(); TextUtils.assertContains("DEBUG", baos.toString(StandardCharsets.UTF_8)); } catch (IOException | RatException e) { fail(e.getMessage(), e); @@ -989,7 +984,7 @@ private void listLicenses(final Option option) { args[0] = filter.name(); ReportConfiguration config = generateConfig(outputFile, stylesheet, ImmutablePair.of(option, args)); Reporter reporter = new Reporter(config); - reporter.output(); + reporter.execute().format(config); Document document = XmlUtils.toDom(new FileInputStream(outFile)); switch (filter) { case ALL: @@ -1035,7 +1030,7 @@ private void listFamilies(final Option option) { args[0] = filter.name(); ReportConfiguration config = generateConfig(outputFile, stylesheet, ImmutablePair.of(option, args)); Reporter reporter = new Reporter(config); - reporter.output(); + reporter.execute().format(config); Document document = XmlUtils.toDom(Files.newInputStream(outFile.toPath())); switch (filter) { case ALL: @@ -1088,7 +1083,7 @@ private void archiveTest(final Option option) { args[0] = proc.name(); ReportConfiguration config = generateConfig(outputFile, stylesheet, ImmutablePair.of(option, args)); Reporter reporter = new Reporter(config); - reporter.output(); + reporter.execute().format(config); Document document = XmlUtils.toDom(Files.newInputStream(outFile.toPath())); XmlUtils.assertIsPresent(proc.name(), document, xPath, "/rat-report/resource[@name='/dummy.jar']"); @@ -1138,7 +1133,7 @@ private void standardTest(final Option option) { args[0] = proc.name(); ReportConfiguration config = generateConfig(outputFile, stylesheet, ImmutablePair.of(option, args)); Reporter reporter = new Reporter(config); - reporter.output(); + reporter.execute().format(config); Document document = XmlUtils.toDom(Files.newInputStream(outFile.toPath())); XmlUtils.assertIsPresent(proc.name(), document, xPath, testDoc); diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsTest.java index ccb82f3c6..d98a46468 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsTest.java @@ -78,14 +78,14 @@ void testRat362() { FileUtils.writeFile(testDir, "foo.md"); ReportConfiguration config = OptionCollection.parseCommands(testDir, args, o -> fail("Help called"), true); Reporter reporter = new Reporter(config); - ClaimStatistic claimStatistic = reporter.execute(); - XmlUtils.printDocument(System.out, reporter.getDocument()); + Reporter.Output output = reporter.execute(); + XmlUtils.printDocument(System.out, output.getDocument()); XPath xpath = XPathFactory.newInstance().newXPath(); - XmlUtils.assertIsPresent(reporter.getDocument(), xpath, "/rat-report/resource[@name='/foo.md']"); - XmlUtils.assertAttributes(reporter.getDocument(), xpath, "/rat-report/resource[@name='/foo.md']", + XmlUtils.assertIsPresent(output.getDocument(), xpath, "/rat-report/resource[@name='/foo.md']"); + XmlUtils.assertAttributes(output.getDocument(), xpath, "/rat-report/resource[@name='/foo.md']", XmlUtils.mapOf("type", "IGNORED")); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(0); - assertThat(claimStatistic.getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(2); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(2); } catch (IOException | RatException | XPathExpressionException e) { fail(e); } diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java index d9f11b7ad..198d9d9b3 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java @@ -87,7 +87,7 @@ void testExecute() throws RatException, ParseException { CommandLine cl = new DefaultParser().parse(OptionCollection.buildOptions(), new String[]{"--output-style", "xml", "--output-file", output.getPath(), basedir}); ArgumentContext ctxt = new ArgumentContext(new File("."), cl); ReportConfiguration config = OptionCollection.createConfiguration(ctxt); - ClaimStatistic statistic = new Reporter(config).execute(); + ClaimStatistic statistic = new Reporter(config).execute().getStatistic(); assertThat(statistic.getCounter(Type.ARCHIVE)).isEqualTo(1); assertThat(statistic.getCounter(Type.BINARY)).isEqualTo(2); @@ -142,7 +142,7 @@ void testOutputOption() throws Exception { ArgumentContext ctxt = new ArgumentContext(new File("."), commandLine); ReportConfiguration config = OptionCollection.createConfiguration(ctxt); - new Reporter(config).output(); + new Reporter(config).execute().format(config); assertThat(output.exists()).isTrue(); String content = FileUtils.readFileToString(output, StandardCharsets.UTF_8); TextUtils.assertPatternInTarget("^! Unapproved:\\s*2 ", content); @@ -161,7 +161,7 @@ void testDefaultOutput() throws Exception { ArgumentContext ctxt = new ArgumentContext(new File("."), commandLine); ReportConfiguration config = OptionCollection.createConfiguration(ctxt); - new Reporter(config).output(); + new Reporter(config).execute().format(config); } finally { System.setOut(origin); } @@ -215,7 +215,7 @@ void testXMLOutput() throws Exception { ArgumentContext ctxt = new ArgumentContext(tempDirectory, commandLine); ReportConfiguration config = OptionCollection.createConfiguration(ctxt); - new Reporter(config).output(); + new Reporter(config).execute().format(config); assertThat(output).exists(); Document doc = XmlUtils.toDom(java.nio.file.Files.newInputStream(output.toPath())); @@ -410,7 +410,7 @@ void xmlReportTest() throws Exception { ReportConfiguration configuration = initializeConfiguration(); configuration.setStyleSheet(StyleSheets.XML.getStyleSheet()); configuration.setOut(new ReportConfiguration.IODescriptor("xmlReportTest", () -> out)); - new Reporter(configuration).output(); + new Reporter(configuration).execute().format(configuration); Document doc = XmlUtils.toDom(new ByteArrayInputStream(out.toByteArray())); XPath xPath = XPathFactory.newInstance().newXPath(); @@ -458,7 +458,7 @@ void plainReportTest() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); ReportConfiguration configuration = initializeConfiguration(); configuration.setOut(new ReportConfiguration.IODescriptor("plainReportTest", () -> out)); - new Reporter(configuration).output(); + new Reporter(configuration).execute().format(configuration); out.flush(); String document = out.toString(); @@ -475,7 +475,7 @@ void unapprovedLicensesReportTest() throws Exception { ReportConfiguration configuration = initializeConfiguration(); configuration.setOut(new ReportConfiguration.IODescriptor("unapprovedLicensesReportTest", () -> out)); configuration.setStyleSheet(this.getClass().getResource("/org/apache/rat/unapproved-licenses.xsl")); - new Reporter(configuration).output(); + new Reporter(configuration).execute().format(configuration); out.flush(); String document = out.toString(); @@ -503,17 +503,17 @@ void listLicensesReportTest() throws Exception { void counterMaxTest() throws Exception { ReportConfiguration config = initializeConfiguration(); Reporter reporter = new Reporter(config); - reporter.output(); + Reporter.Output output = reporter.execute(); assertThat(config.getClaimValidator().hasErrors()).isTrue(); - assertThat(config.getClaimValidator().isValid(ClaimStatistic.Counter.UNAPPROVED, reporter.getClaimsStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED))) + assertThat(config.getClaimValidator().isValid(ClaimStatistic.Counter.UNAPPROVED, output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED))) .isFalse(); config = initializeConfiguration(); config.getClaimValidator().setMax(ClaimStatistic.Counter.UNAPPROVED, 2); reporter = new Reporter(config); - reporter.output(); + output = reporter.execute(); assertThat(config.getClaimValidator().hasErrors()).isFalse(); - assertThat(config.getClaimValidator().isValid(ClaimStatistic.Counter.UNAPPROVED, reporter.getClaimsStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED))) + assertThat(config.getClaimValidator().isValid(ClaimStatistic.Counter.UNAPPROVED, output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED))) .isTrue(); } diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatCheckMojo.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatCheckMojo.java index 5a55a0612..d400b53cc 100644 --- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatCheckMojo.java +++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatCheckMojo.java @@ -36,6 +36,7 @@ import org.apache.rat.commandline.Arg; import org.apache.rat.commandline.StyleSheets; import org.apache.rat.config.exclusion.StandardCollection; +import org.apache.rat.config.results.ClaimValidator; import org.apache.rat.license.LicenseSetFactory.LicenseFilter; import org.apache.rat.report.claim.ClaimStatistic; import org.apache.rat.utils.DefaultLog; @@ -158,9 +159,6 @@ public void setCopyrightMessage(final String copyrightMessage) { @Parameter(property = "rat.consoleOutput", defaultValue = "true") private boolean consoleOutput; - /** The reporter that this mojo uses */ - private Reporter reporter; - @Override protected ReportConfiguration getConfiguration() throws MojoExecutionException { ReportConfiguration result = super.getConfiguration(); @@ -208,12 +206,12 @@ public void execute() throws MojoExecutionException, MojoFailureException { config.reportExclusions(logWriter); } try { - this.reporter = new Reporter(config); - reporter.output(); + Reporter.Output output = new Reporter(config).execute(); if (verbose) { - reporter.writeSummary(logWriter); + output.writeSummary(logWriter); } - check(config); + output.format(config); + check(output); } catch (MojoFailureException e) { throw e; } catch (Exception e) { @@ -224,17 +222,18 @@ public void execute() throws MojoExecutionException, MojoFailureException { } } - protected void check(final ReportConfiguration config) throws MojoFailureException { - ClaimStatistic statistics = reporter.getClaimsStatistic(); + protected void check(final Reporter.Output output) throws MojoFailureException { + ClaimStatistic statistics = output.getStatistic(); + ClaimValidator validator = output.getConfiguration().getClaimValidator(); try { - reporter.writeSummary(DefaultLog.getInstance().asWriter(Log.Level.DEBUG)); - if (config.getClaimValidator().hasErrors()) { - config.getClaimValidator().logIssues(statistics); + output.writeSummary(DefaultLog.getInstance().asWriter(Log.Level.DEBUG)); + if (validator.hasErrors()) { + validator.logIssues(statistics); if (consoleOutput && - !config.getClaimValidator().isValid(ClaimStatistic.Counter.UNAPPROVED, statistics.getCounter(ClaimStatistic.Counter.UNAPPROVED))) { + !validator.isValid(ClaimStatistic.Counter.UNAPPROVED, statistics.getCounter(ClaimStatistic.Counter.UNAPPROVED))) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - reporter.output(StyleSheets.UNAPPROVED_LICENSES.getStyleSheet().ioSupplier(), () -> baos); + output.format(StyleSheets.UNAPPROVED_LICENSES.getStyleSheet().ioSupplier(), () -> baos); getLog().warn(baos.toString(StandardCharsets.UTF_8)); } catch (RuntimeException rte) { throw rte; @@ -244,7 +243,7 @@ protected void check(final ReportConfiguration config) throws MojoFailureExcepti } String msg = format("Counter(s) %s exceeded minimum or maximum values. See RAT report in: '%s'.", - String.join(", ", config.getClaimValidator().listIssues(statistics)), + String.join(", ", validator.listIssues(statistics)), getRatTxtFile()); if (!ignoreErrors) { diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java index 99ac97f58..afeee56b2 100644 --- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java +++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java @@ -443,10 +443,11 @@ protected void executeReport(final Locale locale) throws MavenReportException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); config.setOut(new ReportConfiguration.IODescriptor("RAT output", () -> baos)); Reporter reporter = new Reporter(config); - reporter.output(); + Reporter.Output output = reporter.execute(); if (verbose) { - reporter.writeSummary(logWriter); + output.writeSummary(logWriter); } + output.format(config); sink.text(baos.toString(StandardCharsets.UTF_8.name())); } catch (IOException | MojoExecutionException | RatException e) { throw new MavenReportException(e.getMessage(), e); diff --git a/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Report.java b/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Report.java index cd91a8ecd..3249452e3 100644 --- a/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Report.java +++ b/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Report.java @@ -443,9 +443,11 @@ public ReportConfiguration getConfiguration() { @Override public void execute() { try { - Reporter r = new Reporter(validate(getConfiguration())); - r.output(StyleSheets.PLAIN.getStyleSheet().ioSupplier(), () -> CloseShieldOutputStream.wrap(System.out)); - r.output(); + ReportConfiguration config = validate(getConfiguration()); + Reporter r = new Reporter(config); + Reporter.Output output = r.execute(); + output.format(StyleSheets.PLAIN.getStyleSheet().ioSupplier(), () -> CloseShieldOutputStream.wrap(System.out)); + output.format(config); } catch (BuildException e) { throw e; } catch (Exception ioex) { From a99e12a69633345e149bb4df57eb2e3a316d5fa2 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Mon, 6 Jul 2026 15:18:57 +0100 Subject: [PATCH 02/17] added tests --- apache-rat-core/pom.xml | 5 + .../org/apache/rat/ReportConfiguration.java | 26 ++- .../main/java/org/apache/rat/Reporter.java | 125 ++++++----- .../config/exclusion/ExclusionProcessor.java | 54 ++++- .../apache/rat/utils/StandardXmlFactory.java | 33 +++ .../test/java/org/apache/rat/OutputTest.java | 160 ++++++++++++++ .../apache/rat/ReportConfigurationTest.java | 85 +++++++- .../java/org/apache/rat/ReporterTest.java | 24 +-- .../exclusion/ExclusionProcessorTest.java | 200 ++++++++++++++++++ .../rat/report/claim/ClaimStatisticTest.java | 148 +++++++++++++ pom.xml | 13 ++ 11 files changed, 794 insertions(+), 79 deletions(-) create mode 100644 apache-rat-core/src/test/java/org/apache/rat/OutputTest.java create mode 100644 apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java diff --git a/apache-rat-core/pom.xml b/apache-rat-core/pom.xml index 21f0c583c..061670044 100644 --- a/apache-rat-core/pom.xml +++ b/apache-rat-core/pom.xml @@ -263,5 +263,10 @@ jimfs test + + org.xmlunit + xmlunit-assertj3 + test + diff --git a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java index 8f5d6fb17..e434065f3 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java +++ b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java @@ -39,6 +39,7 @@ import java.util.Objects; import java.util.SortedSet; import java.util.function.Consumer; +import java.util.stream.Stream; import javax.xml.parsers.DocumentBuilder; @@ -153,7 +154,7 @@ public String desc() { private final List reportables; /** - * A predicate to test if a path should be included in the processing. + * The exclusion processor that determines if a file is included or excluded. */ private final ExclusionProcessor exclusionProcessor; @@ -259,6 +260,16 @@ public ReportableListWalker.Builder getSources() { return builder; } + // for testing access + Iterable sources() { + return sources; + } + + // for testing access + Stream reportables() { + return reportables.stream().map(Reportable::name); + } + /** * Gets the matcher that matches generated text. * @return the matcher that matches generated text. @@ -441,6 +452,14 @@ public void addIncludedFilter(final FileFilter fileFilter) { exclusionProcessor.addIncludedMatcher(new DocumentNameMatcher(fileFilter)); } + /** + * Includes files that match a DocumentNameMatcher. + * @param matcher the DocumentNameMatcher to match. + */ + public void addIncludedMatcher(final DocumentNameMatcher matcher) { + exclusionProcessor.addIncludedMatcher(matcher); + } + /** * Add file patterns that are to be included. These patterns override any exclusion of * the same files. @@ -459,6 +478,11 @@ public DocumentNameMatcher getDocumentExcluder(final DocumentName baseDir) { return exclusionProcessor.getNameMatcher(baseDir); } + // visible for testing. + ExclusionProcessor getExclusionProcessor() { + return exclusionProcessor; + } + /** * Gets the IOSupplier with the style sheet. * @return the Supplier of the InputStream that is the XSLT style sheet to style diff --git a/apache-rat-core/src/main/java/org/apache/rat/Reporter.java b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java index 4ccd3c722..9b037efe9 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/Reporter.java +++ b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java @@ -111,6 +111,7 @@ public Output execute() throws RatException { /** * Gets the output from the last {@link #execute} call or {@code null} if {@link #execute} has not been called. + * * @return the output */ public Output getOutput() { @@ -119,8 +120,9 @@ public Output getOutput() { /** * 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. + * @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 { @@ -137,7 +139,9 @@ public static void listLicenses(final ReportConfiguration configuration, final L * The output from a report run. */ public static final class Output { - /** The XML output document */ + /** + * The XML output document + */ private final Document document; /** * The claim statics from the execution that generated the document. @@ -151,6 +155,7 @@ public static final class Output { /** * Create an output with statistics. + * * @param builder the Builder */ private Output(final Builder builder) { @@ -161,98 +166,104 @@ private Output(final Builder builder) { public static Builder builder() { return new Builder(); - } + } /** * Gets the document that was generated during execution. + * * @return the document that was generated during execution. */ public Document getDocument() { return document; } - /** - * Get the claim statistics from the run. - * - * @return the claim statistics. - */ - public ClaimStatistic getStatistic() { - return statistic; - } + /** + * Get the claim statistics from the run. + * + * @return the claim statistics. + */ + public ClaimStatistic getStatistic() { + return statistic; + } public ReportConfiguration getConfiguration() { return configuration; } - /** + + /** * Formats the report to the output and using the stylesheet found in the report configuration. * * @param config s RAT report configuration. - * @throws RatException on error. - */ + * @throws RatException on error. + */ public void format(final ReportConfiguration config) throws RatException { format(config.getStyleSheet(), config.getOutput()); - } + } - /** + /** * Formats 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. - * @throws RatException on error. - */ + * 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. + * @throws RatException on error. + */ public void format(final IOSupplier stylesheet, final IOSupplier output) throws RatException { - try (OutputStream out = output.get(); - InputStream styleIn = stylesheet.get()) { - StandardXmlFactory.createTransformer(styleIn).transform(new DOMSource(document), - new StreamResult(new OutputStreamWriter(out, StandardCharsets.UTF_8))); - } catch (TransformerException | IOException e) { - throw new RatException(e); + try (OutputStream out = output.get(); + InputStream styleIn = stylesheet.get()) { + StandardXmlFactory.createTransformer(styleIn).transform(new DOMSource(document), + new StreamResult(new OutputStreamWriter(out, StandardCharsets.UTF_8))); + } 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(); + /** + * 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(": ") + /** + * 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(statistic.getCounter(counter))) - .append(System.lineSeparator()); + .append(System.lineSeparator()); + } } - } public static final class Builder { - /** The document that was generated */ + /** + * The document that was generated + */ private Document document; /** * The claim statistic from the execution that generated the document. * May be empty if the Document was read from disk. */ private ClaimStatistic statistic; - /** + /** * The configuration that generated the document - */ + */ private ReportConfiguration configuration; public Builder document(final Document document) { diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java index 2a6085845..b8ade20af 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -85,7 +86,47 @@ public Serde serde() { return new Serde(); } - /** Reset the {@link #lastMatcher} and {@link #lastMatcherBaseDir} to start again */ + /* the folloing set of methods are here for testing purposes */ + + Set getExcludedPatterns() { + return new HashSet(excludedPatterns); + } + + Collection getExcludedPaths() { + return new ArrayList(excludedPaths); + } + + Set getIncludedPatterns() { + return new HashSet<>(includedPatterns); + } + + Collection getIncludedPaths() { + return new ArrayList(includedPaths); + } + + Collection getFileProcessors() { + return new HashSet<>(fileProcessors); + } + + Set getIncludedCollections() { + return new HashSet(includedCollections); + } + + Set getExcludedCollections() { + return new HashSet(excludedCollections); + } + + DocumentNameMatcher getLastMatcher() { + return lastMatcher; + } + + DocumentName getLastMatcherBaseDir() { + return lastMatcherBaseDir; + } + + /** + * Reset the {@link #lastMatcher} and {@link #lastMatcherBaseDir} to start again + */ private void resetLastMatcher() { lastMatcher = null; lastMatcherBaseDir = null; @@ -97,9 +138,11 @@ private void resetLastMatcher() { * @return this */ public ExclusionProcessor addIncludedPatterns(final Iterable patterns) { + if (patterns != null) { DefaultLog.getInstance().debug(format("Including patterns: %s", String.join(", ", patterns))); patterns.forEach(includedPatterns::add); resetLastMatcher(); + } return this; } @@ -150,9 +193,11 @@ public ExclusionProcessor addIncludedCollection(final StandardCollection collect * @return this */ public ExclusionProcessor addExcludedPatterns(final Iterable patterns) { + if (patterns != null) { DefaultLog.getInstance().debug(format("Excluding patterns: %s", String.join(", ", patterns))); patterns.forEach(excludedPatterns::add); resetLastMatcher(); + } return this; } @@ -188,8 +233,10 @@ public void reportExclusions(final Appendable appendable) throws IOException { for (DocumentNameMatcher nameMatcher : excludedPaths) { appendable.append(format("Excluding %s.%n", nameMatcher.toString())); } + for (DocumentNameMatcher nameMatcher : includedPaths) { + appendable.append(format("Including %s.%n", nameMatcher.toString())); + } } - /** * Excludes the files/directories specified by a StandardCollection. @@ -214,7 +261,7 @@ public ExclusionProcessor addExcludedCollection(final StandardCollection collect public DocumentNameMatcher getNameMatcher(final DocumentName basedir) { // if lastMatcher is not set or the basedir is not the same as the last one then // we have to regenerate the matching document. - // Otherwise we can just return the lastMatcher since there is no change. + // Otherwise, we can just return the lastMatcher since there is no change. if (lastMatcher == null || !basedir.equals(lastMatcherBaseDir)) { lastMatcherBaseDir = basedir; @@ -347,6 +394,7 @@ private void extractPaths(final MatcherSet.Builder matcherBuilder) { } } } + /** * Serializes and deserializes the ExclusionProcessor to XML document */ diff --git a/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java b/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java index 3ec9849a7..c14abc4c8 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java @@ -18,7 +18,13 @@ */ package org.apache.rat.utils; +import org.w3c.dom.Document; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; import java.io.InputStream; +import java.io.StringWriter; import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; @@ -27,7 +33,10 @@ import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; +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; /** @@ -94,4 +103,28 @@ public static DocumentBuilder documentBuilder() { throw new IllegalStateException("No XML parser defined", e); } } + + /** + * Write an XML document to a file. + * @param document the document to write + * @param file the file to write to. + */ + public static void writeDocument(final Document document, final File file) throws IOException, TransformerException { + DOMSource source = new DOMSource(document); + FileWriter writer = new FileWriter(file); + StreamResult result = new StreamResult(writer); + createTransformer().transform(source, result); + } + + /** + * Write an XML document to a file. + * @param document the document to write. + */ + public static String serializeDocument(final Document document) throws TransformerException { + DOMSource source = new DOMSource(document); + StringWriter writer = new StringWriter(); + StreamResult result = new StreamResult(writer); + createTransformer().transform(source, result); + return writer.toString(); + } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java b/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java new file mode 100644 index 000000000..8e788af56 --- /dev/null +++ b/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java @@ -0,0 +1,160 @@ +/* + * 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 * + * * + * https://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 org.apache.rat.commandline.StyleSheets; +import org.apache.rat.config.AddLicenseHeaders; +import org.apache.rat.config.exclusion.StandardCollection; +import org.apache.rat.config.results.ClaimValidator; +import org.apache.rat.document.DocumentName; +import org.apache.rat.document.DocumentNameMatcher; +import org.apache.rat.license.LicenseSetFactory; +import org.apache.rat.report.claim.ClaimStatistic; +import org.apache.rat.report.claim.ClaimStatisticTest; +import org.apache.rat.testhelpers.FileUtils; +import org.apache.rat.utils.StandardXmlFactory; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; +import org.xmlunit.assertj3.XmlAssert; + +import javax.xml.transform.TransformerException; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +class OutputTest { + + static Path tempPath; + + @BeforeAll + static void setup() throws IOException { + tempPath = Files.createTempDirectory("outputTest").toAbsolutePath(); + } + + @AfterAll + static void teardown() { + FileUtils.delete(tempPath.toFile()); + } + + @Test + void documentReadingTest() throws IOException, SAXException, TransformerException { + Path testPath = tempPath.resolve("documentReading"); + File testFile = testPath.toFile(); + FileUtils.mkDir(testFile); + DocumentName workingDirectory = DocumentName.builder(testPath.toFile()).setBaseName(testFile).build(); + Document document; + DocumentName documentFile = workingDirectory.resolve("document.xml"); + try (InputStream inputStream = OutputTest.class.getClassLoader().getResourceAsStream("XmlOutputExamples/elements.xml")) { + document = StandardXmlFactory.documentBuilder().parse(inputStream); + StandardXmlFactory.writeDocument(document, documentFile.asFile()); + } + + Reporter.Output.Builder builder = Reporter.Output.builder().document(documentFile.getName(), workingDirectory); + + Reporter.Output output = builder.build(); + XmlAssert.assertThat(output.getDocument()).and(document) + .ignoreWhitespace() + .areIdentical(); + } + + @Test + void stasticReadingTest() throws IOException { + Path testPath = tempPath.resolve("statisticReading"); + File testFile = testPath.toFile(); + FileUtils.mkDir(testFile); + DocumentName workingDirectory = DocumentName.builder(testPath.toFile()).setBaseName(testFile).build(); + DocumentName documentFile = workingDirectory.resolve("statistic.xml"); + + ClaimStatistic underTest = new ClaimStatistic(); + underTest.incLicenseCategoryCount("familyCagegory", 1); + underTest.incCounter(ClaimStatistic.Counter.APPROVED, 2); + underTest.incCounter(org.apache.rat.api.Document.Type.IGNORED, 3); + underTest.incLicenseNameCount("licenseName", 4); + + ClaimStatistic.Serde serde = underTest.serde(); + StringWriter stringWriter = new StringWriter(); + serde.serialize(stringWriter); + try (FileOutputStream fos = new FileOutputStream(documentFile.asFile())) { + fos.write(stringWriter.toString().getBytes(StandardCharsets.UTF_8)); + } + + Reporter.Output.Builder builder = Reporter.Output.builder().statistic(documentFile.getName(), workingDirectory); + + Reporter.Output output = builder.build(); + ClaimStatisticTest.assertSame(output.getStatistic(), underTest); + } + + @Test + void configurationReadingTest() throws IOException { + Path testPath = tempPath.resolve("configurationReading"); + File testFile = testPath.toFile(); + FileUtils.mkDir(testFile); + DocumentName workingDirectory = DocumentName.builder(testPath.toFile()).setBaseName(testFile).build(); + DocumentName documentFile = workingDirectory.resolve("configuration.xml"); + + ReportConfiguration underTest = new ReportConfiguration(); + underTest.setAddLicenseHeaders(AddLicenseHeaders.FORCED); + underTest.listFamilies(LicenseSetFactory.LicenseFilter.APPROVED); + underTest.listLicenses(LicenseSetFactory.LicenseFilter.ALL); + underTest.setDryRun(true); + underTest.setArchiveProcessing(ReportConfiguration.Processing.NOTIFICATION); + underTest.setStandardProcessing(ReportConfiguration.Processing.ABSENCE); + underTest.setStyleSheet(StyleSheets.MISSING_HEADERS.getStyleSheet()); + underTest.setOut(new File("/some/file/somewhere")); + underTest.setCopyrightMessage("the copyright message"); + underTest.addSource(new File("/my/file")); + underTest.addSource(new ReportConfigurationTest.TestingReportable()); + underTest.addExcludedPatterns(List.of("pattern/**", "pattern2/**")); + underTest.addExcludedCollection(StandardCollection.BAZAAR); + underTest.addExcludedCollection(StandardCollection.MISC); + underTest.addExcludedFileProcessor(StandardCollection.HIDDEN_FILE); + underTest.addExcludedMatcher(DocumentNameMatcher.MATCHES_ALL); + underTest.addIncludedPatterns(List.of("**/pattern3", "**/pattern4")); + underTest.addIncludedCollection(StandardCollection.ARCH); + underTest.addIncludedCollection(StandardCollection.BITKEEPER); + underTest.addIncludedMatcher(DocumentNameMatcher.MATCHES_NONE); + + ClaimValidator claimValidator = underTest.getClaimValidator(); + claimValidator.setMax(ClaimStatistic.Counter.APPROVED, 5); + claimValidator.setMin(ClaimStatistic.Counter.APPROVED, 3); + claimValidator.setMax(ClaimStatistic.Counter.ARCHIVES, 10); + claimValidator.setMin(ClaimStatistic.Counter.BINARIES, 4); + + StringWriter stringWriter = new StringWriter(); + underTest.serde().serialize(stringWriter); + + try (FileOutputStream fos = new FileOutputStream(documentFile.asFile())) { + fos.write(stringWriter.toString().getBytes(StandardCharsets.UTF_8)); + } + + Reporter.Output.Builder builder = Reporter.Output.builder().configuration(documentFile.getName(), workingDirectory); + + Reporter.Output output = builder.build(); + ReportConfigurationTest.assertSame(output.getConfiguration(), underTest); + } +} diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java index 7d6040433..026b795a7 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java @@ -24,6 +24,7 @@ import static org.mockito.Mockito.when; import java.io.BufferedReader; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileFilter; @@ -32,9 +33,11 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; +import java.io.StringWriter; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -44,15 +47,21 @@ import org.apache.commons.io.filefilter.DirectoryFileFilter; import org.apache.commons.io.output.CloseShieldOutputStream; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.api.RatException; +import org.apache.rat.commandline.StyleSheets; import org.apache.rat.config.AddLicenseHeaders; +import org.apache.rat.config.exclusion.ExclusionProcessorTest; import org.apache.rat.config.exclusion.StandardCollection; +import org.apache.rat.config.results.ClaimValidator; import org.apache.rat.configuration.XMLConfigurationReaderTest; import org.apache.rat.document.DocumentName; import org.apache.rat.document.DocumentNameMatcher; import org.apache.rat.license.ILicense; import org.apache.rat.license.ILicenseFamily; import org.apache.rat.license.LicenseSetFactory.LicenseFilter; +import org.apache.rat.report.RatReport; import org.apache.rat.report.Reportable; +import org.apache.rat.report.claim.ClaimStatistic; import org.apache.rat.testhelpers.TestingLog; import org.apache.rat.testhelpers.TestingLicense; import org.apache.rat.testhelpers.TestingMatcher; @@ -490,7 +499,7 @@ void stylesheetTest() throws IOException, URISyntaxException { assertThat(underTest.getStyleSheetDescriptor()).isNull(); assertThat(underTest.getStyleSheet()).isNull(); InputStream stream = mock(InputStream.class); - underTest.setStyleSheet(new ReportConfiguration.IODescriptor("stylesheetTest", () -> stream)); + underTest.setStyleSheet(new ReportConfiguration.IODescriptor<>("stylesheetTest", () -> stream)); assertThat(underTest.getStyleSheetDescriptor().ioSupplier().get()).isEqualTo(stream); assertThat(underTest.getStyleSheet().get()).isEqualTo(stream); @@ -760,6 +769,64 @@ public static void validateDefault(ReportConfiguration config) { validateDefaultLicenses(config); } + public static void assertSame(ReportConfiguration actual, ReportConfiguration expected) { + assertThat(actual.isAddingLicenses()).isEqualTo(expected.isAddingLicenses()); + assertThat(actual.isAddingLicensesForced()).isEqualTo(expected.isAddingLicensesForced()); + assertThat(actual.listFamilies()).isEqualTo(expected.listFamilies()); + assertThat(actual.listLicenses()).isEqualTo(expected.listLicenses()); + assertThat(actual.isDryRun()).isEqualTo(expected.isDryRun()); + assertThat(actual.getArchiveProcessing()).isEqualTo(expected.getArchiveProcessing()); + assertThat(actual.getStandardProcessing()).isEqualTo(expected.getStandardProcessing()); + assertThat(actual.getStyleSheetDescriptor().name()).isEqualTo(expected.getStyleSheetDescriptor().name()); + assertThat(actual.getOutputDescriptor().name()).isEqualTo(expected.getOutputDescriptor().name()); + + assertThat(actual.getCopyrightMessage()).isEqualTo(expected.getCopyrightMessage()); + + assertThat(actual.sources()).containsExactlyElementsOf(expected.sources()); + assertThat(actual.reportables()).containsExactlyElementsOf(expected.reportables().toList()); + ExclusionProcessorTest.assertSame(actual.getExclusionProcessor(), expected.getExclusionProcessor()); + + } + @Test + void serdeTest() throws IOException { + underTest.setAddLicenseHeaders(AddLicenseHeaders.FORCED); + underTest.listFamilies(LicenseFilter.APPROVED); + underTest.listLicenses(LicenseFilter.ALL); + underTest.setDryRun(true); + underTest.setArchiveProcessing(ReportConfiguration.Processing.NOTIFICATION); + underTest.setStandardProcessing(ReportConfiguration.Processing.ABSENCE); + underTest.setStyleSheet(StyleSheets.MISSING_HEADERS.getStyleSheet()); + underTest.setOut(new File("/some/file/somewhere")); + underTest.setCopyrightMessage("the copyright message"); + underTest.addSource(new File("/my/file")); + underTest.addSource(new TestingReportable()); + + underTest.addExcludedPatterns(List.of("pattern/**", "pattern2/**")); + underTest.addExcludedCollection(StandardCollection.BAZAAR); + underTest.addExcludedCollection(StandardCollection.MISC); + underTest.addExcludedFileProcessor(StandardCollection.HIDDEN_FILE); + underTest.addExcludedMatcher(DocumentNameMatcher.MATCHES_ALL); + underTest.addIncludedPatterns(List.of("**/pattern3", "**/pattern4")); + underTest.addIncludedCollection(StandardCollection.ARCH); + underTest.addIncludedCollection(StandardCollection.BITKEEPER); + underTest.addIncludedMatcher(DocumentNameMatcher.MATCHES_NONE); + + ClaimValidator claimValidator = underTest.getClaimValidator(); + + claimValidator.setMax(ClaimStatistic.Counter.APPROVED, 5); + claimValidator.setMin(ClaimStatistic.Counter.APPROVED, 3); + claimValidator.setMax(ClaimStatistic.Counter.ARCHIVES, 10); + claimValidator.setMin(ClaimStatistic.Counter.BINARIES, 4); + + StringWriter stringWriter = new StringWriter(); + underTest.serde().serialize(stringWriter); + + ReportConfiguration actual = new ReportConfiguration(); + actual.serde().deserialize(() -> new ByteArrayInputStream(stringWriter.toString().getBytes(StandardCharsets.UTF_8)), + DocumentName.builder(new File("/rootDir")).build()); + assertSame(actual, underTest); + } + /** * A class to act as an output stream and count the number of close operations. */ @@ -776,4 +843,20 @@ public void close() { ++closeCount; } } + + /** + * A reportable that only reports its name. Does no actual work. + */ + static class TestingReportable implements Reportable { + + @Override + public void run(RatReport report) throws RatException { + // does nothing + } + + @Override + public DocumentName name() { + return DocumentName.builder().setBaseName("").setName("TestingReportable").build(); + } + } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java index 198d9d9b3..9e2c79de1 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java @@ -7,7 +7,7 @@ * "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 * + * https://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 * @@ -405,13 +405,8 @@ private Validator initValidator() throws SAXException { @Test void xmlReportTest() throws Exception { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ReportConfiguration configuration = initializeConfiguration(); - configuration.setStyleSheet(StyleSheets.XML.getStyleSheet()); - configuration.setOut(new ReportConfiguration.IODescriptor("xmlReportTest", () -> out)); - new Reporter(configuration).execute().format(configuration); - Document doc = XmlUtils.toDom(new ByteArrayInputStream(out.toByteArray())); + Document doc = new Reporter(configuration).execute().getDocument(); XPath xPath = XPathFactory.newInstance().newXPath(); @@ -457,10 +452,9 @@ void plainReportTest() throws Exception { "Generated at: "; ByteArrayOutputStream out = new ByteArrayOutputStream(); ReportConfiguration configuration = initializeConfiguration(); - configuration.setOut(new ReportConfiguration.IODescriptor("plainReportTest", () -> out)); + configuration.setOut(new ReportConfiguration.IODescriptor<>("plainReportTest", () -> out)); new Reporter(configuration).execute().format(configuration); - out.flush(); String document = out.toString(); TextUtils.assertNotContains("", document); @@ -473,11 +467,10 @@ void plainReportTest() throws Exception { void unapprovedLicensesReportTest() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); ReportConfiguration configuration = initializeConfiguration(); - configuration.setOut(new ReportConfiguration.IODescriptor("unapprovedLicensesReportTest", () -> out)); + configuration.setOut(new ReportConfiguration.IODescriptor<>("unapprovedLicensesReportTest", () -> out)); configuration.setStyleSheet(this.getClass().getResource("/org/apache/rat/unapproved-licenses.xsl")); new Reporter(configuration).execute().format(configuration); - out.flush(); String document = out.toString(); TextUtils.assertContains("Generated at: ", document ); @@ -489,29 +482,26 @@ void unapprovedLicensesReportTest() throws Exception { void listLicensesReportTest() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); ReportConfiguration configuration = initializeConfiguration(); - configuration.setOut(new ReportConfiguration.IODescriptor("listLicensesReportTest", () -> out)); + configuration.setOut(new ReportConfiguration.IODescriptor<>("listLicensesReportTest", () -> out)); configuration.setStyleSheet(StyleSheets.UNAPPROVED_LICENSES.getStyleSheet()); Reporter.listLicenses(configuration, LicenseSetFactory.LicenseFilter.NONE); out.flush(); String document = out.toString(); - assertThat(document).contains("Licenses (NONE):"); } @Test void counterMaxTest() throws Exception { ReportConfiguration config = initializeConfiguration(); - Reporter reporter = new Reporter(config); - Reporter.Output output = reporter.execute(); + Reporter.Output output = new Reporter(config).execute(); assertThat(config.getClaimValidator().hasErrors()).isTrue(); assertThat(config.getClaimValidator().isValid(ClaimStatistic.Counter.UNAPPROVED, output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED))) .isFalse(); config = initializeConfiguration(); config.getClaimValidator().setMax(ClaimStatistic.Counter.UNAPPROVED, 2); - reporter = new Reporter(config); - output = reporter.execute(); + output = new Reporter(config).execute(); assertThat(config.getClaimValidator().hasErrors()).isFalse(); assertThat(config.getClaimValidator().isValid(ClaimStatistic.Counter.UNAPPROVED, output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED))) .isTrue(); diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java index 19e2e1542..c30579431 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java @@ -18,6 +18,9 @@ */ package org.apache.rat.config.exclusion; +import java.io.ByteArrayInputStream; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; import java.nio.file.FileSystems; import java.nio.file.Path; import java.util.ArrayList; @@ -26,6 +29,9 @@ import org.apache.commons.io.FileUtils; import org.apache.rat.document.DocumentNameMatcher; import org.apache.rat.document.DocumentName; +import org.apache.rat.report.xml.writer.XmlWriter; +import org.apache.rat.utils.StandardXmlFactory; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import java.io.File; @@ -37,6 +43,8 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.Mockito; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; @@ -264,4 +272,196 @@ private static Stream getDocumentNames() { return lst.stream(); } + + @Test + void addNullIncludedMatcherTest() { + ExclusionProcessor underTest = new ExclusionProcessor(); + assertThat(underTest.getIncludedPaths()).isEmpty(); + underTest.addIncludedMatcher(null); + assertThat(underTest.getIncludedPaths()).isEmpty(); + underTest.addIncludedMatcher(DocumentNameMatcher.MATCHES_ALL) + .addIncludedMatcher(null); + assertThat(underTest.getIncludedPaths()).hasSize(1); + List actualPaths = underTest.getIncludedPaths().stream().map(DocumentNameMatcher::toString).toList(); + assertThat(actualPaths).containsExactly(DocumentNameMatcher.MATCHES_ALL.toString()); + } + + @Test + void addNullExcludedMatcherTest() { + ExclusionProcessor underTest = new ExclusionProcessor(); + assertThat(underTest.getExcludedPaths()).isEmpty(); + underTest.addExcludedMatcher(null); + assertThat(underTest.getExcludedPaths()).isEmpty(); + underTest.addExcludedMatcher(DocumentNameMatcher.MATCHES_ALL) + .addExcludedMatcher(null); + assertThat(underTest.getExcludedPaths()).hasSize(1); + List actualPaths = underTest.getExcludedPaths().stream().map(DocumentNameMatcher::toString).toList(); + assertThat(actualPaths).containsExactly(DocumentNameMatcher.MATCHES_ALL.toString()); + } + + @Test + void addFileProcessor() { + ExclusionProcessor underTest = new ExclusionProcessor(); + assertThat(underTest.getFileProcessors()).isEmpty(); + underTest.addFileProcessor(null); + assertThat(underTest.getFileProcessors()).isEmpty(); + underTest.addFileProcessor(StandardCollection.HIDDEN_FILE) + .addFileProcessor(null); + assertThat(underTest.getFileProcessors()).containsExactly(StandardCollection.HIDDEN_FILE); + } + + @Test + void addNullIncludedPatternTest() { + ExclusionProcessor underTest = new ExclusionProcessor(); + assertThat(underTest.getIncludedPatterns()).isEmpty(); + underTest.addIncludedPatterns(null); + assertThat(underTest.getIncludedPatterns()).isEmpty(); + underTest.addIncludedPatterns(Collections.emptyList()); + assertThat(underTest.getIncludedPatterns()).isEmpty(); + underTest.addIncludedPatterns(List.of("hello/world")) + .addIncludedPatterns(null) + .addIncludedPatterns(Collections.emptyList()); + assertThat(underTest.getIncludedPatterns()).containsExactly("hello/world"); + } + + @Test + void addNullExcludedPatternTest() { + ExclusionProcessor underTest = new ExclusionProcessor(); + assertThat(underTest.getExcludedPatterns()).isEmpty(); + underTest.addExcludedPatterns(null); + assertThat(underTest.getExcludedPatterns()).isEmpty(); + underTest.addExcludedPatterns(Collections.emptyList()); + assertThat(underTest.getExcludedPatterns()).isEmpty(); + underTest.addExcludedPatterns(List.of("hello/world")) + .addExcludedPatterns(null) + .addExcludedPatterns(Collections.emptyList()); + assertThat(underTest.getExcludedPatterns()).containsExactly("hello/world"); + } + + public static void assertSame(ExclusionProcessor actual, ExclusionProcessor expected) { + assertThat(actual.getExcludedCollections()).containsExactlyElementsOf(expected.getExcludedCollections()); + assertThat(actual.getFileProcessors()).containsExactlyElementsOf(expected.getFileProcessors()); + assertThat(actual.getIncludedCollections()).containsExactlyElementsOf(expected.getIncludedCollections()); + assertThat(actual.getExcludedPatterns()).containsExactlyElementsOf(expected.getExcludedPatterns()); + assertThat(actual.getIncludedPatterns()).containsExactlyElementsOf(expected.getIncludedPatterns()); + + // paths only match on name. deserialized paths are not functional. + List actualPaths = actual.getExcludedPaths().stream().map(DocumentNameMatcher::toString).toList(); + List expectedPaths = expected.getExcludedPaths().stream().map(DocumentNameMatcher::toString).toList(); + assertThat(actualPaths).as("excluded paths").containsExactlyElementsOf(expectedPaths); + + actualPaths = actual.getIncludedPaths().stream().map(DocumentNameMatcher::toString).toList(); + expectedPaths = expected.getIncludedPaths().stream().map(DocumentNameMatcher::toString).toList(); + assertThat(actualPaths).as("included paths").containsExactlyElementsOf(expectedPaths); + } + + @ParameterizedTest + @MethodSource("serdeTestData") + void serdeTest(ExclusionProcessor underTest) throws IOException, SAXException { + StringWriter stringWriter = new StringWriter(); + try (XmlWriter writer = new XmlWriter(stringWriter)) { + underTest.serde().serialize(writer); + } + Document document = StandardXmlFactory.documentBuilder().parse(new ByteArrayInputStream(stringWriter.toString().getBytes(StandardCharsets.UTF_8))); + ExclusionProcessor actual = new ExclusionProcessor(); + actual.serde().deserialize(document.getElementsByTagName("ExclusionProcessor").item(0)); + assertSame(actual, underTest); + } + + static List serdeTestData() { + List tests = new ArrayList<>(); + tests.add(new ExclusionProcessor()); + + // single exclusions + tests.add(new ExclusionProcessor() + .addExcludedPatterns(List.of("pattern/**"))); + + tests.add(new ExclusionProcessor() + .addExcludedCollection(StandardCollection.BAZAAR)); + + + tests.add(new ExclusionProcessor() + .addExcludedMatcher(DocumentNameMatcher.MATCHES_ALL)); + + // single inclusions + tests.add(new ExclusionProcessor() + .addIncludedPatterns(List.of("pattern/**"))); + + tests.add(new ExclusionProcessor() + .addIncludedCollection(StandardCollection.BAZAAR)); + + tests.add(new ExclusionProcessor() + .addIncludedMatcher(DocumentNameMatcher.MATCHES_NONE)); + + // full population + tests.add(new ExclusionProcessor() + .addExcludedPatterns(List.of("pattern/**", "pattern2/**")) + .addExcludedCollection(StandardCollection.BAZAAR) + .addExcludedCollection(StandardCollection.MISC) + .addExcludedMatcher(DocumentNameMatcher.MATCHES_ALL) + .addIncludedPatterns(List.of("**/pattern3", "**/pattern4")) + .addIncludedCollection(StandardCollection.ARCH) + .addIncludedCollection(StandardCollection.BITKEEPER) + .addIncludedMatcher(DocumentNameMatcher.MATCHES_NONE)); + + return tests; + } + + @Test + void reportExclusionsTest() throws IOException { + ExclusionProcessor underTest = new ExclusionProcessor() + .addExcludedPatterns(List.of("pattern/**", "pattern2/**")) + .addExcludedCollection(StandardCollection.BAZAAR) + .addExcludedCollection(StandardCollection.MISC) + .addFileProcessor(StandardCollection.HIDDEN_FILE) + .addExcludedMatcher(DocumentNameMatcher.MATCHES_ALL) + .addIncludedPatterns(List.of("**/pattern3", "**/pattern4")) + .addIncludedCollection(StandardCollection.ARCH) + .addIncludedCollection(StandardCollection.BITKEEPER) + .addIncludedMatcher(DocumentNameMatcher.MATCHES_NONE); + + StringWriter writer = new StringWriter(); + underTest.reportExclusions(writer); + String actual = writer.toString(); + + assertThat(actual).containsPattern("Excluding patterns:[^$]+\\Qpattern/**\\E") + .containsPattern("Excluding patterns:[^$]+\\Qpattern2/**\\E") + .containsPattern("Including patterns:[^$]+\\Q**/pattern3\\E") + .containsPattern("Including patterns:[^$]+\\Q**/pattern4\\E") + .contains("Excluding " + StandardCollection.BAZAAR + " collection.") + .contains("Excluding " + StandardCollection.MISC + " collection.") + .contains("Including " + StandardCollection.ARCH + " collection.") + .contains("Including " + StandardCollection.BITKEEPER + " collection.") + .contains("Processing exclude file from " + StandardCollection.HIDDEN_FILE) + .contains("Excluding " + DocumentNameMatcher.MATCHES_ALL + ".") + .contains("Including " + DocumentNameMatcher.MATCHES_NONE + "."); + } + + @Test + void getNameMatcherTest() { + ExclusionProcessor underTest = new ExclusionProcessor() + .addExcludedPatterns(List.of("pattern/**", "pattern2/**")) + .addExcludedCollection(StandardCollection.BAZAAR) + .addExcludedCollection(StandardCollection.MISC) + .addFileProcessor(StandardCollection.HIDDEN_FILE) + .addExcludedMatcher(DocumentNameMatcher.MATCHES_ALL) + .addIncludedPatterns(List.of("**/pattern3", "**/pattern4")) + .addIncludedCollection(StandardCollection.ARCH) + .addIncludedCollection(StandardCollection.BITKEEPER) + .addIncludedMatcher(DocumentNameMatcher.MATCHES_NONE); + + assertThat(underTest.getLastMatcherBaseDir()).isNull(); + assertThat(underTest.getLastMatcher()).isNull(); + DocumentName base = DocumentName.builder(new File(".")).build(); + + DocumentNameMatcher matcher = underTest.getNameMatcher(base); + assertThat(underTest.getLastMatcherBaseDir()).isEqualTo(base); + assertThat(underTest.getLastMatcher()).isEqualTo(matcher); + + DocumentNameMatcher matcher2 = underTest.getNameMatcher(base); + assertThat(underTest.getLastMatcherBaseDir()).isEqualTo(base); + assertThat(underTest.getLastMatcher()).isEqualTo(matcher); + assertThat(underTest.getLastMatcherBaseDir()).isEqualTo(base); + assertThat(matcher2).isEqualTo(matcher); + } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java b/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java new file mode 100644 index 000000000..ef8a31e2c --- /dev/null +++ b/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java @@ -0,0 +1,148 @@ +/* + * 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 * + * * + * https://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.report.claim; + +import org.apache.rat.api.Document; +import org.junit.jupiter.api.Test; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ClaimStatisticTest { + + @Test + void counterTests() { + ClaimStatistic underTest = new ClaimStatistic(); + assertThat(underTest.getCounter(ClaimStatistic.Counter.APPROVED)).isZero(); + underTest.incCounter(ClaimStatistic.Counter.APPROVED, 1); + assertThat(underTest.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); + underTest.incCounter(ClaimStatistic.Counter.APPROVED, -2); + assertThat(underTest.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(-1); + underTest.setCounter(ClaimStatistic.Counter.APPROVED, Integer.MAX_VALUE); + assertThat(underTest.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(Integer.MAX_VALUE); + } + + @Test + void typeTests() { + ClaimStatistic underTest = new ClaimStatistic(); + assertThat(underTest.getCounter(Document.Type.NOTICE)).isZero(); + underTest.incCounter(Document.Type.NOTICE, 1); + assertThat(underTest.getCounter(Document.Type.NOTICE)).isEqualTo(1); + underTest.incCounter(Document.Type.NOTICE, -2); + assertThat(underTest.getCounter(Document.Type.NOTICE)).isEqualTo(-1); + } + + @Test + void documentTypeTest() { + ClaimStatistic underTest = new ClaimStatistic(); + assertThat(underTest.getDocumentTypes()).isEmpty(); + underTest.incCounter(Document.Type.NOTICE, 1); + underTest.incCounter(Document.Type.BINARY, -1); + assertThat(underTest.getDocumentTypes()).containsExactly(Document.Type.BINARY, Document.Type.NOTICE); + } + + @Test + void licenseCategoryCountTest() { + ClaimStatistic underTest = new ClaimStatistic(); + assertThat(underTest.getLicenseCategoryCount("fam")).isZero(); + underTest.incLicenseCategoryCount("fam", 1); + assertThat(underTest.getLicenseCategoryCount("fam")).isEqualTo(1); + underTest.incLicenseCategoryCount("fam", -2); + assertThat(underTest.getLicenseCategoryCount("fam")).isEqualTo(-1); + underTest.incLicenseCategoryCount("wayToLongAName", 5); + assertThat(underTest.getLicenseCategoryCount("wayToLongAName")).isEqualTo(5); + } + + @Test + void licenseNameCountTest() { + ClaimStatistic underTest = new ClaimStatistic(); + assertThat(underTest.getLicenseNameCount("fam")).isZero(); + underTest.incLicenseNameCount("fam", 1); + assertThat(underTest.getLicenseNameCount("fam")).isEqualTo(1); + underTest.incLicenseNameCount("fam", -2); + assertThat(underTest.getLicenseNameCount("fam")).isEqualTo(-1); + } + + @Test + void licenseFamilyCategoriesTest() { + ClaimStatistic underTest = new ClaimStatistic(); + assertThat(underTest.getLicenseFamilyCategories()).isEmpty(); + underTest.incLicenseCategoryCount("one", 1); + underTest.incLicenseCategoryCount("neg", -1); + assertThat(underTest.getLicenseFamilyCategories()).containsExactly("neg", "one"); + underTest.incLicenseCategoryCount("wayToLongAName", 5); + assertThat(underTest.getLicenseFamilyCategories()).containsExactly("neg", "one", "wayToLongAName"); + } + + @Test + void licenseFamilyNameTest() { + ClaimStatistic underTest = new ClaimStatistic(); + assertThat(underTest.getLicenseNames()).isEmpty(); + underTest.incLicenseNameCount("one", 1); + underTest.incLicenseNameCount("neg", -1); + assertThat(underTest.getLicenseNames()).containsExactly("neg", "one"); + underTest.incLicenseNameCount("wayToLongAName", 5); + assertThat(underTest.getLicenseNames()).containsExactly("neg", "one", "wayToLongAName"); + } + + /** + * Compares two claim statistics for similarity after serialization/deserialization. + * @param actual the deserialized verison. + * @param expected the original version. + */ + public static void assertSame(final ClaimStatistic actual, final ClaimStatistic expected) { + + assertThat(actual.getLicenseFamilyCategories()).containsExactlyElementsOf(expected.getLicenseFamilyCategories()); + assertThat(actual.getLicenseNames()).containsExactlyElementsOf(expected.getLicenseNames()); + assertThat(actual.getDocumentTypes()).containsExactlyElementsOf(expected.getDocumentTypes()); + for (String cat : expected.getLicenseFamilyCategories()) { + assertThat(actual.getLicenseCategoryCount(cat)).isEqualTo(expected.getLicenseCategoryCount(cat)); + } + for (String name : expected.getLicenseNames()) { + assertThat(actual.getLicenseNameCount(name)).isEqualTo(expected.getLicenseNameCount(name)); + } + for (Document.Type type : expected.getDocumentTypes()) { + assertThat(actual.getCounter(type)).isEqualTo(expected.getCounter(type)); + } + for (ClaimStatistic.Counter counter : ClaimStatistic.Counter.values()) { + assertThat(actual.getCounter(counter)).isEqualTo(expected.getCounter(counter)); + } + } + + @Test + void serdeRoundTrip() throws IOException { + ClaimStatistic underTest = new ClaimStatistic(); + underTest.incLicenseCategoryCount("familyCagegory", 1); + underTest.incCounter(ClaimStatistic.Counter.APPROVED, 2); + underTest.incCounter(Document.Type.IGNORED, 3); + underTest.incLicenseNameCount("licenseName", 4); + + ClaimStatistic.Serde serde = underTest.serde(); + StringWriter stringWriter = new StringWriter(); + serde.serialize(stringWriter); + ClaimStatistic actual = new ClaimStatistic(); + ClaimStatistic.Serde serde2 = actual.serde(); + serde2.deserialize(() -> new ByteArrayInputStream(stringWriter.toString().getBytes(StandardCharsets.UTF_8))); + + assertSame(actual, underTest); + } +} diff --git a/pom.xml b/pom.xml index cc2dc1581..76d9d0ec8 100644 --- a/pom.xml +++ b/pom.xml @@ -61,6 +61,7 @@ agnostic home for software distribution comprehension and audit tools. RAT 2.4.1 3.1 + 2.12.0 3.5.1 3.15.2 @@ -268,6 +269,18 @@ agnostic home for software distribution comprehension and audit tools. 1.3.1 test + + org.xmlunit + xmlunit-assertj3 + ${xmlunit.version} + test + + + org.xmlunit + xmlunit-core + ${xmlunit.version} + test + From 30707d2d4b53e8c495d02efb3e733a97ffd694ba Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Mon, 6 Jul 2026 15:59:00 +0100 Subject: [PATCH 03/17] fixed some style issues --- .../rat/config/exclusion/ExclusionProcessor.java | 12 ++++++------ .../org/apache/rat/utils/StandardXmlFactory.java | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java index b8ade20af..05844d1a0 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java @@ -86,14 +86,14 @@ public Serde serde() { return new Serde(); } - /* the folloing set of methods are here for testing purposes */ + /* the following set of methods are here for testing purposes */ Set getExcludedPatterns() { - return new HashSet(excludedPatterns); + return new HashSet<>(excludedPatterns); } Collection getExcludedPaths() { - return new ArrayList(excludedPaths); + return new ArrayList<>(excludedPaths); } Set getIncludedPatterns() { @@ -101,7 +101,7 @@ Set getIncludedPatterns() { } Collection getIncludedPaths() { - return new ArrayList(includedPaths); + return new ArrayList<>(includedPaths); } Collection getFileProcessors() { @@ -109,11 +109,11 @@ Collection getFileProcessors() { } Set getIncludedCollections() { - return new HashSet(includedCollections); + return new HashSet<>(includedCollections); } Set getExcludedCollections() { - return new HashSet(excludedCollections); + return new HashSet<>(excludedCollections); } DocumentNameMatcher getLastMatcher() { diff --git a/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java b/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java index c14abc4c8..eeee73432 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java @@ -18,8 +18,6 @@ */ package org.apache.rat.utils; -import org.w3c.dom.Document; - import java.io.File; import java.io.FileWriter; import java.io.IOException; @@ -39,6 +37,8 @@ import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import org.w3c.dom.Document; + /** * Factory to create standard XML objects. The intention of this class is to resolve in a consistent manner the * XXE errors and similar XML IO errors. From 046c1bed9f79332995e9edadb58dc7b44d3e9be1 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Mon, 6 Jul 2026 16:51:08 +0100 Subject: [PATCH 04/17] fixes sonarqube issues --- .../main/java/org/apache/rat/Reporter.java | 42 +++++++----------- .../test/java/org/apache/rat/OutputTest.java | 44 +++++++++++++++++++ .../apache/rat/ReportConfigurationTest.java | 4 +- .../apache/rat/ReporterOptionsProvider.java | 30 ++++++------- .../java/org/apache/rat/ReporterTest.java | 14 ------ .../exclusion/ExclusionProcessorTest.java | 7 +-- .../java/org/apache/rat/mp/RatReportMojo.java | 2 +- .../java/org/apache/rat/anttasks/Report.java | 3 +- 8 files changed, 84 insertions(+), 62 deletions(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/Reporter.java b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java index 9b037efe9..42fa52d73 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/Reporter.java +++ b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java @@ -118,23 +118,6 @@ public Output getOutput() { return output; } - /** - * 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(); - } - } - /** * The output from a report run. */ @@ -220,19 +203,28 @@ public void format(final IOSupplier stylesheet, final IOSupplier printWriter.format(LICENSE_FORMAT, lic.getLicenseFamily().getFamilyCategory(), + lic.getLicenseFamily().getFamilyName(), lic.getNote())); + printWriter.println(); + } + + /** + * Lists the licenses on the output specified in the configuration. * - * @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 { + public void listLicenses(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(); + listLicenses(pw, filter); } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java b/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java index 8e788af56..ecfe42ee9 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java @@ -24,11 +24,14 @@ import org.apache.rat.config.results.ClaimValidator; import org.apache.rat.document.DocumentName; import org.apache.rat.document.DocumentNameMatcher; +import org.apache.rat.document.FileDocument; import org.apache.rat.license.LicenseSetFactory; import org.apache.rat.report.claim.ClaimStatistic; import org.apache.rat.report.claim.ClaimStatisticTest; +import org.apache.rat.test.utils.Resources; import org.apache.rat.testhelpers.FileUtils; import org.apache.rat.utils.StandardXmlFactory; +import org.apache.rat.walker.DirectoryWalker; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -37,16 +40,21 @@ import org.xmlunit.assertj3.XmlAssert; import javax.xml.transform.TransformerException; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.PrintWriter; import java.io.StringWriter; +import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; + class OutputTest { static Path tempPath; @@ -157,4 +165,40 @@ void configurationReadingTest() throws IOException { Reporter.Output output = builder.build(); ReportConfigurationTest.assertSame(output.getConfiguration(), underTest); } + + private ReportConfiguration initializeConfiguration() throws URISyntaxException { + Defaults defaults = Defaults.builder().build(); + final File elementsFile = Resources.getExampleResource("exampleData"); + final ReportConfiguration configuration = new ReportConfiguration(); + configuration.setFrom(defaults); + DocumentName documentName = DocumentName.builder(elementsFile).build(); + configuration.addSource(new DirectoryWalker(new FileDocument(documentName, elementsFile, + configuration.getDocumentExcluder(documentName)))); + return configuration; + } + + @Test + void listLicensesReportTest() throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ReportConfiguration configuration = initializeConfiguration(); + configuration.setOut(new ReportConfiguration.IODescriptor<>("listLicensesReportTest", () -> out)); + configuration.setStyleSheet(StyleSheets.UNAPPROVED_LICENSES.getStyleSheet()); + Reporter.Output output = Reporter.Output.builder() + .statistic(new ClaimStatistic()) + .document(null) + .configuration(configuration) + .build(); + output.listLicenses(LicenseSetFactory.LicenseFilter.NONE); + + out.flush(); + String document = out.toString(); + assertThat(document).contains("Licenses (NONE):"); + StringWriter writer = new StringWriter(); + try (PrintWriter printWriter = new PrintWriter(writer)) { + output.listLicenses(printWriter, LicenseSetFactory.LicenseFilter.ALL); + } + assertThat(writer.toString()).contains("Licenses (ALL):"); + + } + } diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java index 026b795a7..f289b6283 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java @@ -472,7 +472,7 @@ void outputTest() throws IOException { assertThat(underTest.getWriter()).isNotNull(); ByteArrayOutputStream stream = new ByteArrayOutputStream(); - underTest.setOut(new ReportConfiguration.IODescriptor("outputTest", () -> stream)); + underTest.setOut(new ReportConfiguration.IODescriptor<>("outputTest", () -> stream)); assertThat(underTest.getOutput().get()).isEqualTo(stream); PrintWriter writer = underTest.getWriter().get(); assertThat(writer).isNotNull(); @@ -560,7 +560,7 @@ void testValidate() { void testSetOut() throws IOException { ReportConfiguration config = new ReportConfiguration(); try (OutputStreamInterceptor osi = new OutputStreamInterceptor()) { - config.setOut(new ReportConfiguration.IODescriptor("testSetOut",() -> osi)); + config.setOut(new ReportConfiguration.IODescriptor<>("testSetOut",() -> osi)); assertThat(osi.closeCount).isEqualTo(0); try (OutputStream os = config.getOutput().get()) { assertThat(os).isNotNull(); diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsProvider.java b/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsProvider.java index 30905e90d..720a42102 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsProvider.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsProvider.java @@ -378,7 +378,7 @@ protected void inputExcludeSizeTest() { Reporter reporter = new Reporter(config); Reporter.Output output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(3); - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isZero(); // filter out source config = generateConfig(ImmutablePair.of(option, args)); @@ -469,7 +469,7 @@ protected void inputExcludeParsedScmTest() { Reporter.Output output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(11); // .gitignore is ignored by default as it is hidden but not counted - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isZero(); config = generateConfig(ImmutablePair.of(option, args)); reporter = new Reporter(config); @@ -591,13 +591,13 @@ protected void inputSourceTest() { Reporter reporter = new Reporter(config); Reporter.Output output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(3); - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isZero(); config = generateConfig(ImmutablePair.of(option, new String[]{inputFile.getAbsolutePath()})); reporter = new Reporter(config); output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isZero(); }); } @@ -622,7 +622,7 @@ private void execLicenseFamiliesApprovedTest(final Option option, final String[] Reporter.Output output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isZero(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); config = addCatzLicense(generateConfig(arg1)); @@ -630,7 +630,7 @@ private void execLicenseFamiliesApprovedTest(final Option option, final String[] output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isZero(); }); } @@ -662,13 +662,13 @@ private void execLicenseFamiliesDeniedTest(final Option option, final String[] a Reporter.Output output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isZero(); config = generateConfig(arg1); reporter = new Reporter(config); output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isZero(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); }); } @@ -709,7 +709,7 @@ private void configTest(final Option option) { output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(2); - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isZero(); Pair arg2 = ImmutablePair.of(Arg.CONFIGURATION_NO_DEFAULTS.find("configuration-no-defaults"), null); @@ -754,7 +754,7 @@ protected void execLicensesApprovedTest(final Option option, String[] args) { output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(2); - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isZero(); }); } @@ -791,7 +791,7 @@ protected void scanHiddenDirectoriesTest() { Reporter.Output output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isZero(); config = generateConfig(arg1); reporter = new Reporter(config); @@ -815,7 +815,7 @@ private void outTest(final Option option) { Reporter.Output output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isZero(); output.format(config); String actualText = TextUtils.readFile(outFile); TextUtils.assertContainsExactly(1, "Apache License 2.0: 1 ", actualText); @@ -854,7 +854,7 @@ private void styleSheetTest(final Option option) { Reporter reporter = new Reporter(config); Reporter.Output output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isZero(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); output.format(config); String actualText = baos.toString(StandardCharsets.UTF_8); @@ -884,7 +884,7 @@ private void styleSheetTest(final Option option) { Reporter reporter = new Reporter(config); Reporter.Output output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isZero(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); output.format(config); String actualText = baos.toString(StandardCharsets.UTF_8); @@ -926,7 +926,7 @@ protected void xmlTest() { Reporter reporter = new Reporter(config); Reporter.Output output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.APPROVED)).isZero(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); output.format(config); String actualText = baos.toString(StandardCharsets.UTF_8); diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java index 9e2c79de1..9afcc622f 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java @@ -21,7 +21,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Fail.fail; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.PrintStream; @@ -478,19 +477,6 @@ void unapprovedLicensesReportTest() throws Exception { TextUtils.assertPatternInTarget("\\Q/sub/Empty.txt\\E", document); } - @Test - void listLicensesReportTest() throws Exception { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ReportConfiguration configuration = initializeConfiguration(); - configuration.setOut(new ReportConfiguration.IODescriptor<>("listLicensesReportTest", () -> out)); - configuration.setStyleSheet(StyleSheets.UNAPPROVED_LICENSES.getStyleSheet()); - Reporter.listLicenses(configuration, LicenseSetFactory.LicenseFilter.NONE); - - out.flush(); - String document = out.toString(); - assertThat(document).contains("Licenses (NONE):"); - } - @Test void counterMaxTest() throws Exception { ReportConfiguration config = initializeConfiguration(); diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java index c30579431..066d9b623 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java @@ -42,7 +42,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.Mockito; import org.w3c.dom.Document; import org.xml.sax.SAXException; @@ -52,6 +51,8 @@ import static org.apache.rat.document.FSInfoTest.UNIX; import static org.apache.rat.document.FSInfoTest.WINDOWS; import static org.junit.jupiter.api.Assertions.fail; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; public class ExclusionProcessorTest { @@ -70,7 +71,7 @@ private String dump(DocumentNameMatcher nameMatcher, DocumentName name) { private DocumentName mkName(DocumentName baseDir, String pth) throws IOException { DocumentName result = baseDir.resolve(ExclusionUtils.convertSeparator(pth, "/", baseDir.getDirectorySeparator())); - DocumentName mocked = Mockito.spy(result); + DocumentName mocked = spy(result); String fn = result.localized(FileSystems.getDefault().getSeparator()); File file = tempDir.resolve(fn.substring(1)).toFile(); @@ -91,7 +92,7 @@ private DocumentName mkName(DocumentName baseDir, String pth) throws IOException if (!file.createNewFile()) { fail(() -> "Unable to create file: " + file); } - Mockito.when(mocked.asFile()).thenReturn(file); + when(mocked.asFile()).thenReturn(file); return mocked; } diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java index afeee56b2..67c49daf6 100644 --- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java +++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java @@ -441,7 +441,7 @@ protected void executeReport(final Locale locale) throws MavenReportException { config.reportExclusions(logWriter); } ByteArrayOutputStream baos = new ByteArrayOutputStream(); - config.setOut(new ReportConfiguration.IODescriptor("RAT output", () -> baos)); + config.setOut(new ReportConfiguration.IODescriptor<>("RAT output", () -> baos)); Reporter reporter = new Reporter(config); Reporter.Output output = reporter.execute(); if (verbose) { diff --git a/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Report.java b/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Report.java index 3249452e3..e43990340 100644 --- a/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Report.java +++ b/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Report.java @@ -29,7 +29,6 @@ import org.apache.commons.cli.Option; import org.apache.commons.io.filefilter.IOFileFilter; -import org.apache.commons.io.output.CloseShieldOutputStream; import org.apache.rat.ConfigurationException; import org.apache.rat.DeprecationReporter; import org.apache.rat.ImplementationException; @@ -446,7 +445,7 @@ public void execute() { ReportConfiguration config = validate(getConfiguration()); Reporter r = new Reporter(config); Reporter.Output output = r.execute(); - output.format(StyleSheets.PLAIN.getStyleSheet().ioSupplier(), () -> CloseShieldOutputStream.wrap(System.out)); + output.format(StyleSheets.PLAIN.getStyleSheet().ioSupplier(), ReportConfiguration.SYSTEM_OUT.ioSupplier()); output.format(config); } catch (BuildException e) { throw e; From 2ad3adcd014a4d768b8266207fb968c04fd95435 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Tue, 7 Jul 2026 09:06:18 +0100 Subject: [PATCH 05/17] fix sonarqube issues --- apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java index 9afcc622f..d535c3588 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java @@ -51,11 +51,9 @@ import org.apache.rat.api.Document.Type; import org.apache.rat.api.RatException; import org.apache.rat.commandline.ArgumentContext; -import org.apache.rat.commandline.StyleSheets; import org.apache.rat.document.FileDocument; import org.apache.rat.document.DocumentName; import org.apache.rat.license.ILicenseFamily; -import org.apache.rat.license.LicenseSetFactory; import org.apache.rat.report.claim.ClaimStatistic; import org.apache.rat.test.utils.Resources; import org.apache.rat.testhelpers.TextUtils; From 0fcd7da248bcbc40e841621498ada28e52f0309d Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Tue, 7 Jul 2026 17:09:04 +0100 Subject: [PATCH 06/17] cleaned up code --- .../config/exclusion/ExclusionProcessor.java | 36 +++----- .../rat/report/claim/ClaimStatistic.java | 24 ++--- .../apache/rat/utils/StandardXmlFactory.java | 8 +- .../test/java/org/apache/rat/OutputTest.java | 92 +++++++++++++++++++ .../java/org/apache/rat/ReporterTest.java | 27 ++++++ .../exclusion/ExclusionProcessorTest.java | 22 +++++ .../rat/report/claim/ClaimStatisticTest.java | 28 +++--- .../rat/utils/StandardXmlFactoryTests.java | 40 +++++++- 8 files changed, 222 insertions(+), 55 deletions(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java index 05844d1a0..77b1500be 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java @@ -448,39 +448,33 @@ public void deserialize(final Node xmlNode) { for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); Map attributes = XMLConfigurationReader.attributes(child); - StandardCollection collection; switch (child.getNodeName()) { - case "excludedPattern": + case "excludedPattern" -> excludedPatterns.add(attributes.get(PATTERN)); - break; - case "excludedCollection": - collection = StandardCollection.valueOf(attributes.get(NAME)); - excludedCollections.add(collection); - break; - case "excludedPath": + + case "excludedCollection" -> + excludedCollections.add(StandardCollection.valueOf(attributes.get(NAME))); + + case "excludedPath" -> excludedPaths.add(new DocumentNameMatcher(attributes.get(NAME), (Predicate) x -> { throw new NotImplementedException("Deserialized ExclusionProcessor can not evaluate paths"); })); - break; - case "includedPattern": + + case "includedPattern" -> includedPatterns.add(attributes.get(PATTERN)); - break; - case "includedCollection": - collection = StandardCollection.valueOf(attributes.get(NAME)); - includedCollections.add(collection); - break; - case "includedPath": + + case "includedCollection" -> + includedCollections.add(StandardCollection.valueOf(attributes.get(NAME))); + + case "includedPath" -> includedPaths.add(new DocumentNameMatcher(attributes.get(NAME), (Predicate) x -> { throw new NotImplementedException("Deserialized ExclusionProcessor can not evaluate paths"); })); - break; - case "fileProcessor": + + case "fileProcessor" -> fileProcessors.add(StandardCollection.valueOf(attributes.get(NAME))); - break; - default: - throw new NotImplementedException(String.format("Deserialization for `%s` is not implemented", child.getNodeName())); } } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java index 38b538eec..8b0687df6 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java @@ -190,24 +190,12 @@ public List getDocumentTypes() { public void incCounter(final Document.Type documentType, final int value) { documentTypeMap.compute(documentType, (k, v) -> updateCounter(Counter.DOCUMENT_TYPES, v, value)); switch (documentType) { - case STANDARD: - incCounter(Counter.STANDARDS, value); - break; - case ARCHIVE: - incCounter(Counter.ARCHIVES, value); - break; - case BINARY: - incCounter(Counter.BINARIES, value); - break; - case NOTICE: - incCounter(Counter.NOTICES, value); - break; - case UNKNOWN: - incCounter(Counter.UNKNOWN, value); - break; - case IGNORED: - incCounter(Counter.IGNORED, value); - break; + case STANDARD -> incCounter(Counter.STANDARDS, value); + case ARCHIVE -> incCounter(Counter.ARCHIVES, value); + case BINARY -> incCounter(Counter.BINARIES, value); + case NOTICE -> incCounter(Counter.NOTICES, value); + case UNKNOWN -> incCounter(Counter.UNKNOWN, value); + case IGNORED -> incCounter(Counter.IGNORED, value); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java b/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java index eeee73432..753a0a829 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java @@ -37,6 +37,7 @@ import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import org.apache.commons.lang3.StringUtils; import org.w3c.dom.Document; /** @@ -123,8 +124,9 @@ public static void writeDocument(final Document document, final File file) throw public static String serializeDocument(final Document document) throws TransformerException { DOMSource source = new DOMSource(document); StringWriter writer = new StringWriter(); - StreamResult result = new StreamResult(writer); - createTransformer().transform(source, result); - return writer.toString(); + StreamResult sink = new StreamResult(writer); + createTransformer().transform(source, sink); + String result = writer.toString(); + return StringUtils.defaultIfBlank(result, ""); } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java b/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java index ecfe42ee9..29113405c 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java @@ -18,6 +18,8 @@ */ package org.apache.rat; +import org.apache.commons.io.function.IOSupplier; +import org.apache.rat.api.RatException; import org.apache.rat.commandline.StyleSheets; import org.apache.rat.config.AddLicenseHeaders; import org.apache.rat.config.exclusion.StandardCollection; @@ -31,6 +33,7 @@ import org.apache.rat.test.utils.Resources; import org.apache.rat.testhelpers.FileUtils; import org.apache.rat.utils.StandardXmlFactory; +import org.apache.rat.utils.StandardXmlFactoryTests; import org.apache.rat.walker.DirectoryWalker; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -45,6 +48,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.net.URISyntaxException; @@ -54,6 +58,7 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; class OutputTest { @@ -117,6 +122,43 @@ void stasticReadingTest() throws IOException { ClaimStatisticTest.assertSame(output.getStatistic(), underTest); } + @Test + void readingBadFileTestTest() throws IOException, URISyntaxException, SAXException { + Path testPath = tempPath.resolve("stasticReadingBadFileTest"); + File testFile = testPath.toFile(); + FileUtils.mkDir(testFile); + DocumentName workingDirectory = DocumentName.builder(testPath.toFile()).setBaseName(testFile).build(); + DocumentName documentFile = workingDirectory.resolve("statistic.xml"); + Reporter.Output.Builder builder = Reporter.Output.builder(); + assertThatThrownBy(() -> builder.statistic(documentFile.getName(), workingDirectory)) + .isInstanceOf(ConfigurationException.class) + .hasMessageContaining("Unable to read file: " + testPath.resolve("statistic.xml")); + } + + @Test + void ReadingBadFileTest() throws IOException, URISyntaxException, SAXException { + Path testPath = tempPath.resolve("stasticReadingBadFileTest"); + File testFile = testPath.toFile(); + FileUtils.mkDir(testFile); + DocumentName workingDirectory = DocumentName.builder(testPath.toFile()).setBaseName(testFile).build(); + DocumentName documentFile = workingDirectory.resolve("missing.file"); + Reporter.Output.Builder builder = Reporter.Output.builder(); + assertThatThrownBy(() -> builder.configuration(documentFile.getName(), workingDirectory)) + .as("statistic read") + .isInstanceOf(ConfigurationException.class) + .hasMessageContaining("Unable to read file: " + testPath.resolve("missing.file")); + + assertThatThrownBy(() -> builder.configuration(documentFile.getName(), workingDirectory)) + .as("configuration read") + .isInstanceOf(ConfigurationException.class) + .hasMessageContaining("Unable to read file: " + testPath.resolve("missing.file")); + + assertThatThrownBy(() -> builder.document(documentFile.getName(), workingDirectory)) + .as("document read") + .isInstanceOf(ConfigurationException.class) + .hasMessageContaining("Unable to read file: " + testPath.resolve("missing.file")); + } + @Test void configurationReadingTest() throws IOException { Path testPath = tempPath.resolve("configurationReading"); @@ -198,7 +240,57 @@ void listLicensesReportTest() throws Exception { output.listLicenses(printWriter, LicenseSetFactory.LicenseFilter.ALL); } assertThat(writer.toString()).contains("Licenses (ALL):"); + } + + @Test + void formatTest() throws URISyntaxException, IOException, SAXException { + Reporter.Output output = Reporter.Output.builder() + .statistic(new ClaimStatistic()) + .document(StandardXmlFactoryTests.simpleDocument()) + .configuration(new ReportConfiguration()) + .build(); + + IOSupplier badStyleSheet = () -> new InputStream() { + @Override + public int read() throws IOException { + throw new IOException("Expected exception."); + } + }; + assertThatThrownBy(() -> output.format(badStyleSheet, ReportConfiguration.SYSTEM_OUT.ioSupplier())) + .as("badStyleSheet") + .isInstanceOf(RatException.class) + .hasMessageContaining("Expected exception") + .hasCauseInstanceOf(TransformerException.class); + + IOSupplier missingStyleSheet = () -> {throw new IOException("Expected exception.");}; + + + assertThatThrownBy(() -> output.format(missingStyleSheet, ReportConfiguration.SYSTEM_OUT.ioSupplier())) + .as("missingStyleSheet") + .isInstanceOf(RatException.class) + .hasMessageContaining("Expected exception") + .hasCauseInstanceOf(IOException.class); + + IOSupplier badOutput = () -> new OutputStream() { + @Override + public void write(int b) throws IOException { + throw new IOException("Expected exception."); + } + }; + assertThatThrownBy(() -> output.format(StyleSheets.XML.getStyleSheet().ioSupplier(), badOutput)) + .as("badOutput") + .isInstanceOf(RatException.class) + .hasMessageContaining("Expected exception") + .hasCauseInstanceOf(TransformerException.class); + + IOSupplier missingOutput = () -> {throw new IOException("Expected exception.");}; + assertThatThrownBy(() -> output.format(StyleSheets.XML.getStyleSheet().ioSupplier(), missingOutput)) + .as("missingOutput") + .isInstanceOf(RatException.class) + .hasMessageContaining("Expected exception") + .hasCauseInstanceOf(IOException.class); } + } diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java index d535c3588..e3c1695e1 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java @@ -35,6 +35,7 @@ import java.util.TreeMap; import javax.xml.XMLConstants; import javax.xml.transform.Source; +import javax.xml.transform.TransformerException; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; @@ -55,9 +56,11 @@ import org.apache.rat.document.DocumentName; import org.apache.rat.license.ILicenseFamily; import org.apache.rat.report.claim.ClaimStatistic; +import org.apache.rat.report.claim.ClaimStatisticTest; import org.apache.rat.test.utils.Resources; import org.apache.rat.testhelpers.TextUtils; import org.apache.rat.testhelpers.XmlUtils; +import org.apache.rat.utils.StandardXmlFactory; import org.apache.rat.walker.DirectoryWalker; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -132,6 +135,18 @@ void testExecute() throws RatException, ParseException { assertThat(actual).isEqualTo(expected); } + @Test + void testExecuteNoSource() throws ParseException, RatException, TransformerException { + File output = new File(tempDirectory, "testExecuteNoSource"); + + CommandLine cl = new DefaultParser().parse(OptionCollection.buildOptions(), new String[]{"--output-style", "xml", "--output-file", output.getPath()}); + ArgumentContext ctxt = new ArgumentContext(new File("."), cl); + ReportConfiguration config = OptionCollection.createConfiguration(ctxt); + Reporter.Output result = new Reporter(config).execute(); + assertThat(StandardXmlFactory.serializeDocument(result.getDocument())).isEmpty(); + ClaimStatisticTest.assertSame(result.getStatistic(), new ClaimStatistic()); + } + @Test void testOutputOption() throws Exception { File output = new File(tempDirectory, "test"); @@ -147,6 +162,18 @@ void testOutputOption() throws Exception { assertThat(content).contains("/sub/Empty.txt"); } + @Test + void testGetOutputMethod() throws Exception { + File output = new File(tempDirectory, "test"); + CommandLine commandLine = new DefaultParser().parse(OptionCollection.buildOptions(), new String[]{"-o", output.getCanonicalPath(), basedir}); + ArgumentContext ctxt = new ArgumentContext(new File("."), commandLine); + + ReportConfiguration config = OptionCollection.createConfiguration(ctxt); + Reporter reporter = new Reporter(config); + Reporter.Output expected = reporter.execute(); + assertThat(reporter.getOutput()).isEqualTo(expected); + } + @Test void testDefaultOutput() throws Exception { File output = new File(tempDirectory, "testDefaultOutput"); diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java index 066d9b623..cf9d1c795 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java @@ -325,6 +325,28 @@ void addNullIncludedPatternTest() { assertThat(underTest.getIncludedPatterns()).containsExactly("hello/world"); } + @Test + void addNullIncludedCollectionTest() { + ExclusionProcessor underTest = new ExclusionProcessor(); + assertThat(underTest.getIncludedCollections()).isEmpty(); + underTest.addIncludedCollection(null); + assertThat(underTest.getIncludedCollections()).isEmpty(); + underTest.addIncludedCollection(StandardCollection.HIDDEN_FILE) + .addIncludedCollection(null); + assertThat(underTest.getIncludedCollections()).containsExactly(StandardCollection.HIDDEN_FILE); + } + + @Test + void addNullExcludedCollectionTest() { + ExclusionProcessor underTest = new ExclusionProcessor(); + assertThat(underTest.getExcludedCollections()).isEmpty(); + underTest.addExcludedCollection(null); + assertThat(underTest.getExcludedCollections()).isEmpty(); + underTest.addExcludedCollection(StandardCollection.HIDDEN_FILE) + .addExcludedCollection(null); + assertThat(underTest.getExcludedCollections()).containsExactly(StandardCollection.HIDDEN_FILE); + } + @Test void addNullExcludedPatternTest() { ExclusionProcessor underTest = new ExclusionProcessor(); diff --git a/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java b/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java index ef8a31e2c..b44f0e189 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java @@ -32,23 +32,27 @@ public class ClaimStatisticTest { @Test void counterTests() { ClaimStatistic underTest = new ClaimStatistic(); - assertThat(underTest.getCounter(ClaimStatistic.Counter.APPROVED)).isZero(); - underTest.incCounter(ClaimStatistic.Counter.APPROVED, 1); - assertThat(underTest.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(1); - underTest.incCounter(ClaimStatistic.Counter.APPROVED, -2); - assertThat(underTest.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(-1); - underTest.setCounter(ClaimStatistic.Counter.APPROVED, Integer.MAX_VALUE); - assertThat(underTest.getCounter(ClaimStatistic.Counter.APPROVED)).isEqualTo(Integer.MAX_VALUE); + for (ClaimStatistic.Counter counter : ClaimStatistic.Counter.values()) { + assertThat(underTest.getCounter(counter)).isZero(); + underTest.incCounter(counter, 1); + assertThat(underTest.getCounter(counter)).isEqualTo(1); + underTest.incCounter(counter, -2); + assertThat(underTest.getCounter(counter)).isEqualTo(-1); + underTest.setCounter(counter, Integer.MAX_VALUE); + assertThat(underTest.getCounter(counter)).isEqualTo(Integer.MAX_VALUE); + } } @Test void typeTests() { ClaimStatistic underTest = new ClaimStatistic(); - assertThat(underTest.getCounter(Document.Type.NOTICE)).isZero(); - underTest.incCounter(Document.Type.NOTICE, 1); - assertThat(underTest.getCounter(Document.Type.NOTICE)).isEqualTo(1); - underTest.incCounter(Document.Type.NOTICE, -2); - assertThat(underTest.getCounter(Document.Type.NOTICE)).isEqualTo(-1); + for (Document.Type docType : Document.Type.values()) { + assertThat(underTest.getCounter(docType)).isZero(); + underTest.incCounter(docType, 1); + assertThat(underTest.getCounter(docType)).isEqualTo(1); + underTest.incCounter(docType, -2); + assertThat(underTest.getCounter(docType)).isEqualTo(-1); + } } @Test diff --git a/apache-rat-core/src/test/java/org/apache/rat/utils/StandardXmlFactoryTests.java b/apache-rat-core/src/test/java/org/apache/rat/utils/StandardXmlFactoryTests.java index bfffac4fa..85731a4f2 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/utils/StandardXmlFactoryTests.java +++ b/apache-rat-core/src/test/java/org/apache/rat/utils/StandardXmlFactoryTests.java @@ -18,14 +18,22 @@ */ package org.apache.rat.utils; +import org.apache.rat.report.xml.writer.XmlWriter; import org.junit.jupiter.api.Test; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.InputStream; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -33,7 +41,25 @@ /** * Tests for StandardXmlFactory. */ -class StandardXmlFactoryTests { +public class StandardXmlFactoryTests { + + public static final String SIMPLE_DOCUMENT_TEXT = """ + + + + """; + + public static Document simpleDocument() throws IOException, SAXException { + StringWriter writer = new StringWriter(); + try (XmlWriter xmlWriter = new XmlWriter(writer)) { + xmlWriter.startDocument().startElement("first") + .startElement("second") + .attribute("attr1", "one") + .closeDocument(); + } + return StandardXmlFactory.documentBuilder() + .parse(new ByteArrayInputStream(writer.toString().getBytes(StandardCharsets.UTF_8))); + } @Test void noArg() throws TransformerConfigurationException { @@ -64,6 +90,18 @@ void goodDocumentBuilderTest() { .isNotNull(); } + @Test + void serializeDocumentTest() throws IOException, SAXException, TransformerException { + String result = StandardXmlFactory.serializeDocument(simpleDocument()); + assertThat(result).isEqualTo(SIMPLE_DOCUMENT_TEXT); + } + + @Test + void serializeEmptyDocumentYieldsEmtpyString() throws TransformerException { + Document document = StandardXmlFactory.documentBuilder().newDocument(); + assertThat(StandardXmlFactory.serializeDocument(document)).isEmpty(); + } + /** * Class to test failing document builder. */ From efedd1e5261eef6ddb4cade2667be044c5655862 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Thu, 9 Jul 2026 16:43:14 +0100 Subject: [PATCH 07/17] cleaned up sonarqube --- .../org/apache/rat/ReportConfiguration.java | 5 ++-- .../main/java/org/apache/rat/Reporter.java | 3 +- .../config/exclusion/ExclusionProcessor.java | 3 ++ .../apache/rat/utils/StandardXmlFactory.java | 5 +++- .../test/java/org/apache/rat/OutputTest.java | 30 ++++++------------- 5 files changed, 20 insertions(+), 26 deletions(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java index e434065f3..7207e51cd 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java +++ b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java @@ -43,6 +43,7 @@ import javax.xml.parsers.DocumentBuilder; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.collections4.set.UnmodifiableSortedSet; import org.apache.commons.io.function.IOSupplier; import org.apache.commons.io.output.CloseShieldOutputStream; @@ -954,6 +955,7 @@ static IODescriptor input(final File file) { * Deserialized ReportConfigurations can not be executed as the reportable objects a simply named placeholders * and do not have access to the original object. */ + @SuppressFBWarnings("EI_EXPOSE_REP2") public class Serde { /** * Writes the configuration as an XML document to the appendable. @@ -1006,10 +1008,9 @@ public void serialize(final Appendable appendable) throws IOException { } public void deserialize(final IOSupplier inputStreamSupplier, final DocumentName workingDirectory) throws IOException { - DocumentBuilder builder = StandardXmlFactory.documentBuilder(); org.w3c.dom.Document document; try (InputStream stream = inputStreamSupplier.get()) { - document = builder.parse(stream); + document = StandardXmlFactory.documentBuilder().parse(stream); } catch (SAXException e) { throw new IOException("Unable to read input", e); } diff --git a/apache-rat-core/src/main/java/org/apache/rat/Reporter.java b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java index 42fa52d73..0b5f3fdce 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/Reporter.java +++ b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java @@ -264,10 +264,9 @@ public Builder document(final Document document) { } public Builder document(final String fileName, final DocumentName workingDirectory) { - DocumentBuilder builder = StandardXmlFactory.documentBuilder(); File inputFile = workingDirectory.resolve(fileName).asFile(); try (InputStream inputStream = new FileInputStream(inputFile)) { - this.document = builder.parse(inputStream); + this.document = StandardXmlFactory.documentBuilder().parse(inputStream); } catch (SAXException | IOException e) { throw new ConfigurationException("Unable to read file: " + inputFile, e); } diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java index 77b1500be..37b60ef14 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java @@ -475,6 +475,9 @@ public void deserialize(final Node xmlNode) { case "fileProcessor" -> fileProcessors.add(StandardCollection.valueOf(attributes.get(NAME))); + + default -> + DefaultLog.getInstance().error(String.format("Unknown child node '%s'", child.getNodeName())); } } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java b/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java index 753a0a829..0539d78b7 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; +import java.nio.charset.StandardCharsets; import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; @@ -37,6 +38,7 @@ import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.lang3.StringUtils; import org.w3c.dom.Document; @@ -72,6 +74,7 @@ public static Transformer createTransformer() throws TransformerConfigurationExc * @return the transformer. * @throws TransformerConfigurationException on error. */ + @SuppressFBWarnings("MALICIOUS_XSLT") public static Transformer createTransformer(final InputStream styleIn) throws TransformerConfigurationException { TransformerFactory factory = TransformerFactory.newInstance(); // NOSONAR factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); @@ -112,7 +115,7 @@ public static DocumentBuilder documentBuilder() { */ public static void writeDocument(final Document document, final File file) throws IOException, TransformerException { DOMSource source = new DOMSource(document); - FileWriter writer = new FileWriter(file); + FileWriter writer = new FileWriter(file, StandardCharsets.UTF_8); StreamResult result = new StreamResult(writer); createTransformer().transform(source, result); } diff --git a/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java b/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java index 29113405c..26aebd2f2 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java @@ -96,7 +96,7 @@ void documentReadingTest() throws IOException, SAXException, TransformerExceptio } @Test - void stasticReadingTest() throws IOException { + void statisticReadingTest() throws IOException { Path testPath = tempPath.resolve("statisticReading"); File testFile = testPath.toFile(); FileUtils.mkDir(testFile); @@ -104,7 +104,7 @@ void stasticReadingTest() throws IOException { DocumentName documentFile = workingDirectory.resolve("statistic.xml"); ClaimStatistic underTest = new ClaimStatistic(); - underTest.incLicenseCategoryCount("familyCagegory", 1); + underTest.incLicenseCategoryCount("familyCategory", 1); underTest.incCounter(ClaimStatistic.Counter.APPROVED, 2); underTest.incCounter(org.apache.rat.api.Document.Type.IGNORED, 3); underTest.incLicenseNameCount("licenseName", 4); @@ -123,37 +123,25 @@ void stasticReadingTest() throws IOException { } @Test - void readingBadFileTestTest() throws IOException, URISyntaxException, SAXException { - Path testPath = tempPath.resolve("stasticReadingBadFileTest"); - File testFile = testPath.toFile(); - FileUtils.mkDir(testFile); - DocumentName workingDirectory = DocumentName.builder(testPath.toFile()).setBaseName(testFile).build(); - DocumentName documentFile = workingDirectory.resolve("statistic.xml"); - Reporter.Output.Builder builder = Reporter.Output.builder(); - assertThatThrownBy(() -> builder.statistic(documentFile.getName(), workingDirectory)) - .isInstanceOf(ConfigurationException.class) - .hasMessageContaining("Unable to read file: " + testPath.resolve("statistic.xml")); - } - - @Test - void ReadingBadFileTest() throws IOException, URISyntaxException, SAXException { - Path testPath = tempPath.resolve("stasticReadingBadFileTest"); + void ReadingBadFileTest() { + Path testPath = tempPath.resolve("readingBadFileTest"); File testFile = testPath.toFile(); FileUtils.mkDir(testFile); DocumentName workingDirectory = DocumentName.builder(testPath.toFile()).setBaseName(testFile).build(); DocumentName documentFile = workingDirectory.resolve("missing.file"); + String name = documentFile.getName(); Reporter.Output.Builder builder = Reporter.Output.builder(); - assertThatThrownBy(() -> builder.configuration(documentFile.getName(), workingDirectory)) + assertThatThrownBy(() -> builder.statistic(name, workingDirectory)) .as("statistic read") .isInstanceOf(ConfigurationException.class) .hasMessageContaining("Unable to read file: " + testPath.resolve("missing.file")); - assertThatThrownBy(() -> builder.configuration(documentFile.getName(), workingDirectory)) + assertThatThrownBy(() -> builder.configuration(name, workingDirectory)) .as("configuration read") .isInstanceOf(ConfigurationException.class) .hasMessageContaining("Unable to read file: " + testPath.resolve("missing.file")); - assertThatThrownBy(() -> builder.document(documentFile.getName(), workingDirectory)) + assertThatThrownBy(() -> builder.document(name, workingDirectory)) .as("document read") .isInstanceOf(ConfigurationException.class) .hasMessageContaining("Unable to read file: " + testPath.resolve("missing.file")); @@ -243,7 +231,7 @@ void listLicensesReportTest() throws Exception { } @Test - void formatTest() throws URISyntaxException, IOException, SAXException { + void formatTest() throws IOException, SAXException { Reporter.Output output = Reporter.Output.builder() .statistic(new ClaimStatistic()) .document(StandardXmlFactoryTests.simpleDocument()) From 75d80ca479cc98d238828ed954fc652c7f158067 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Thu, 9 Jul 2026 17:20:30 +0100 Subject: [PATCH 08/17] fixed checkstyle --- .../src/main/java/org/apache/rat/ReportConfiguration.java | 4 +--- apache-rat-core/src/main/java/org/apache/rat/Reporter.java | 1 - .../main/java/org/apache/rat/utils/StandardXmlFactory.java | 3 ++- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java index 7207e51cd..2f853c33c 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java +++ b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java @@ -41,9 +41,6 @@ import java.util.function.Consumer; import java.util.stream.Stream; -import javax.xml.parsers.DocumentBuilder; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.collections4.set.UnmodifiableSortedSet; import org.apache.commons.io.function.IOSupplier; import org.apache.commons.io.output.CloseShieldOutputStream; @@ -77,6 +74,7 @@ import org.w3c.dom.Node; import org.xml.sax.SAXException; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; /** * A configuration object is used by the front end to invoke the diff --git a/apache-rat-core/src/main/java/org/apache/rat/Reporter.java b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java index 0b5f3fdce..06514a85b 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/Reporter.java +++ b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java @@ -28,7 +28,6 @@ import java.io.StringReader; import java.nio.charset.StandardCharsets; -import javax.xml.parsers.DocumentBuilder; import javax.xml.transform.TransformerException; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; diff --git a/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java b/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java index 0539d78b7..c5f917d13 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java @@ -38,10 +38,11 @@ import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.lang3.StringUtils; import org.w3c.dom.Document; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + /** * Factory to create standard XML objects. The intention of this class is to resolve in a consistent manner the * XXE errors and similar XML IO errors. From 97a8d8c2edc48474f1ee0a6cf6822c500450ecdd Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Thu, 9 Jul 2026 17:31:16 +0100 Subject: [PATCH 09/17] fixed new line issue --- .../test/java/org/apache/rat/utils/StandardXmlFactoryTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apache-rat-core/src/test/java/org/apache/rat/utils/StandardXmlFactoryTests.java b/apache-rat-core/src/test/java/org/apache/rat/utils/StandardXmlFactoryTests.java index 85731a4f2..28e36a80a 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/utils/StandardXmlFactoryTests.java +++ b/apache-rat-core/src/test/java/org/apache/rat/utils/StandardXmlFactoryTests.java @@ -93,7 +93,7 @@ void goodDocumentBuilderTest() { @Test void serializeDocumentTest() throws IOException, SAXException, TransformerException { String result = StandardXmlFactory.serializeDocument(simpleDocument()); - assertThat(result).isEqualTo(SIMPLE_DOCUMENT_TEXT); + assertThat(result).isEqualToIgnoringNewLines(SIMPLE_DOCUMENT_TEXT); } @Test From b0d2fb790f4dc6fa32cb7c9d33fb562f17208b12 Mon Sep 17 00:00:00 2001 From: "P. Ottlinger" Date: Mon, 13 Jul 2026 23:36:11 +0200 Subject: [PATCH 10/17] RAT-570: Minor refactorings during review --- .../src/main/java/org/apache/rat/Report.java | 2 +- .../org/apache/rat/ReportConfiguration.java | 46 +++++++++++-------- .../main/java/org/apache/rat/Reporter.java | 19 ++++---- .../config/exclusion/ExclusionProcessor.java | 18 ++++---- .../configuration/XMLConfigurationReader.java | 32 ++++++------- .../rat/report/claim/ClaimStatistic.java | 16 +++---- .../apache/rat/utils/StandardXmlFactory.java | 2 +- .../exclusion/ExclusionProcessorTest.java | 3 +- 8 files changed, 71 insertions(+), 67 deletions(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/Report.java b/apache-rat-core/src/main/java/org/apache/rat/Report.java index 3c366fab7..4346951d2 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/Report.java +++ b/apache-rat-core/src/main/java/org/apache/rat/Report.java @@ -66,7 +66,7 @@ public static void main(final String[] args) throws Exception { /** * Prints the usage message on {@code System.out}. - * @param opts The defined options. + * @param opts the defined options. */ private static void printUsage(final Options opts) { new Help(System.out).printUsage(opts); diff --git a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java index 2f853c33c..a822e8b99 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java +++ b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java @@ -100,7 +100,7 @@ public enum Processing { ABSENCE("List licenses found and any unknown licences"); /** - * Description of the processing + * Description of the processing. */ private final String description; @@ -124,19 +124,23 @@ public String desc() { * {@code true} if we are adding license headers to the files. */ private boolean addingLicenses; + /** * {@code true} if we are adding license headers in place (no *.new files) */ private boolean addingLicensesForced; + /** * The copyright message to add if we are adding headers. Will be {@code null} * if we are not adding copyright messages. */ private String copyrightMessage; + /** * The IODescriptor that provides the output stream to write the report to. */ private IODescriptor out; + /** * The IODescriptor that provides the stylesheet to style the XML output. */ @@ -161,22 +165,27 @@ public String desc() { * The default filter for displaying families. */ private LicenseFilter listFamilies; + /** * The default filter for displaying licenses. */ private LicenseFilter listLicenses; + /** * {@code true} if this is a dry run and no processing is to take place. */ private boolean dryRun; + /** * How to process ARCHIVE document types. */ private Processing archiveProcessing; + /** * How to process STANDARD document types. */ private Processing standardProcessing; + /** * The ClaimValidator to validate min/max counts and similar claims. */ @@ -279,7 +288,7 @@ public IHeaderMatcher getGeneratedMatcher() { /** * Retrieves the archive processing type. - * @return The archive processing type. + * @return the archive processing type. */ public Processing getArchiveProcessing() { return archiveProcessing == null ? Defaults.ARCHIVE_PROCESSING : archiveProcessing; @@ -294,16 +303,16 @@ public void setArchiveProcessing(final Processing archiveProcessing) { } /** - * Retrieves the archive processing type. - * @return The archive processing type. + * Retrieves the standard processing type. + * @return the standard processing type. */ public Processing getStandardProcessing() { return standardProcessing == null ? Defaults.STANDARD_PROCESSING : standardProcessing; } /** - * Sets the archive processing type. If not set will default to NOTIFICATION. - * @param standardProcessing the type of processing archives should have. + * Sets the standard processing type. If not set will default to NOTIFICATION. + * @param standardProcessing the type of processing standard files should have. */ public void setStandardProcessing(final Processing standardProcessing) { this.standardProcessing = standardProcessing; @@ -312,7 +321,7 @@ public void setStandardProcessing(final Processing standardProcessing) { /** * Set the log level for reporting collisions in the set of license families. *

NOTE: should be set before licenses or license families are added.

- * @param level The log level to use. + * @param level the log level to use. */ public void logFamilyCollisions(final Level level) { licenseSetFactory.logFamilyCollisions(level); @@ -320,7 +329,7 @@ public void logFamilyCollisions(final Level level) { /** * Sets the reporting option for duplicate license families. - * @param state The ReportingSet.Option to use for reporting. + * @param state the ReportingSet.Option to use for reporting. */ public void familyDuplicateOption(final ReportingSet.Options state) { licenseSetFactory.familyDuplicateOption(state); @@ -328,7 +337,7 @@ public void familyDuplicateOption(final ReportingSet.Options state) { /** * Sets the log level for reporting license collisions. - * @param level The log level. + * @param level the log level. */ public void logLicenseCollisions(final Level level) { licenseSetFactory.logLicenseCollisions(level); @@ -336,7 +345,7 @@ public void logLicenseCollisions(final Level level) { /** * Sets the reporting option for duplicate licenses. - * @param state the ReportingSt.Option to use for reporting. + * @param state the ReportingSet.Option to use for reporting. */ public void licenseDuplicateOption(final ReportingSet.Options state) { licenseSetFactory.licenseDuplicateOption(state); @@ -563,7 +572,7 @@ public void setStyleSheet(final URL styleSheet) { * appended to and that can be closed. If an {@code OutputStream} should not be * closed consider wrapping it in a {@code CloseShieldOutputStream} * @param out the OutputStream supplier that provides the output stream to write - * the report to. A null value will use System.out. + * the report to. A {@code null} value will use {@code System.out}. * @see CloseShieldOutputStream */ public void setOut(final IODescriptor out) { @@ -586,6 +595,7 @@ public void setOut(final File file) { DefaultLog.getInstance().warn("Unable to delete file: " + file); } } + File parent = file.getParentFile(); if (!parent.mkdirs() && !parent.isDirectory()) { DefaultLog.getInstance().warn("Unable to create directory: " + file.getParentFile()); @@ -685,7 +695,7 @@ public void addApprovedLicenseCategory(final ILicenseFamily approvedILicenseFami } /** - * Adds a license family category (id) to the list of approved licenses + * Adds a license family category (id) to the list of approved licenses. * @param familyCategory the category to add. */ public void addApprovedLicenseCategory(final String familyCategory) { @@ -867,8 +877,8 @@ public void setAddLicenseHeaders(final AddLicenseHeaders addLicenseHeaders) { *
  • {@code approved} - Only approved license families will be returned.
  • *
  • {@code none} - No license families will be returned.
  • * - * @param filter The license filter. - * @return The set of defined licenses. + * @param filter the license filter. + * @return the set of defined licenses. */ public SortedSet getLicenseFamilies(final LicenseFilter filter) { return licenseSetFactory.getLicenseFamilies(filter); @@ -911,7 +921,7 @@ public void validate(final Consumer logger) { /** * An IODescriptor comprises a name and an IOSupplier. The name should identify the contents of the stream. * @param name the name of the supplier. - * @param ioSupplier the IOSupplier that provides either an InputStream or an OutputStream + * @param ioSupplier the IOSupplier that provides either an InputStream or an OutputStream. * @param either InputStream or OutputStream. */ public record IODescriptor(String name, IOSupplier ioSupplier) { @@ -949,8 +959,8 @@ static IODescriptor input(final File file) { } /** - * Serializes the ReportConfiguration into an XML document that can be deserialzed by the Serde. - * Deserialized ReportConfigurations can not be executed as the reportable objects a simply named placeholders + * Serializes the ReportConfiguration into an XML document that can be deserialized by the Serde. + * Deserialized ReportConfigurations can not be executed as the reportable objects use named placeholders * and do not have access to the original object. */ @SuppressFBWarnings("EI_EXPOSE_REP2") @@ -1065,7 +1075,7 @@ public void deserialize(final IOSupplier inputStreamSupplier, final } /** - * A record that identifies a deserialized reportable. Deserialized reportables are not executable. + * A record that identifies a deserialized reportable. Deserialized reportables are not executable. * @param name the name of the reportable. */ private record DeserializedReportable(DocumentName name) implements Reportable { diff --git a/apache-rat-core/src/main/java/org/apache/rat/Reporter.java b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java index 06514a85b..31fdbc3c0 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/Reporter.java +++ b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java @@ -57,7 +57,7 @@ public class Reporter { private static final String LICENSE_FORMAT = "%s:\t%s%n\t\t%s%n"; /** - * The configuration for the report + * The configuration for the report. */ private final ReportConfiguration configuration; @@ -122,7 +122,7 @@ public Output getOutput() { */ public static final class Output { /** - * The XML output document + * The XML output document. */ private final Document document; /** @@ -131,7 +131,7 @@ public static final class Output { */ private final ClaimStatistic statistic; /** - * The configuration that generated the document + * The configuration that generated the document. */ private final ReportConfiguration configuration; @@ -175,7 +175,7 @@ public ReportConfiguration getConfiguration() { /** * Formats the report to the output and using the stylesheet found in the report configuration. * - * @param config s RAT report configuration. + * @param config the RAT report configuration. * @throws RatException on error. */ public void format(final ReportConfiguration config) throws RatException { @@ -187,11 +187,10 @@ public void format(final ReportConfiguration config) throws RatException { * 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. + * @param output the output stream to write to. * @throws RatException on error. */ public void format(final IOSupplier stylesheet, final IOSupplier output) throws RatException { - try (OutputStream out = output.get(); InputStream styleIn = stylesheet.get()) { StandardXmlFactory.createTransformer(styleIn).transform(new DOMSource(document), @@ -204,8 +203,8 @@ public void format(final IOSupplier stylesheet, final IOSupplier getExcludedPatterns() { return new HashSet<>(excludedPatterns); } @@ -125,7 +124,7 @@ DocumentName getLastMatcherBaseDir() { } /** - * Reset the {@link #lastMatcher} and {@link #lastMatcherBaseDir} to start again + * Reset the {@link #lastMatcher} and {@link #lastMatcherBaseDir} to start again. */ private void resetLastMatcher() { lastMatcher = null; @@ -133,8 +132,8 @@ private void resetLastMatcher() { } /** - * Add the Iterable of strings to the collection of file/directory patters to ignore. - * @param patterns the patterns to add + * Add the iterable of strings to the collection of file/directory patters to ignore. + * @param patterns the patterns to add. * @return this */ public ExclusionProcessor addIncludedPatterns(final Iterable patterns) { @@ -235,7 +234,7 @@ public void reportExclusions(final Appendable appendable) throws IOException { } for (DocumentNameMatcher nameMatcher : includedPaths) { appendable.append(format("Including %s.%n", nameMatcher.toString())); - } + } } /** @@ -396,7 +395,7 @@ private void extractPaths(final MatcherSet.Builder matcherBuilder) { } /** - * Serializes and deserializes the ExclusionProcessor to XML document + * Serializes and deserializes the ExclusionProcessor to an XML document. */ public class Serde { /** The pattern attribute name */ @@ -436,11 +435,10 @@ public void serialize(final XmlWriter writer) throws IOException { writer.startElement("fileProcessor").attribute(NAME, obj.name()).closeElement(); } writer.closeElement(); - } /** - * Deserialize from XML Document node to ExclusionProcessor + * Deserialize from XML Document node to ExclusionProcessor. * @param xmlNode the node to deserialize from. */ public void deserialize(final Node xmlNode) { @@ -458,7 +456,7 @@ public void deserialize(final Node xmlNode) { case "excludedPath" -> excludedPaths.add(new DocumentNameMatcher(attributes.get(NAME), (Predicate) x -> { - throw new NotImplementedException("Deserialized ExclusionProcessor can not evaluate paths"); + throw new NotImplementedException("Deserialized ExclusionProcessor can not evaluate excluded paths"); })); case "includedPattern" -> @@ -470,7 +468,7 @@ public void deserialize(final Node xmlNode) { case "includedPath" -> includedPaths.add(new DocumentNameMatcher(attributes.get(NAME), (Predicate) x -> { - throw new NotImplementedException("Deserialized ExclusionProcessor can not evaluate paths"); + throw new NotImplementedException("Deserialized ExclusionProcessor can not evaluate included paths"); })); case "fileProcessor" -> diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/XMLConfigurationReader.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/XMLConfigurationReader.java index 04b9fbe45..ba20fd5fd 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/XMLConfigurationReader.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/XMLConfigurationReader.java @@ -123,7 +123,7 @@ public SortedSet licenseFamilies() { /** * Creates textual representation of a node for display. * @param node the node to create the textual representation of. - * @return The textual representation of the node for display. + * @return the textual representation of the node for display. */ private String nodeText(final Node node) { StringBuilder stringBuilder = new StringBuilder().append("<").append(node.getNodeName()); @@ -154,7 +154,7 @@ public void read(final Reader reader) { /** * Read the uris and extract the DOM information to create new objects. - * @param uris The URIs to read. + * @param uris the URIs to read. */ public void read(final URI... uris) { DocumentBuilder builder = StandardXmlFactory.documentBuilder(); @@ -170,7 +170,7 @@ public void read(final URI... uris) { /** * Applies the {@code consumer} to each node in the {@code list}. Generally used for extracting info from a * {@code NodeList}. - * @param list the NodeList to process + * @param list the NodeList to process. * @param consumer the consumer to apply to each node in the list. */ public static void nodeListConsumer(final NodeList list, final Consumer consumer) { @@ -196,7 +196,7 @@ public void add(final Document newDoc) { /** * Get a map of Node attribute names to values. - * @param node The node to process + * @param node the node to process. * @return the map of attributes on the node. */ public static Map attributes(final Node node) { @@ -211,9 +211,9 @@ public static Map attributes(final Node node) { /** * Finds the setter description property in the builder and set it with the value. - * @param desc The description for the setter. - * @param builder The builder to set the value in. - * @param value The value to set. + * @param desc the description for the setter. + * @param builder the builder to set the value in. + * @param value the value to set. */ private void callSetter(final Description desc, final IHeaderMatcher.Builder builder, final Object value) { try { @@ -226,7 +226,7 @@ private void callSetter(final Description desc, final IHeaderMatcher.Builder bui /** * For any children of description that are BUILD_PARAMETERS set the builder property. - * @param description The description for the builder. + * @param description the description for the builder. * @param builder the builder to set the properties in. */ private void processBuilderParams(final Description description, final IHeaderMatcher.Builder builder) { @@ -245,7 +245,7 @@ private void processBuilderParams(final Description description, final IHeaderMa * of the child (if any) to the BiPredicate. If there is not a child description * for the node it is ignored. If the node is processed it is removed from list * of children. - * @param description the Description of the node being processed + * @param description the description of the node being processed. * @param children the child nodes of that node. * @param childProcessor the function that handles the processing of the child * node. @@ -266,7 +266,7 @@ private void processChildren(final Description description, final List chi /** * Creates a child node processor for the builder described by the description. - * @param builder The builder to set properties in. + * @param builder the builder to set properties in. * @param description the description of the builder. * @return child node. */ @@ -315,11 +315,11 @@ private void setValue(final Description description, final Description childDesc * Process the ELEMENT_NODEs children of the parent whose names match child * descriptions. All children of children are processed with the childProcessor. If * the childProcessor handles the node it is not included in the resulting list. - * @param description the Description of the parent node. - * @param parent the node being processed + * @param description the description of the parent node. + * @param parent the node being processed. * @param childProcessor the BiProcessor to handle process each child. If the * processor handles the child it must return {@code true}. - * @return A Pair comprising a boolean flag indicating children were found, and + * @return a Pair comprising a boolean flag indicating children were found, and * a list of all child nodes that were not processed by the childProcessor. */ private Pair> processChildNodes(final Description description, final Node parent, @@ -350,7 +350,7 @@ private Pair> processChildNodes(final Description descriptio /** * Creates a Builder from a Matcher node. * @param matcherNode the Matcher node to parse. - * @return The Builder for the matcher described by the node. + * @return the Builder for the matcher described by the node. */ private AbstractBuilder parseMatcher(final Node matcherNode) { final AbstractBuilder builder = MatcherBuilderTracker.getMatcherBuilder(matcherNode.getNodeName()); @@ -391,7 +391,6 @@ private AbstractBuilder parseMatcher(final Node matcherNode) { iter.remove(); } } - } else { processChildren(description, children, (child, childD) -> { if (childD.getChildType().equals(description.getChildType())) { @@ -401,7 +400,6 @@ private AbstractBuilder parseMatcher(final Node matcherNode) { return false; }); } - } if (!children.isEmpty()) { @@ -421,7 +419,7 @@ private BiPredicate licenseChildNodeProcessor(final ILicense. switch (childDescription.getType()) { case LICENSE: throw new ConfigurationException(String.format( - "%s may not be enclosed in another license. %s '%s' found in '%s'", childDescription.getType(), + "%s may not be enclosed in another license. %s '%s' found in '%s'", childDescription.getType(), childDescription.getType(), childDescription.getCommonName(), description.getCommonName())); case BUILD_PARAMETER: break; diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java index 8b0687df6..5bd6418b4 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java @@ -127,7 +127,7 @@ public Serde serde() { return new Serde(); } /** - * Converts null counter to 0. + * Converts {@code null} counter to 0. * * @param counter the Counter to retrieve the value from. * @return 0 if counter is {@code null} or counter value otherwise. @@ -218,10 +218,10 @@ public int getLicenseNameCount(final String licenseName) { } /** - * Updates the intCounter with the value and if the intCounter was null creates a new one and registers the + * Updates the intCounter with the value and if the intCounter was {@code null} creates a new one and registers the * creation as a counter type. * @param counter the Type of the counter. - * @param intCounter the IntCounter to update. May be null. + * @param intCounter the IntCounter to update. May be {@code null}. * @param value the value to add to the int counter. * @return the intCounter if it was not {@code null}, a new IntCounter otherwise. */ @@ -306,17 +306,17 @@ public String toString() { } /** - * Serialze and deserialze the claim Statistic. + * Serialize and deserialize the claim Statistic. */ public class Serde { - /** The count attribute string */ + /** The count attribute string. */ private static final String COUNT = "count"; - /** the name attribute string */ + /** The name attribute string. */ private static final String NAME = "name"; /** * Serializes the claim statistic into an appendable. - * @param appendable the appendable to write to + * @param appendable the appendable to write to. * @throws IOException on error. */ public void serialize(final Appendable appendable) throws IOException { @@ -369,9 +369,9 @@ public void serialize(final Appendable appendable) throws IOException { public void deserialize(final IOSupplier inputStreamSupplier) throws IOException { DocumentBuilder builder = StandardXmlFactory.documentBuilder(); org.w3c.dom.Document document; + try (InputStream stream = inputStreamSupplier.get()) { document = builder.parse(stream); - } catch (SAXException e) { throw new IOException("Unable to read input", e); } diff --git a/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java b/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java index c5f917d13..b6a0339e8 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/utils/StandardXmlFactory.java @@ -111,7 +111,7 @@ public static DocumentBuilder documentBuilder() { /** * Write an XML document to a file. - * @param document the document to write + * @param document the document to write. * @param file the file to write to. */ public static void writeDocument(final Document document, final File file) throws IOException, TransformerException { diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java index cf9d1c795..4d6307388 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java @@ -368,7 +368,7 @@ public static void assertSame(ExclusionProcessor actual, ExclusionProcessor expe assertThat(actual.getExcludedPatterns()).containsExactlyElementsOf(expected.getExcludedPatterns()); assertThat(actual.getIncludedPatterns()).containsExactlyElementsOf(expected.getIncludedPatterns()); - // paths only match on name. deserialized paths are not functional. + // Paths only match on name. Deserialized paths are not functional. List actualPaths = actual.getExcludedPaths().stream().map(DocumentNameMatcher::toString).toList(); List expectedPaths = expected.getExcludedPaths().stream().map(DocumentNameMatcher::toString).toList(); assertThat(actualPaths).as("excluded paths").containsExactlyElementsOf(expectedPaths); @@ -402,7 +402,6 @@ static List serdeTestData() { tests.add(new ExclusionProcessor() .addExcludedCollection(StandardCollection.BAZAAR)); - tests.add(new ExclusionProcessor() .addExcludedMatcher(DocumentNameMatcher.MATCHES_ALL)); From 6cd8be13935dc8770fdad25d77df541babf3a034 Mon Sep 17 00:00:00 2001 From: "P. Ottlinger" Date: Mon, 13 Jul 2026 23:40:17 +0200 Subject: [PATCH 11/17] RAT-570: Add changelog --- src/changes/changes.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 6d37b83a5..0beb59be3 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -68,6 +68,9 @@ in order to be properly linked in site reports. --> + + Internal change: Introduced a Reporter.Output class that encapsulates the execution configuration, the generated XML document, and the ClaimStatistic containing counts for file types, licenses, license categories, and other all of RAT run statistics. + Internal change to prepare a better UI testing: create and utilize an IODescriptor that will have a name associated with the current IOSupplier that is in use. From 75f706558ea8ccbfbf0ee4905632f74c33376343 Mon Sep 17 00:00:00 2001 From: "P. Ottlinger" Date: Tue, 14 Jul 2026 17:29:08 +0200 Subject: [PATCH 12/17] RAT-570: minor refactorings during review --- .../src/test/java/org/apache/rat/OutputTest.java | 8 +++----- .../test/java/org/apache/rat/ReportConfigurationTest.java | 2 +- .../org/apache/rat/report/claim/ClaimStatisticTest.java | 5 ++--- .../utils/{CasedStringTests.java => CasedStringTest.java} | 2 +- ...rdXmlFactoryTests.java => StandardXmlFactoryTest.java} | 4 ++-- 5 files changed, 9 insertions(+), 12 deletions(-) rename apache-rat-core/src/test/java/org/apache/rat/utils/{CasedStringTests.java => CasedStringTest.java} (99%) rename apache-rat-core/src/test/java/org/apache/rat/utils/{StandardXmlFactoryTests.java => StandardXmlFactoryTest.java} (97%) diff --git a/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java b/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java index 26aebd2f2..4cf313d3a 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java @@ -33,7 +33,7 @@ import org.apache.rat.test.utils.Resources; import org.apache.rat.testhelpers.FileUtils; import org.apache.rat.utils.StandardXmlFactory; -import org.apache.rat.utils.StandardXmlFactoryTests; +import org.apache.rat.utils.StandardXmlFactoryTest; import org.apache.rat.walker.DirectoryWalker; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -123,7 +123,7 @@ void statisticReadingTest() throws IOException { } @Test - void ReadingBadFileTest() { + void readingBadFileTest() { Path testPath = tempPath.resolve("readingBadFileTest"); File testFile = testPath.toFile(); FileUtils.mkDir(testFile); @@ -234,7 +234,7 @@ void listLicensesReportTest() throws Exception { void formatTest() throws IOException, SAXException { Reporter.Output output = Reporter.Output.builder() .statistic(new ClaimStatistic()) - .document(StandardXmlFactoryTests.simpleDocument()) + .document(StandardXmlFactoryTest.simpleDocument()) .configuration(new ReportConfiguration()) .build(); @@ -279,6 +279,4 @@ public void write(int b) throws IOException { .hasCauseInstanceOf(IOException.class); } - - } diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java index f289b6283..9d07ec3e4 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java @@ -845,7 +845,7 @@ public void close() { } /** - * A reportable that only reports its name. Does no actual work. + * A reportable that only reports its name. Does no actual work. */ static class TestingReportable implements Reportable { diff --git a/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java b/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java index b44f0e189..611a67e3d 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java @@ -110,11 +110,10 @@ void licenseFamilyNameTest() { /** * Compares two claim statistics for similarity after serialization/deserialization. - * @param actual the deserialized verison. + * @param actual the deserialized version. * @param expected the original version. */ public static void assertSame(final ClaimStatistic actual, final ClaimStatistic expected) { - assertThat(actual.getLicenseFamilyCategories()).containsExactlyElementsOf(expected.getLicenseFamilyCategories()); assertThat(actual.getLicenseNames()).containsExactlyElementsOf(expected.getLicenseNames()); assertThat(actual.getDocumentTypes()).containsExactlyElementsOf(expected.getDocumentTypes()); @@ -135,7 +134,7 @@ public static void assertSame(final ClaimStatistic actual, final ClaimStatistic @Test void serdeRoundTrip() throws IOException { ClaimStatistic underTest = new ClaimStatistic(); - underTest.incLicenseCategoryCount("familyCagegory", 1); + underTest.incLicenseCategoryCount("familyCategory", 1); underTest.incCounter(ClaimStatistic.Counter.APPROVED, 2); underTest.incCounter(Document.Type.IGNORED, 3); underTest.incLicenseNameCount("licenseName", 4); diff --git a/apache-rat-core/src/test/java/org/apache/rat/utils/CasedStringTests.java b/apache-rat-core/src/test/java/org/apache/rat/utils/CasedStringTest.java similarity index 99% rename from apache-rat-core/src/test/java/org/apache/rat/utils/CasedStringTests.java rename to apache-rat-core/src/test/java/org/apache/rat/utils/CasedStringTest.java index f69c11600..93738568a 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/utils/CasedStringTests.java +++ b/apache-rat-core/src/test/java/org/apache/rat/utils/CasedStringTest.java @@ -29,7 +29,7 @@ import static org.assertj.core.api.Assertions.assertThat; -class CasedStringTests { +class CasedStringTest { @MethodSource("testSegmentationData") @ParameterizedTest diff --git a/apache-rat-core/src/test/java/org/apache/rat/utils/StandardXmlFactoryTests.java b/apache-rat-core/src/test/java/org/apache/rat/utils/StandardXmlFactoryTest.java similarity index 97% rename from apache-rat-core/src/test/java/org/apache/rat/utils/StandardXmlFactoryTests.java rename to apache-rat-core/src/test/java/org/apache/rat/utils/StandardXmlFactoryTest.java index 28e36a80a..0414ebe7c 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/utils/StandardXmlFactoryTests.java +++ b/apache-rat-core/src/test/java/org/apache/rat/utils/StandardXmlFactoryTest.java @@ -41,7 +41,7 @@ /** * Tests for StandardXmlFactory. */ -public class StandardXmlFactoryTests { +public class StandardXmlFactoryTest { public static final String SIMPLE_DOCUMENT_TEXT = """ @@ -97,7 +97,7 @@ void serializeDocumentTest() throws IOException, SAXException, TransformerExcept } @Test - void serializeEmptyDocumentYieldsEmtpyString() throws TransformerException { + void serializeEmptyDocumentYieldsEmptyString() throws TransformerException { Document document = StandardXmlFactory.documentBuilder().newDocument(); assertThat(StandardXmlFactory.serializeDocument(document)).isEmpty(); } From 03a5210719719cfa07b920240634424da4185428 Mon Sep 17 00:00:00 2001 From: "P. Ottlinger" Date: Tue, 14 Jul 2026 23:37:08 +0200 Subject: [PATCH 13/17] RAT-570: Remove unused code and deprecated stuff Remove unused code and use SiteRenderer instead of deprecated Renderer. --- .../java/org/apache/rat/mp/RatCheckMojo.java | 7 ++-- .../java/org/apache/rat/mp/RatReportMojo.java | 41 ++++++++----------- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatCheckMojo.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatCheckMojo.java index d400b53cc..50fed5ad4 100644 --- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatCheckMojo.java +++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatCheckMojo.java @@ -53,7 +53,8 @@ @Mojo(name = "check", defaultPhase = LifecyclePhase.VALIDATE, threadSafe = true) public class RatCheckMojo extends AbstractRatMojo { - /** The default output file if no other is specified. + /** + * The default output file if no other is specified. * @deprecated Use <outputFile> instead. */ @Deprecated @@ -61,7 +62,7 @@ public class RatCheckMojo extends AbstractRatMojo { private File defaultReportFile; /** - * The defined build directory + * The defined build directory. */ @Parameter(defaultValue = "${project.build.directory}", readonly = true) private String buildDirectory; @@ -84,7 +85,7 @@ public void setReportFile(final File reportFile) { * or "xml" for the raw XML report. Alternatively you can give the path of an * XSL transformation that will be applied on the raw XML to produce the report * written to the output file. - * @deprecated Use setStyleSheet or xml instead. + * @deprecated Use setStyleSheet or "xml" instead. */ @Deprecated @Parameter(property = "rat.outputStyle") diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java index 67c49daf6..087dbace2 100644 --- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java +++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java @@ -37,8 +37,8 @@ import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet; import org.apache.maven.doxia.site.SiteModel; import org.apache.maven.doxia.siterenderer.DocumentRenderingContext; -import org.apache.maven.doxia.siterenderer.Renderer; import org.apache.maven.doxia.siterenderer.RendererException; +import org.apache.maven.doxia.siterenderer.SiteRenderer; import org.apache.maven.doxia.siterenderer.SiteRenderingContext; import org.apache.maven.doxia.siterenderer.sink.SiteRendererSink; import org.apache.maven.doxia.tools.SiteTool; @@ -121,20 +121,20 @@ public class RatReportMojo extends AbstractRatMojo implements MavenMultiPageRepo * Doxia Site Renderer component. */ @Component - protected Renderer siteRenderer; + protected SiteRenderer siteRenderer; /** - * The current sink to use + * The current sink to use. */ private Sink sink; /** - * The sink factory to use + * The sink factory to use. */ private SinkFactory sinkFactory; /** - * The current report output directory to use + * The current report output directory to use. */ private File reportOutputDirectory; @@ -142,7 +142,7 @@ public class RatReportMojo extends AbstractRatMojo implements MavenMultiPageRepo * This method is called when the report generation is invoked directly as a * standalone Mojo. * - * @throws MojoExecutionException if an error occurs when generating the report + * @throws MojoExecutionException if an error occurs when generating the report. * @see org.apache.maven.plugin.Mojo#execute() */ @Override @@ -218,8 +218,7 @@ private SiteRenderingContext createSiteRenderingContext(final Locale locale) Artifact skinArtifact = siteTool.getSkinArtifactFromRepository( session.getRepositorySession(), remoteRepositories, - siteSkin - ); + siteSkin); getLog().debug(buffer().a("Rendering content with ").strong(skinArtifact.getId() + " skin").a('.').build()); @@ -228,11 +227,10 @@ private SiteRenderingContext createSiteRenderingContext(final Locale locale) templateProperties, siteModel, project.getName(), - locale - ); + locale); context.setRootDirectory(project.getBasedir()); - return context; + return context; } catch (SiteToolException e) { throw new MavenReportException("Failed to retrieve skin artifact", e); } catch (RendererException e) { @@ -246,7 +244,7 @@ private SiteRenderingContext createSiteRenderingContext(final Locale locale) * * @param sink the sink to use for the generation. * @param sinkFactory the sink factory to use for the generation. - * @param locale the wanted locale to generate the report, could be null. + * @param locale the wanted locale to generate the report, could be {@code null}. * @throws MavenReportException if any */ @Override @@ -305,7 +303,7 @@ private void generateReportManually(final Locale locale) throws MavenReportExcep * Generate a report. * * @param sink the sink to use for the generation. - * @param locale the wanted locale to generate the report, could be null. + * @param locale the wanted locale to generate the report, could be {@code null}. * @throws MavenReportException if any * @deprecated use {@link #generate(Sink, SinkFactory, Locale)} instead. */ @@ -341,7 +339,7 @@ protected String getOutputDirectory() { return outputDirectory.getAbsolutePath(); } - protected Renderer getSiteRenderer() { + protected SiteRenderer getSiteRenderer() { return siteRenderer; } @@ -378,13 +376,6 @@ public Sink getSink() { return sink; } - /** - * @return the sink factory used - */ - public SinkFactory getSinkFactory() { - return sinkFactory; - } - /** * @return {@code false} by default. * @see org.apache.maven.reporting.MavenReport#isExternalReport() @@ -448,7 +439,7 @@ protected void executeReport(final Locale locale) throws MavenReportException { output.writeSummary(logWriter); } output.format(config); - sink.text(baos.toString(StandardCharsets.UTF_8.name())); + sink.text(baos.toString(StandardCharsets.UTF_8)); } catch (IOException | MojoExecutionException | RatException e) { throw new MavenReportException(e.getMessage(), e); } @@ -462,9 +453,9 @@ protected void executeReport(final Locale locale) throws MavenReportException { } /** - * Returns the reports bundle + * Returns the reports bundle. * - * @param locale Requested locale of the bundle + * @param locale Requested locale of the bundle. * @return The bundle, which is used to read localized strings. */ private ResourceBundle getBundle(final Locale locale) { @@ -486,7 +477,7 @@ public String getDescription(final Locale locale) { /** * Returns the reports name. * - * @param locale Requested locale of the bundle + * @param locale Requested locale of the bundle. * @return Report name, as given by the key "report.rat.name" in the bundle. */ @Override From 121bb6d913a6129ac330ad1d17d8195fe9655396 Mon Sep 17 00:00:00 2001 From: "P. Ottlinger" Date: Tue, 14 Jul 2026 23:38:16 +0200 Subject: [PATCH 14/17] RAT-570: Minor refactorings during review --- .../apache/rat/ReporterOptionsProvider.java | 4 +-- .../java/org/apache/rat/ReporterTest.java | 26 +++++++++---------- .../exclusion/ExclusionProcessorTest.java | 1 - 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsProvider.java b/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsProvider.java index 720a42102..12fe7aa45 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsProvider.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsProvider.java @@ -506,7 +506,7 @@ private void execIncludeTest(final Option option, final String[] args, boolean a // .gitignore is ignored by default as it is hidden but not counted assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(addIgnored ? 4 : 3); - // verify include pust them back + // verify include put them back config = generateConfig(ImmutablePair.of(option, args), ImmutablePair.of(excludeOption, EXCLUDE_ARGS)); reporter = new Reporter(config); output = reporter.execute(); @@ -653,8 +653,6 @@ private void execLicenseFamiliesDeniedTest(final Option option, final String[] a assertDoesNotThrow(() -> { configureSourceDir(option); - - // write the catz licensed text file writeFile("bsd.txt", "SPDX-License-Identifier: BSD-3-Clause"); ReportConfiguration config = generateConfig(); diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java index e3c1695e1..c0f2da002 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java @@ -85,8 +85,8 @@ void testExecute() throws RatException, ParseException { File output = new File(tempDirectory, "testExecute"); CommandLine cl = new DefaultParser().parse(OptionCollection.buildOptions(), new String[]{"--output-style", "xml", "--output-file", output.getPath(), basedir}); - ArgumentContext ctxt = new ArgumentContext(new File("."), cl); - ReportConfiguration config = OptionCollection.createConfiguration(ctxt); + ArgumentContext context = new ArgumentContext(new File("."), cl); + ReportConfiguration config = OptionCollection.createConfiguration(context); ClaimStatistic statistic = new Reporter(config).execute().getStatistic(); assertThat(statistic.getCounter(Type.ARCHIVE)).isEqualTo(1); @@ -140,8 +140,8 @@ void testExecuteNoSource() throws ParseException, RatException, TransformerExcep File output = new File(tempDirectory, "testExecuteNoSource"); CommandLine cl = new DefaultParser().parse(OptionCollection.buildOptions(), new String[]{"--output-style", "xml", "--output-file", output.getPath()}); - ArgumentContext ctxt = new ArgumentContext(new File("."), cl); - ReportConfiguration config = OptionCollection.createConfiguration(ctxt); + ArgumentContext context = new ArgumentContext(new File("."), cl); + ReportConfiguration config = OptionCollection.createConfiguration(context); Reporter.Output result = new Reporter(config).execute(); assertThat(StandardXmlFactory.serializeDocument(result.getDocument())).isEmpty(); ClaimStatisticTest.assertSame(result.getStatistic(), new ClaimStatistic()); @@ -151,9 +151,9 @@ void testExecuteNoSource() throws ParseException, RatException, TransformerExcep void testOutputOption() throws Exception { File output = new File(tempDirectory, "test"); CommandLine commandLine = new DefaultParser().parse(OptionCollection.buildOptions(), new String[]{"-o", output.getCanonicalPath(), basedir}); - ArgumentContext ctxt = new ArgumentContext(new File("."), commandLine); + ArgumentContext context = new ArgumentContext(new File("."), commandLine); - ReportConfiguration config = OptionCollection.createConfiguration(ctxt); + ReportConfiguration config = OptionCollection.createConfiguration(context); new Reporter(config).execute().format(config); assertThat(output.exists()).isTrue(); String content = FileUtils.readFileToString(output, StandardCharsets.UTF_8); @@ -166,9 +166,9 @@ void testOutputOption() throws Exception { void testGetOutputMethod() throws Exception { File output = new File(tempDirectory, "test"); CommandLine commandLine = new DefaultParser().parse(OptionCollection.buildOptions(), new String[]{"-o", output.getCanonicalPath(), basedir}); - ArgumentContext ctxt = new ArgumentContext(new File("."), commandLine); + ArgumentContext context = new ArgumentContext(new File("."), commandLine); - ReportConfiguration config = OptionCollection.createConfiguration(ctxt); + ReportConfiguration config = OptionCollection.createConfiguration(context); Reporter reporter = new Reporter(config); Reporter.Output expected = reporter.execute(); assertThat(reporter.getOutput()).isEqualTo(expected); @@ -182,9 +182,9 @@ void testDefaultOutput() throws Exception { try (PrintStream out = new PrintStream(output)) { System.setOut(out); CommandLine commandLine = new DefaultParser().parse(OptionCollection.buildOptions(), new String[]{basedir}); - ArgumentContext ctxt = new ArgumentContext(new File("."), commandLine); + ArgumentContext context = new ArgumentContext(new File("."), commandLine); - ReportConfiguration config = OptionCollection.createConfiguration(ctxt); + ReportConfiguration config = OptionCollection.createConfiguration(context); new Reporter(config).execute().format(config); } finally { System.setOut(origin); @@ -236,9 +236,9 @@ void testXMLOutput() throws Exception { File output = new File(tempDirectory, ".rat/testXMLOutput"); output.getParentFile().mkdir(); CommandLine commandLine = new DefaultParser().parse(OptionCollection.buildOptions(), new String[]{"--output-style", "xml", "--output-file", output.getPath(), basedir}); - ArgumentContext ctxt = new ArgumentContext(tempDirectory, commandLine); + ArgumentContext context = new ArgumentContext(tempDirectory, commandLine); - ReportConfiguration config = OptionCollection.createConfiguration(ctxt); + ReportConfiguration config = OptionCollection.createConfiguration(context); new Reporter(config).execute().format(config); assertThat(output).exists(); @@ -331,7 +331,7 @@ void testXMLOutput() throws Exception { * Finds a node via xpath on the document. And then checks family, approval and * type of elements of the node. * - * @param doc The document to check + * @param doc the document to check * @param xpath the XPath instance to use. * @param resource the xpath statement to locate the node. * @param licenseInfo the license info for the node. (can be null) diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java index 4d6307388..604e8ad80 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java @@ -147,7 +147,6 @@ private void assertExclusions(DocumentName basedir, String pattern, Map expectedMap = new HashMap<>(); - expectedMap.put("a/b/foo", true); expectedMap.put("b/foo", true); expectedMap.put("foo", false); From a2ff7bb4329fb66ef39d6afd50c60fecf662c2a2 Mon Sep 17 00:00:00 2001 From: "P. Ottlinger" Date: Wed, 15 Jul 2026 00:02:44 +0200 Subject: [PATCH 15/17] RAT-570: Replace deprecated Component by Inject --- .../src/main/java/org/apache/rat/mp/RatReportMojo.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java index 087dbace2..c82d6d440 100644 --- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java +++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java @@ -31,6 +31,8 @@ import java.util.Map; import java.util.ResourceBundle; +import javax.inject.Inject; + import org.apache.maven.artifact.Artifact; import org.apache.maven.doxia.sink.Sink; import org.apache.maven.doxia.sink.SinkFactory; @@ -45,7 +47,6 @@ import org.apache.maven.doxia.tools.SiteToolException; import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; @@ -114,13 +115,13 @@ public class RatReportMojo extends AbstractRatMojo implements MavenMultiPageRepo /** * SiteTool. */ - @Component + @Inject protected SiteTool siteTool; /** * Doxia Site Renderer component. */ - @Component + @Inject protected SiteRenderer siteRenderer; /** From 55eb11ed7164836b69a24c5a6537704eaf3d5f25 Mon Sep 17 00:00:00 2001 From: "P. Ottlinger" Date: Wed, 15 Jul 2026 22:54:39 +0200 Subject: [PATCH 16/17] RAT-570: Rename de/serializer to SerDes --- .../src/main/java/org/apache/rat/ReportConfiguration.java | 6 +++--- .../apache/rat/config/exclusion/ExclusionProcessor.java | 6 +++--- .../java/org/apache/rat/report/claim/ClaimStatistic.java | 6 +++--- .../src/test/java/org/apache/rat/OutputTest.java | 4 ++-- .../org/apache/rat/report/claim/ClaimStatisticTest.java | 8 ++++---- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java index a822e8b99..2768e841a 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java +++ b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java @@ -205,8 +205,8 @@ public ReportConfiguration() { reportables = new ArrayList<>(); } - public Serde serde() { - return new Serde(); + public SerDes serde() { + return new SerDes(); } /** @@ -964,7 +964,7 @@ static IODescriptor input(final File file) { * and do not have access to the original object. */ @SuppressFBWarnings("EI_EXPOSE_REP2") - public class Serde { + public class SerDes { /** * Writes the configuration as an XML document to the appendable. * diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java index b48467f4e..ac73fa7f6 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java @@ -82,8 +82,8 @@ public ExclusionProcessor() { excludedCollections = new HashSet<>(); } - public Serde serde() { - return new Serde(); + public SerDes serde() { + return new SerDes(); } /* the following set of methods are here for testing purposes */ @@ -397,7 +397,7 @@ private void extractPaths(final MatcherSet.Builder matcherBuilder) { /** * Serializes and deserializes the ExclusionProcessor to an XML document. */ - public class Serde { + public class SerDes { /** The pattern attribute name */ private static final String PATTERN = "pattern"; /** THe name attribute name */ diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java index 5bd6418b4..5ef244599 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java @@ -123,8 +123,8 @@ public String displayName() { /** Map of counter type to value */ private final ConcurrentHashMap counterMap = new ConcurrentHashMap<>(); - public Serde serde() { - return new Serde(); + public SerDes serde() { + return new SerDes(); } /** * Converts {@code null} counter to 0. @@ -308,7 +308,7 @@ public String toString() { /** * Serialize and deserialize the claim Statistic. */ - public class Serde { + public class SerDes { /** The count attribute string. */ private static final String COUNT = "count"; /** The name attribute string. */ diff --git a/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java b/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java index 4cf313d3a..faa7954dd 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java @@ -109,9 +109,9 @@ void statisticReadingTest() throws IOException { underTest.incCounter(org.apache.rat.api.Document.Type.IGNORED, 3); underTest.incLicenseNameCount("licenseName", 4); - ClaimStatistic.Serde serde = underTest.serde(); + ClaimStatistic.SerDes serDes = underTest.serde(); StringWriter stringWriter = new StringWriter(); - serde.serialize(stringWriter); + serDes.serialize(stringWriter); try (FileOutputStream fos = new FileOutputStream(documentFile.asFile())) { fos.write(stringWriter.toString().getBytes(StandardCharsets.UTF_8)); } diff --git a/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java b/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java index 611a67e3d..a103da340 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java @@ -139,12 +139,12 @@ void serdeRoundTrip() throws IOException { underTest.incCounter(Document.Type.IGNORED, 3); underTest.incLicenseNameCount("licenseName", 4); - ClaimStatistic.Serde serde = underTest.serde(); + ClaimStatistic.SerDes serDes = underTest.serde(); StringWriter stringWriter = new StringWriter(); - serde.serialize(stringWriter); + serDes.serialize(stringWriter); ClaimStatistic actual = new ClaimStatistic(); - ClaimStatistic.Serde serde2 = actual.serde(); - serde2.deserialize(() -> new ByteArrayInputStream(stringWriter.toString().getBytes(StandardCharsets.UTF_8))); + ClaimStatistic.SerDes serDes2 = actual.serde(); + serDes2.deserialize(() -> new ByteArrayInputStream(stringWriter.toString().getBytes(StandardCharsets.UTF_8))); assertSame(actual, underTest); } From a3c37cdd5bec73ec067eb125e43ec57f96079962 Mon Sep 17 00:00:00 2001 From: "P. Ottlinger" Date: Thu, 16 Jul 2026 12:41:04 +0200 Subject: [PATCH 17/17] RAT-570: Rename method to class name accordingly --- .../main/java/org/apache/rat/ReportConfiguration.java | 6 +++--- .../src/main/java/org/apache/rat/Reporter.java | 4 ++-- .../rat/config/exclusion/ExclusionProcessor.java | 2 +- .../org/apache/rat/report/claim/ClaimStatistic.java | 2 +- .../src/test/java/org/apache/rat/OutputTest.java | 4 ++-- .../java/org/apache/rat/ReportConfigurationTest.java | 6 +++--- .../rat/config/exclusion/ExclusionProcessorTest.java | 10 +++++----- .../apache/rat/report/claim/ClaimStatisticTest.java | 6 +++--- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java index 2768e841a..a17077e8c 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java +++ b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java @@ -205,7 +205,7 @@ public ReportConfiguration() { reportables = new ArrayList<>(); } - public SerDes serde() { + public SerDes serDes() { return new SerDes(); } @@ -999,7 +999,7 @@ public void serialize(final Appendable appendable) throws IOException { } writer.closeElement(); - exclusionProcessor.serde().serialize(writer); + exclusionProcessor.serDes().serialize(writer); writer.startElement("claimValidator"); for (ClaimStatistic.Counter counter : ClaimStatistic.Counter.values()) { @@ -1063,7 +1063,7 @@ public void deserialize(final IOSupplier inputStreamSupplier, final addSource(new DeserializedReportable(documentName)); }); - exclusionProcessor.serde().deserialize(document.getElementsByTagName("ExclusionProcessor").item(0)); + exclusionProcessor.serDes().deserialize(document.getElementsByTagName("ExclusionProcessor").item(0)); XMLConfigurationReader.nodeListConsumer(document.getElementsByTagName("claimCounter"), lNode -> { Map nAttributes = XMLConfigurationReader.attributes(lNode); diff --git a/apache-rat-core/src/main/java/org/apache/rat/Reporter.java b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java index 31fdbc3c0..c752db924 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/Reporter.java +++ b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java @@ -284,7 +284,7 @@ public Builder statistic(final String fileName, final DocumentName workingDirect File sourceFile = workingDirectory.resolve(fileName).asFile(); try { ClaimStatistic newStatistic = new ClaimStatistic(); - newStatistic.serde().deserialize(() -> new FileInputStream(sourceFile)); + newStatistic.serDes().deserialize(() -> new FileInputStream(sourceFile)); this.statistic = newStatistic; return this; } catch (IOException e) { @@ -301,7 +301,7 @@ public Builder configuration(final String fileName, final DocumentName workingDi File configurationFile = workingDirectory.resolve(fileName).asFile(); try { ReportConfiguration config = new ReportConfiguration(); - config.serde().deserialize(() -> new FileInputStream(configurationFile), workingDirectory); + config.serDes().deserialize(() -> new FileInputStream(configurationFile), workingDirectory); this.configuration = config; return this; } catch (IOException e) { diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java index ac73fa7f6..d57e21181 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java @@ -82,7 +82,7 @@ public ExclusionProcessor() { excludedCollections = new HashSet<>(); } - public SerDes serde() { + public SerDes serDes() { return new SerDes(); } diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java index 5ef244599..7279e3e81 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimStatistic.java @@ -123,7 +123,7 @@ public String displayName() { /** Map of counter type to value */ private final ConcurrentHashMap counterMap = new ConcurrentHashMap<>(); - public SerDes serde() { + public SerDes serDes() { return new SerDes(); } /** diff --git a/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java b/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java index faa7954dd..f523f55e3 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java @@ -109,7 +109,7 @@ void statisticReadingTest() throws IOException { underTest.incCounter(org.apache.rat.api.Document.Type.IGNORED, 3); underTest.incLicenseNameCount("licenseName", 4); - ClaimStatistic.SerDes serDes = underTest.serde(); + ClaimStatistic.SerDes serDes = underTest.serDes(); StringWriter stringWriter = new StringWriter(); serDes.serialize(stringWriter); try (FileOutputStream fos = new FileOutputStream(documentFile.asFile())) { @@ -184,7 +184,7 @@ void configurationReadingTest() throws IOException { claimValidator.setMin(ClaimStatistic.Counter.BINARIES, 4); StringWriter stringWriter = new StringWriter(); - underTest.serde().serialize(stringWriter); + underTest.serDes().serialize(stringWriter); try (FileOutputStream fos = new FileOutputStream(documentFile.asFile())) { fos.write(stringWriter.toString().getBytes(StandardCharsets.UTF_8)); diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java index 9d07ec3e4..098669e82 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java @@ -788,7 +788,7 @@ public static void assertSame(ReportConfiguration actual, ReportConfiguration ex } @Test - void serdeTest() throws IOException { + void serDesTest() throws IOException { underTest.setAddLicenseHeaders(AddLicenseHeaders.FORCED); underTest.listFamilies(LicenseFilter.APPROVED); underTest.listLicenses(LicenseFilter.ALL); @@ -819,10 +819,10 @@ void serdeTest() throws IOException { claimValidator.setMin(ClaimStatistic.Counter.BINARIES, 4); StringWriter stringWriter = new StringWriter(); - underTest.serde().serialize(stringWriter); + underTest.serDes().serialize(stringWriter); ReportConfiguration actual = new ReportConfiguration(); - actual.serde().deserialize(() -> new ByteArrayInputStream(stringWriter.toString().getBytes(StandardCharsets.UTF_8)), + actual.serDes().deserialize(() -> new ByteArrayInputStream(stringWriter.toString().getBytes(StandardCharsets.UTF_8)), DocumentName.builder(new File("/rootDir")).build()); assertSame(actual, underTest); } diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java index 604e8ad80..3e5ad642e 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java @@ -378,19 +378,19 @@ public static void assertSame(ExclusionProcessor actual, ExclusionProcessor expe } @ParameterizedTest - @MethodSource("serdeTestData") - void serdeTest(ExclusionProcessor underTest) throws IOException, SAXException { + @MethodSource("serDesTestData") + void serDesTest(ExclusionProcessor underTest) throws IOException, SAXException { StringWriter stringWriter = new StringWriter(); try (XmlWriter writer = new XmlWriter(stringWriter)) { - underTest.serde().serialize(writer); + underTest.serDes().serialize(writer); } Document document = StandardXmlFactory.documentBuilder().parse(new ByteArrayInputStream(stringWriter.toString().getBytes(StandardCharsets.UTF_8))); ExclusionProcessor actual = new ExclusionProcessor(); - actual.serde().deserialize(document.getElementsByTagName("ExclusionProcessor").item(0)); + actual.serDes().deserialize(document.getElementsByTagName("ExclusionProcessor").item(0)); assertSame(actual, underTest); } - static List serdeTestData() { + static List serDesTestData() { List tests = new ArrayList<>(); tests.add(new ExclusionProcessor()); diff --git a/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java b/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java index a103da340..a0da56311 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/report/claim/ClaimStatisticTest.java @@ -132,18 +132,18 @@ public static void assertSame(final ClaimStatistic actual, final ClaimStatistic } @Test - void serdeRoundTrip() throws IOException { + void serDesRoundTrip() throws IOException { ClaimStatistic underTest = new ClaimStatistic(); underTest.incLicenseCategoryCount("familyCategory", 1); underTest.incCounter(ClaimStatistic.Counter.APPROVED, 2); underTest.incCounter(Document.Type.IGNORED, 3); underTest.incLicenseNameCount("licenseName", 4); - ClaimStatistic.SerDes serDes = underTest.serde(); + ClaimStatistic.SerDes serDes = underTest.serDes(); StringWriter stringWriter = new StringWriter(); serDes.serialize(stringWriter); ClaimStatistic actual = new ClaimStatistic(); - ClaimStatistic.SerDes serDes2 = actual.serde(); + ClaimStatistic.SerDes serDes2 = actual.serDes(); serDes2.deserialize(() -> new ByteArrayInputStream(stringWriter.toString().getBytes(StandardCharsets.UTF_8))); assertSame(actual, underTest);