Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
bc38597
fix DocumentName issues
Claudenw Jun 9, 2026
c2c2d9d
checkpoint
Claudenw Jun 16, 2026
082579e
Fixed several parsing errors in DocumentName.Builder
Claudenw Jun 18, 2026
188a671
initial changes
Claudenw May 10, 2026
53fc65f
created testhelper and updated tests
Claudenw May 10, 2026
d9f42f0
fixed tests
Claudenw May 10, 2026
5e0aebd
Change to Reporter.Output usage
Claudenw May 24, 2026
e625ea6
updated javadoc
Claudenw May 24, 2026
d6f9c33
updated UI strategy
Claudenw May 31, 2026
597808c
Remove ArchiveEntryDocument and clean up ArchiveWalker.
Claudenw Jun 1, 2026
63592fd
Change ArgumentContext to build from Options and arguments rather tha…
Claudenw Jun 1, 2026
d250a12
Switch to UnmodifiableSets for licences
Claudenw Jun 1, 2026
04a5e45
fix spotbugs issues
Claudenw Jun 1, 2026
7ea7d82
fix spotbugs issues
Claudenw Jun 1, 2026
27d16f9
fix spotbugs issues
Claudenw Jun 1, 2026
c828f9c
created TempDir replacement to support Windows
Claudenw Jun 1, 2026
892ea59
Fixed issues with DocumentName and DocumentNameBuilder.
Claudenw Jun 5, 2026
aa88fcb
fixes for DocumentName errors
Claudenw Jun 9, 2026
2632460
fixed rebasing issues
Claudenw Jun 22, 2026
01b4af7
fix DocumentName issues
Claudenw Jun 9, 2026
cba7296
checkpoint
Claudenw Jun 16, 2026
36fc67e
Fixed several parsing errors in DocumentName.Builder
Claudenw Jun 18, 2026
789ce73
RAT-559: Refactor during review
ottlinger Jun 23, 2026
181aafb
RAT-559: Shorten tests
ottlinger Jun 23, 2026
43ad0dd
fixed merge issues
Claudenw Jun 24, 2026
f10553c
fixed rebase issues
Claudenw Jun 25, 2026
59b3b69
fix some sonarqube issues
Claudenw Jun 25, 2026
98d1d6d
fixed sonar issues
Claudenw Jun 26, 2026
ab6f099
fixes for SonarQube results
Claudenw Jun 27, 2026
7ae7c49
cleaned up checkstyle issues
Claudenw Jun 27, 2026
5753369
cleaned up SonarQube issues
Claudenw Jun 27, 2026
14a9187
fixed tests
Claudenw Jun 29, 2026
335aa27
merged main branch
Claudenw Jul 5, 2026
fd06cde
fixup from rebase
Claudenw Jul 23, 2026
36ca0f2
fixed some sonarcloud issues
Claudenw Jul 25, 2026
96e7681
fixed null pointer issue
Claudenw Jul 25, 2026
a9720a4
fixed some sonarcloud issues
Claudenw Jul 26, 2026
3180bf8
fixed bad comments
Claudenw Jul 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions apache-rat-core/src/it/java/org/apache/rat/ReportTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,15 @@
* associated with the exception.</li>
* </ul>
*/
public class ReportTest {
class ReportTest {

private String[] asArgs(final List<String> argsList) {
return argsList.toArray(new String[0]);
}

@ParameterizedTest(name = "{index} {0}")
@MethodSource("args")
public void integrationTest(String testName, Document commandLineDoc) throws Exception {
void integrationTest(String testName, Document commandLineDoc) throws Exception {
DefaultLog.getInstance().log(Log.Level.INFO, "Running test for " + testName);
File baseDir = new File(commandLineDoc.getName().getName()).getParentFile();

Expand Down Expand Up @@ -119,9 +119,11 @@ public void integrationTest(String testName, Document commandLineDoc) throws Exc

File expectedMsg = new File(baseDir, "expected-message.txt");
if (expectedMsg.exists()) {
String msg = IOUtils.readLines(new FileReader(expectedMsg)).get(0).trim();
assertThrows(RatDocumentAnalysisException.class, () -> Report.main(asArgs(argsList)),
msg);
try (FileReader fr = new FileReader(expectedMsg)) {
String msg = IOUtils.readLines(fr).get(0).trim();
assertThrows(RatDocumentAnalysisException.class, () -> Report.main(asArgs(argsList)),
msg);
}
} else {
Report.main(asArgs(argsList));
}
Expand All @@ -142,7 +144,7 @@ public void integrationTest(String testName, Document commandLineDoc) throws Exc
try {
Object value = shell.run(groovyScript, new String[]{outputFile.getAbsolutePath(), logFile.getAbsolutePath()});
if (value != null) {
fail(String.format("%s", value));
fail(String.format("%s: %s", testName, value));
}
} catch (AssertionError e) {
throw new AssertionError(String.format("%s: %s", testName, e.getMessage()), e);
Expand Down Expand Up @@ -204,6 +206,7 @@ public static class FileLog implements Log {
*
* @param level the level to use when writing messages.
*/
@Override
public void setLevel(final Level level) {
this.level = level;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,9 @@ myArgs[3] = src.getAbsolutePath()

ReportConfiguration configuration = OptionCollection.parseCommands(src, myArgs, { opts -> })
assertNotNull(configuration)
configuration.validate(DefaultLog.getInstance().&error)
configuration.validate()
Reporter reporter = new Reporter(configuration)
Reporter.Output output = reporter.execute()
ClaimStatistic statistic = output.getStatistic()
ClaimStatistic statistic = reporter.execute().getStatistic()

assertEquals(3, statistic.getCounter(ClaimStatistic.Counter.APPROVED))
assertEquals(2, statistic.getCounter(ClaimStatistic.Counter.ARCHIVES))
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Issues with UNAPPROVED
Issues with LICENSE_CATEGORIES, LICENSE_NAMES, STANDARDS
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
--licenses-denied
DOJO
--
19 changes: 6 additions & 13 deletions apache-rat-core/src/main/java/org/apache/rat/OptionCollection.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import java.util.stream.Collectors;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
Expand Down Expand Up @@ -130,29 +129,23 @@ public static ReportConfiguration parseCommands(final File workingDirectory, fin
*/
public static ReportConfiguration parseCommands(final File workingDirectory, final String[] args,
final Consumer<Options> helpCmd, final boolean noArgs) throws IOException {

Options opts = buildOptions();
CommandLine commandLine;
ArgumentContext argumentContext;
try {
commandLine = DefaultParser.builder().setDeprecatedHandler(DeprecationReporter.getLogReporter())
.setAllowPartialMatching(true).build().parse(opts, args);
argumentContext = new ArgumentContext(workingDirectory, opts, args);
} catch (ParseException e) {
DefaultLog.getInstance().error(e.getMessage());
DefaultLog.getInstance().error("Please use the \"--help\" option to see a list of valid commands and options.", e);
System.exit(1);
return null; // dummy return (won't be reached) to avoid Eclipse complaint about possible NPE
// for "commandLine"
}

ArgumentContext argumentContext = new ArgumentContext(workingDirectory, commandLine);
Arg.processLogLevel(argumentContext, CLIOptionCollection.INSTANCE);

if (commandLine.hasOption(HELP)) {
if (argumentContext.getCommandLine().hasOption(HELP)) {
helpCmd.accept(opts);
return null;
}

if (commandLine.hasOption(Arg.HELP_LICENSES.option())) {
if (argumentContext.getCommandLine().hasOption(Arg.HELP_LICENSES.option())) {
new Licenses(createConfiguration(argumentContext), new PrintWriter(System.out, false, StandardCharsets.UTF_8)).printHelp();
return null;
}
Expand Down Expand Up @@ -184,8 +177,8 @@ public static ReportConfiguration createConfiguration(final ArgumentContext argu
Optional<Option> dirOpt = CLIOptionCollection.INSTANCE.getSelected(Arg.DIR);
if (dirOpt.isPresent()) {
try {
configuration.addSource(getReportable(commandLine.getParsedOptionValue(
dirOpt.get()), configuration));
DocumentName directoryName = commandLine.getParsedOptionValue(dirOpt.get());
configuration.addSource(getReportable(directoryName.asFile(), configuration));
} catch (ParseException e) {
throw new ConfigurationException("Unable to set parse " + dirOpt.get(), e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.lang3.StringUtils;
import org.apache.rat.api.RatException;
import org.apache.rat.commandline.Arg;
import org.apache.rat.commandline.ArgumentContext;
import org.apache.rat.help.Licenses;
import org.apache.rat.report.Reportable;
import org.apache.rat.ui.UIOption;
import org.apache.rat.ui.UIOptionCollection;
import org.apache.rat.utils.DefaultLog;

Expand All @@ -44,15 +46,21 @@
/**
* Uses the AbstractOptionCollection to parse the command line options.
* Contains utility methods to ReportConfiguration from the options and an array of arguments.
*
* @param <T> The UIOption type that this parser is handeling.
*/
@SuppressFBWarnings("EI_EXPOSE_REP2")
public final class OptionCollectionParser {
public final class OptionCollectionParser<T extends UIOption<T>> {
/**
* The OptionCollection that we are working with.
*/
private final UIOptionCollection<?> uiOptionCollection;
private final UIOptionCollection<T> uiOptionCollection;

public OptionCollectionParser(final UIOptionCollection<?> optionCollection) {
/**
* Constructor.
* @param optionCollection The option collection to use for
*/
public OptionCollectionParser(final UIOptionCollection<T> optionCollection) {
this.uiOptionCollection = optionCollection;
}

Expand All @@ -62,11 +70,10 @@ public OptionCollectionParser(final UIOptionCollection<?> optionCollection) {
* @param workingDirectory The directory to resolve relative file names against.
* @param args the arguments to parse
* @return the ArgumentContext for the process.
* @throws IOException on error.
* @throws ParseException on option parsing error.
* @throws RatException on error.
*/
public ArgumentContext parseCommands(final File workingDirectory, final String[] args)
throws IOException, ParseException {
throws RatException {
return parseCommands(workingDirectory, args, uiOptionCollection.getOptions());
}

Expand All @@ -77,8 +84,7 @@ public ArgumentContext parseCommands(final File workingDirectory, final String[]
* @return the CommandLine
* @throws ParseException on option parsing error.
*/
//@VisibleForTesting
CommandLine parseCommandLine(final Options opts, final String[] args) throws ParseException {
public static CommandLine parseCommandLine(final Options opts, final String[] args) throws ParseException {
try {
return DefaultParser.builder().setDeprecatedHandler(DeprecationReporter.getLogReporter())
.setAllowPartialMatching(true).build().parse(opts, args);
Expand All @@ -89,29 +95,39 @@ CommandLine parseCommandLine(final Options opts, final String[] args) throws Par
}
}

// visible for testing
void printHelp(final ArgumentContext argumentContext) throws RatException {
try {
new Licenses(argumentContext.getConfiguration(),
new PrintWriter(argumentContext.getConfiguration().getOutput().get(),
false, StandardCharsets.UTF_8)).printHelp();
} catch (IOException e) {
throw new RatException("Unable to print help: " + e.getMessage(), e);
}
}
/**
* Parses the standard options to create a ReportConfiguration.
*
* @param workingDirectory The directory to resolve relative file names against.
* @param args the arguments to parse.
* @param options An Options object containing Apache command line options.
* @return the ArgumentContext for the process.
* @throws IOException on error.
* @throws ParseException on option parsing error.
* @throws RatException on error.
*/
private ArgumentContext parseCommands(final File workingDirectory, final String[] args,
final Options options) throws IOException, ParseException {
CommandLine commandLine = parseCommandLine(options, args);
ArgumentContext argumentContext = new ArgumentContext(workingDirectory, commandLine);
Arg.processLogLevel(argumentContext, uiOptionCollection);
populateConfiguration(argumentContext);
if (uiOptionCollection.isSelected(Arg.HELP_LICENSES)) {
new Licenses(argumentContext.getConfiguration(),
new PrintWriter(argumentContext.getConfiguration().getOutput().get(),
false, StandardCharsets.UTF_8)).printHelp();
// visible for testing
ArgumentContext parseCommands(final File workingDirectory, final String[] args,
final Options options) throws RatException {
try {
ArgumentContext argumentContext = new ArgumentContext(workingDirectory, options, args);
Arg.processLogLevel(argumentContext, uiOptionCollection);
populateConfiguration(argumentContext);
if (uiOptionCollection.isSelected(Arg.HELP_LICENSES)) {
printHelp(argumentContext);
}
return argumentContext;
} catch (ParseException e) {
throw new RatException("Unable to parse command line: " + e.getMessage(), e);
}

return argumentContext;
}

/**
Expand Down
64 changes: 51 additions & 13 deletions apache-rat-core/src/main/java/org/apache/rat/Report.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,15 @@
package org.apache.rat;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;

import org.apache.commons.cli.Options;
import org.apache.commons.io.function.IOSupplier;
import org.apache.rat.api.RatException;
import org.apache.rat.commandline.ArgumentContext;
import org.apache.rat.document.RatDocumentAnalysisException;
import org.apache.rat.help.Help;
import org.apache.rat.utils.DefaultLog;
Expand Down Expand Up @@ -48,28 +55,59 @@ public static void main(final String[] args) throws Exception {
System.exit(0);
}

ReportConfiguration configuration = OptionCollection.parseCommands(new File("."), args, Report::printUsage);
if (configuration != null) {
configuration.validate(DefaultLog.getInstance()::error);
Reporter.Output output = new Reporter(configuration).execute();
output.format(configuration);
output.writeSummary(DefaultLog.getInstance().asWriter());
Reporter.Output result = generateReport(CLIOptionCollection.INSTANCE, new File("."), args);
if (result != null) {
result.writeSummary(DefaultLog.getInstance().asWriter());

if (configuration.getClaimValidator().hasErrors()) {
configuration.getClaimValidator().logIssues(output.getStatistic());
if (result.getConfiguration().getClaimValidator().hasErrors()) {
result.getConfiguration().getClaimValidator().logIssues(result.getStatistic());
throw new RatDocumentAnalysisException(format("Issues with %s",
String.join(", ",
configuration.getClaimValidator().listIssues(output.getStatistic()))));
result.getConfiguration().getClaimValidator().listIssues(result.getStatistic()))));
}
}
}

/**
* Prints the usage message on {@code System.out}.
* @param opts the defined options.
* Prints the usage message on the specified output stream.
* @param out The OutputStream supplier
*/
private static void printUsage(final Options options, final IOSupplier<OutputStream> out) {
try (OutputStream stream = out.get();
PrintWriter writer = new PrintWriter(stream, false, StandardCharsets.UTF_8)) {
new Help(writer).printUsage(options);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

/**
* Generates the report
* @param workingDirectory the directory that we are executing in
* @param args the arguments from the command line.
* @return The Client output.
* @throws Exception on error.
*/
private static void printUsage(final Options opts) {
new Help(System.out).printUsage(opts);
static Reporter.Output generateReport(final CLIOptionCollection optionCollection, final File workingDirectory, final String[] args) throws RatException {
Reporter.Output output = null;
OptionCollectionParser optionParser = new OptionCollectionParser(optionCollection);
ArgumentContext argumentContext = optionParser.parseCommands(workingDirectory, args);
ReportConfiguration configuration = argumentContext.getConfiguration();
if (configuration != null) {
if (argumentContext.getCommandLine().hasOption(CLIOptionCollection.HELP)) {
printUsage(optionCollection.getOptions(), argumentContext.getConfiguration().getOutput());
} else if (!configuration.hasSource()) {
String msg = "No directories or files specified for scanning. Did you forget to close a multi-argument option?";
DefaultLog.getInstance().error(msg);
printUsage(optionCollection.getOptions(), argumentContext.getConfiguration().getOutput());
} else {
configuration.validate();
Reporter reporter = new Reporter(configuration);
output = reporter.execute();
output.format(configuration);
}
}
return output;
}

private Report() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import java.util.Map;
import java.util.Objects;
import java.util.SortedSet;
import java.util.function.Consumer;
import java.util.stream.Stream;

import org.apache.commons.collections4.set.UnmodifiableSortedSet;
Expand Down Expand Up @@ -527,7 +526,7 @@ public void setStyleSheet(final IODescriptor<InputStream> styleSheet) {
*/
public void setFrom(final Defaults defaults) {
licenseSetFactory.add(defaults.getLicenseSetFactory());
if (getStyleSheet() == null) {
if (getStyleSheetDescriptor() == null) {
setStyleSheet(StyleSheets.PLAIN.getStyleSheet());
}
defaults.getStandardExclusion().forEach(this::addExcludedCollection);
Expand Down Expand Up @@ -902,20 +901,15 @@ public LicenseSetFactory getLicenseSetFactory() {

/**
* Validates that the configuration is valid.
* @param logger String consumer to log warning messages to.
* @throws ConfigurationException on configuration error.
*/
public void validate(final Consumer<String> logger) {
public void validate() {
if (!hasSource()) {
String msg = "At least one source must be specified";
logger.accept(msg);
throw new ConfigurationException(msg);
}
if (licenseSetFactory.getLicenses(LicenseFilter.ALL).isEmpty()) {
String msg = "You must specify at least one license";
logger.accept(msg);
DefaultLog.getInstance().error(msg);
throw new ConfigurationException(msg);
}
licenseSetFactory.validate();
}

/**
Expand Down Expand Up @@ -1036,7 +1030,7 @@ public void deserialize(final IOSupplier<InputStream> inputStreamSupplier, final
standardProcessing = Processing.valueOf(attributes.get("standardProcessing"));
String styleName = attributes.get("stylesheet");
if (styleName != null) {
styleSheet = StyleSheets.getStyleSheet(styleName);
styleSheet = StyleSheets.getStyleSheet(styleName, workingDirectory);
}
String outputName = attributes.get("output");
if (outputName != null) {
Expand Down
Loading
Loading