This is an automated email from the ASF dual-hosted git repository.
Claudenw pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/creadur-rat.git
The following commit(s) were added to refs/heads/master by this push:
new 3e6b50cc RAT-564: make LicenseSetFactory return unmodifiable licenses
sets (#687)
3e6b50cc is described below
commit 3e6b50ccf2c4edb571873669220f2aa5a3839258
Author: Claude Warren <[email protected]>
AuthorDate: Sat Jul 4 23:32:42 2026 +0200
RAT-564: make LicenseSetFactory return unmodifiable licenses sets (#687)
* make LicenseSetFactory return unmodifiable licenses sets
* added factory tests
---------
Co-authored-by: P. Ottlinger <[email protected]>
Co-authored-by: P. Ottlinger <[email protected]>
---
.../java/org/apache/rat/ReportConfiguration.java | 45 ++++++------
.../org/apache/rat/analysis/AnalyserFactory.java | 33 ++++-----
.../rat/analysis/DocumentHeaderAnalyser.java | 8 +--
.../org/apache/rat/analysis/HeaderCheckWorker.java | 27 ++++---
.../org/apache/rat/license/LicenseSetFactory.java | 84 +++++++++++++++-------
.../java/org/apache/rat/license/SimpleLicense.java | 10 +--
.../src/test/java/org/apache/rat/DefaultsTest.java | 13 ++--
.../apache/rat/analysis/HeaderCheckWorkerTest.java | 24 +++++--
.../apache/rat/license/LicenseSetFactoryTest.java | 77 ++++++++++++++++++++
.../apache/rat/documentation/velocity/RatTool.java | 9 ++-
src/changes/changes.xml | 3 +
11 files changed, 227 insertions(+), 106 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 787bb3dc..8fc5835d 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
@@ -38,6 +38,7 @@ import java.util.Objects;
import java.util.SortedSet;
import java.util.function.Consumer;
+import org.apache.commons.collections4.set.UnmodifiableSortedSet;
import org.apache.commons.io.function.IOSupplier;
import org.apache.commons.io.output.CloseShieldOutputStream;
import org.apache.rat.analysis.IHeaderMatcher;
@@ -84,7 +85,6 @@ public class ReportConfiguration {
*/
private final String description;
-
Processing(final String description) {
this.description = description;
}
@@ -162,6 +162,7 @@ public class ReportConfiguration {
* The ClaimValidator to validate min/max counts and similar claims.
*/
private final ClaimValidator claimValidator;
+
/**
* Constructor
*/
@@ -245,7 +246,7 @@ public class ReportConfiguration {
/**
* 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;
@@ -261,7 +262,7 @@ public class ReportConfiguration {
/**
* 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;
@@ -278,7 +279,7 @@ public class ReportConfiguration {
/**
* Set the log level for reporting collisions in the set of license
families.
* <p>NOTE: should be set before licenses or license families are
added.</p>
- * @param level The log level to use.
+ * @param level the log level to use.
*/
public void logFamilyCollisions(final Level level) {
licenseSetFactory.logFamilyCollisions(level);
@@ -286,7 +287,7 @@ public class ReportConfiguration {
/**
* 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);
@@ -294,7 +295,7 @@ public class ReportConfiguration {
/**
* 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);
@@ -420,7 +421,7 @@ public class ReportConfiguration {
/**
* Add file patterns that are to be included. These patterns override any
exclusion of
* the same files.
- * @param patterns The iterable of Strings containing the patterns.
+ * @param patterns the iterable of Strings containing the patterns.
*/
public void addIncludedPatterns(final Iterable<String> patterns) {
exclusionProcessor.addIncludedPatterns(patterns);
@@ -458,7 +459,7 @@ public class ReportConfiguration {
* Adds the licenses and approved licenses from the defaults object to the
* configuration. <em>Side effect:</em> if the report should be styled and
no
* style sheet has been set the plain stylesheet from the defaults will be
used.
- * @param defaults The defaults to set.
+ * @param defaults the defaults to set.
*/
public void setFrom(final Defaults defaults) {
licenseSetFactory.add(defaults.getLicenseSetFactory());
@@ -506,7 +507,7 @@ public class ReportConfiguration {
* times to provide the stream. Suppliers should prepare streams that are
* 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
+ * @param out the OutputStream supplier that provides the output stream to
write
* the report to. A null value will use System.out.
* @see CloseShieldOutputStream
*/
@@ -519,7 +520,7 @@ public class ReportConfiguration {
* opened and closed several times. File is deleted first and then may be
* repeatedly opened in append mode.
* @see #setOut(IOSupplier)
- * @param file The file to create the supplier with.
+ * @param file the file to create the supplier with.
*/
public void setOut(final File file) {
Objects.requireNonNull(file, "output file should not be null");
@@ -540,7 +541,7 @@ public class ReportConfiguration {
/**
* Returns the output stream supplier. If no stream has been set returns a
* supplier for System.out.
- * @return The supplier of the output stream to write the report to.
+ * @return the supplier of the output stream to write the report to.
*/
public IOSupplier<OutputStream> getOutput() {
return out == null ? () -> CloseShieldOutputStream.wrap(System.out) :
out;
@@ -548,7 +549,7 @@ public class ReportConfiguration {
/**
* Gets a PrintWriter that wraps the output stream.
- * @return A supplier for a PrintWriter that wraps the output stream.
+ * @return a supplier for a PrintWriter that wraps the output stream.
* @see #getOutput()
*/
public IOSupplier<PrintWriter> getWriter() {
@@ -558,7 +559,7 @@ public class ReportConfiguration {
/**
* Adds a license to the list of licenses. Does not add the license to the
list
* of approved licenses.
- * @param license The license to add to the list of licenses.
+ * @param license the license to add to the list of licenses.
*/
public void addLicense(final ILicense license) {
licenseSetFactory.addLicense(license);
@@ -567,7 +568,7 @@ public class ReportConfiguration {
/**
* Adds a license to the list of licenses. Does not add the license to the
list
* of approved licenses.
- * @param builder The license builder to build and add to the list of
licenses.
+ * @param builder the license builder to build and add to the list of
licenses.
* @return The ILicense implementation that was added.
*/
public ILicense addLicense(final ILicense.Builder builder) {
@@ -577,7 +578,7 @@ public class ReportConfiguration {
/**
* Adds multiple licenses to the list of licenses. Does not add the
licenses to
* the list of approved licenses.
- * @param licenses The licenses to add.
+ * @param licenses the licenses to add.
*/
public void addLicenses(final Collection<ILicense> licenses) {
licenseSetFactory.addLicenses(licenses);
@@ -586,7 +587,7 @@ public class ReportConfiguration {
/**
* Adds a license family to the list of families. Does not add the family
to the
* list of approved licenses.
- * @param family The license family to add to the list of license families.
+ * @param family the license family to add to the list of license families.
*/
public void addFamily(final ILicenseFamily family) {
licenseSetFactory.addFamily(family);
@@ -595,7 +596,7 @@ public class ReportConfiguration {
/**
* Adds a license family to the list of families. Does not add the family
to the
* list of approved licenses.
- * @param builder The licenseFamily.Builder to build and add to the list of
+ * @param builder the licenseFamily.Builder to build and add to the list of
* licenses.
*/
public void addFamily(final ILicenseFamily.Builder builder) {
@@ -605,7 +606,7 @@ public class ReportConfiguration {
/**
* Adds multiple families to the list of license families. Does not add the
* licenses to the list of approved licenses.
- * @param families The license families to add.
+ * @param families the license families to add.
*/
public void addFamilies(final Collection<ILicenseFamily> families) {
families.forEach(this::addApprovedLicenseCategory);
@@ -658,7 +659,7 @@ public class ReportConfiguration {
/**
* Gets the SortedSet of approved license categories. <em>Once a license
has
* been removed from the approved list it cannot be re-added</em>
- * @param filter The LicenseFilter to filter the categories by.
+ * @param filter the LicenseFilter to filter the categories by.
* @return the Sorted set of approved license categories.
*/
public SortedSet<String> getLicenseCategories(final LicenseFilter filter) {
@@ -668,17 +669,17 @@ public class ReportConfiguration {
/**
* Gets the SortedSet of approved license categories. <em>Once a license
has
* been removed from the approved list it cannot be re-added</em>
- * @param filter The LicenseFilter to filter the licenses by.
+ * @param filter the LicenseFilter to filter the licenses by.
* @return the Sorted set of approved license categories.
*/
- public SortedSet<ILicense> getLicenses(final LicenseFilter filter) {
+ public UnmodifiableSortedSet<ILicense> getLicenses(final LicenseFilter
filter) {
return licenseSetFactory.getLicenses(filter);
}
/**
* Gets the SortedSet of approved license categories. <em>Once a license
has
* been removed from the approved list it cannot be re-added</em>
- * @param filter The LicenseFilter to filter the licenses by.
+ * @param filter the LicenseFilter to filter the licenses by.
* @return the Sorted set of approved license categories.
*/
public SortedSet<String> getLicenseIds(final LicenseFilter filter) {
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/analysis/AnalyserFactory.java
b/apache-rat-core/src/main/java/org/apache/rat/analysis/AnalyserFactory.java
index f2eca190..0d4abc09 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/AnalyserFactory.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/AnalyserFactory.java
@@ -18,10 +18,9 @@
*/
package org.apache.rat.analysis;
-import java.util.Collection;
-import java.util.Set;
import java.util.function.Predicate;
+import org.apache.commons.collections4.set.UnmodifiableSortedSet;
import org.apache.rat.ConfigurationException;
import org.apache.rat.Defaults;
import org.apache.rat.ReportConfiguration;
@@ -50,7 +49,7 @@ public final class AnalyserFactory {
* Note you probably do not want this as it is automatically added to
{@link #createConfiguredAnalyser}.
* </p>
* @param approvalPredicate the predicate to approve licenses.
- * @return A document analyser that sets the approvalPredicate in document
metadata.
+ * @return a document analyser that sets the approvalPredicate in document
metadata.
*/
public static DocumentAnalyser createPolicy(final Predicate<ILicense>
approvalPredicate) {
return document -> {
@@ -75,12 +74,12 @@ public final class AnalyserFactory {
/**
* Creates a DocumentAnalyser from the report configuration.
- * @param configuration the ReportConfiguration
- * @return A document analyser that uses the provided licenses.
+ * @param configuration the ReportConfiguration.
+ * @return a document analyser that uses the provided licenses.
*/
public static DocumentAnalyser createConfiguredAnalyser(final
ReportConfiguration configuration) {
LicenseSetFactory licenseSetFactory =
configuration.getLicenseSetFactory();
- Set<ILicense> licenses =
licenseSetFactory.getLicenses(LicenseSetFactory.LicenseFilter.ALL);
+ UnmodifiableSortedSet<ILicense> licenses =
licenseSetFactory.getLicenses(LicenseSetFactory.LicenseFilter.ALL);
if (licenses.isEmpty()) {
throw new ConfigurationException("At least one license must be
defined");
}
@@ -98,18 +97,18 @@ public final class AnalyserFactory {
private static final class DefaultAnalyser implements DocumentAnalyser {
/** The licenses to analyze */
- private final Collection<ILicense> licenses;
- /** the Report Configuration */
+ private final UnmodifiableSortedSet<ILicense> licenses;
+ /** The report configuration */
private final ReportConfiguration configuration;
/** The matcher for generated files */
private final IHeaderMatcher generatedMatcher;
/**
* Constructs a DocumentAnalyser for the specified license.
- * @param config the ReportConfiguration
- * @param licenses The licenses to analyse
+ * @param config the ReportConfiguration.
+ * @param licenses the licenses to analyse.
*/
- DefaultAnalyser(final ReportConfiguration config, final
Collection<ILicense> licenses) {
+ DefaultAnalyser(final ReportConfiguration config, final
UnmodifiableSortedSet<ILicense> licenses) {
this.licenses = licenses;
this.configuration = config;
this.generatedMatcher = configuration.getGeneratedMatcher();
@@ -118,15 +117,13 @@ public final class AnalyserFactory {
/**
* Generates a predicate to filter out licenses that should not be
reported.
* @param proc the processing status to filter.
- * @return a Predicate to do the filtering.
+ * @return a predicate to do the filtering.
*/
private Predicate<ILicense> licenseFilter(final
ReportConfiguration.Processing proc) {
- return license -> {
- return switch (proc) {
- case PRESENCE ->
!license.getLicenseFamily().equals(UnknownLicense.INSTANCE.getLicenseFamily());
- case ABSENCE -> true;
- default -> false;
- };
+ return license -> switch (proc) {
+ case PRESENCE ->
!license.getLicenseFamily().equals(UnknownLicense.INSTANCE.getLicenseFamily());
+ case ABSENCE -> true;
+ default -> false;
};
}
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/analysis/DocumentHeaderAnalyser.java
b/apache-rat-core/src/main/java/org/apache/rat/analysis/DocumentHeaderAnalyser.java
index cec174f6..a87d18fe 100644
---
a/apache-rat-core/src/main/java/org/apache/rat/analysis/DocumentHeaderAnalyser.java
+++
b/apache-rat-core/src/main/java/org/apache/rat/analysis/DocumentHeaderAnalyser.java
@@ -20,8 +20,8 @@ package org.apache.rat.analysis;
import java.io.IOException;
import java.io.Reader;
-import java.util.Collection;
+import org.apache.commons.collections4.set.UnmodifiableSortedSet;
import org.apache.rat.api.Document;
import org.apache.rat.document.DocumentAnalyser;
import org.apache.rat.license.ILicense;
@@ -35,15 +35,15 @@ import static java.lang.String.format;
class DocumentHeaderAnalyser implements DocumentAnalyser {
/** The license to analyse */
- private final Collection<ILicense> licenses;
+ private final UnmodifiableSortedSet<ILicense> licenses;
/** The matcher for generated headers */
private final IHeaderMatcher generatedMatcher;
/**
* Constructs the HeaderAnalyser for the specific license.
- * @param licenses The licenses to analyse
+ * @param licenses the licenses to analyse.
*/
- DocumentHeaderAnalyser(final IHeaderMatcher generatedMatcher, final
Collection<ILicense> licenses) {
+ DocumentHeaderAnalyser(final IHeaderMatcher generatedMatcher, final
UnmodifiableSortedSet<ILicense> licenses) {
super();
this.generatedMatcher = generatedMatcher;
this.licenses = licenses;
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/analysis/HeaderCheckWorker.java
b/apache-rat-core/src/main/java/org/apache/rat/analysis/HeaderCheckWorker.java
index 30243bb0..b7aed491 100644
---
a/apache-rat-core/src/main/java/org/apache/rat/analysis/HeaderCheckWorker.java
+++
b/apache-rat-core/src/main/java/org/apache/rat/analysis/HeaderCheckWorker.java
@@ -21,17 +21,17 @@ package org.apache.rat.analysis;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
-import java.util.Collection;
import java.util.Locale;
import java.util.Objects;
+import org.apache.commons.collections4.set.UnmodifiableSortedSet;
import org.apache.rat.ConfigurationException;
import org.apache.rat.analysis.matchers.FullTextMatcher;
import org.apache.rat.api.Document;
import org.apache.rat.license.ILicense;
/**
- * Reads from a stream to check license.
+ * Reads from a stream to check for a license.
* <p>
* <strong>Note</strong> that this class is not thread safe.
* </p>
@@ -54,21 +54,20 @@ public final class HeaderCheckWorker {
/** The BufferedReader used to read the lines */
private final BufferedReader reader;
/** The licenses to check for match */
- private final Collection<ILicense> licenses;
+ private final UnmodifiableSortedSet<ILicense> licenses;
/** The document being processed */
private final Document document;
/** The matcher for generated headers */
private final IHeaderMatcher generatedMatcher;
-
/**
* Read the input and perform the header check.
* <p>
- * The number of lines indicates how many lines from the top of the file
will be read for processing
+ * The number of lines indicates how many lines from the top of the file
will be read for processing.
*
- * @param reader The reader for the document.
+ * @param reader the reader for the document.
* @param numberOfLines the number of lines to read from the header.
- * @return The IHeaders instance for the header.
+ * @return the IHeaders instance for the header.
* @throws IOException on input failure
*/
public static IHeaders readHeader(final BufferedReader reader, final int
numberOfLines) throws IOException {
@@ -103,12 +102,12 @@ public final class HeaderCheckWorker {
* Convenience constructor wraps given <code>Reader</code> in a
* <code>BufferedReader</code>.
*
- * @param generatedMatcher The matcher for generated headers.
- * @param reader The reader on the document. Not null.
- * @param licenses The licenses to check against. Not null.
- * @param name The document that is being checked. Possibly null.
+ * @param generatedMatcher the matcher for generated headers.
+ * @param reader the reader on the document. Not null.
+ * @param licenses the licenses to check against. Not null.
+ * @param name the document that is being checked. Possibly null.
*/
- public HeaderCheckWorker(final IHeaderMatcher generatedMatcher, final
Reader reader, final Collection<ILicense> licenses, final Document name) {
+ public HeaderCheckWorker(final IHeaderMatcher generatedMatcher, final
Reader reader, final UnmodifiableSortedSet<ILicense> licenses, final Document
name) {
this(generatedMatcher, reader,
DEFAULT_NUMBER_OF_RETAINED_HEADER_LINES, licenses, name);
}
@@ -123,7 +122,7 @@ public final class HeaderCheckWorker {
* @param document The document that is being checked. Possibly null.
*/
public HeaderCheckWorker(final IHeaderMatcher generatedMatcher, final
Reader reader,
- final int numberOfRetainedHeaderLine, final
Collection<ILicense> licenses,
+ final int numberOfRetainedHeaderLine, final
UnmodifiableSortedSet<ILicense> licenses,
final Document document) {
Objects.requireNonNull(reader, "Reader may not be null");
Objects.requireNonNull(licenses, "Licenses may not be null");
@@ -140,7 +139,7 @@ public final class HeaderCheckWorker {
/**
* Read the input and perform the header check.
*
- * @throws RatHeaderAnalysisException on IO exception.
+ * @throws RatHeaderAnalysisException in case of I/O exceptions.
*/
public void read() throws RatHeaderAnalysisException {
try {
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/license/LicenseSetFactory.java
b/apache-rat-core/src/main/java/org/apache/rat/license/LicenseSetFactory.java
index 6fe00db5..18ca3b41 100644
---
a/apache-rat-core/src/main/java/org/apache/rat/license/LicenseSetFactory.java
+++
b/apache-rat-core/src/main/java/org/apache/rat/license/LicenseSetFactory.java
@@ -20,13 +20,19 @@ package org.apache.rat.license;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.Optional;
+import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import org.apache.commons.collections4.set.UnmodifiableSortedSet;
+import org.apache.rat.ConfigurationException;
import org.apache.rat.analysis.IHeaderMatcher;
import org.apache.rat.analysis.IHeaders;
+import org.apache.rat.utils.DefaultLog;
import org.apache.rat.utils.Log;
import org.apache.rat.utils.ReportingSet;
@@ -38,7 +44,7 @@ public class LicenseSetFactory {
/**
* Search a SortedSet of ILicenseFamily instances looking for a matching
instance.
- * @param target The instance to search for.
+ * @param target the instance to search for.
* @param licenseFamilies the license families to search.
* @return the matching instance of the target given.
*/
@@ -50,7 +56,7 @@ public class LicenseSetFactory {
/**
* Search a SortedSet of ILicenseFamily instances looking for a matching
instance.
- * @param target The instance to search for.
+ * @param target the instance to search for.
* @param licenseFamilies the license families to search.
* @return the matching instance of the target given.
*/
@@ -60,7 +66,7 @@ public class LicenseSetFactory {
}
/**
- * An enum that defines the types of Licenses to extract.
+ * An enum that defines the types of licenses to extract.
*/
public enum LicenseFilter {
/** All defined licenses are returned. */
@@ -121,6 +127,31 @@ public class LicenseSetFactory {
licenses.forEach(l -> families.addIfNotPresent(l.getLicenseFamily()));
}
+ public void validate() {
+ Log log = DefaultLog.getInstance();
+
+ // verify license definitions exist
+ if (getLicenses(LicenseFilter.ALL).isEmpty()) {
+ String msg = "At least one license must be defined";
+ log.error(msg);
+ throw new ConfigurationException(msg);
+ }
+
+ // verify that all approved license families exist
+ Set<String> exists = getLicenseFamilies(LicenseFilter.ALL)
+
.stream().map(ILicenseFamily::getFamilyCategory).collect(Collectors.toSet());
+ Set<String> approved = new HashSet<>(approvedLicenseCategories);
+ approved.removeIf(exists::contains);
+ approved.forEach(name -> log.warn(String.format("License category '%s'
was approved but does not exist.", name)));
+
+ // verify that all approved licenses exist
+ exists = getLicenses(LicenseFilter.ALL)
+ .stream().map(ILicense::getId).collect(Collectors.toSet());
+ approved = new HashSet<>(approvedLicenseIds);
+ approved.removeIf(exists::contains);
+ approved.forEach(name -> log.warn(String.format("License '%s' was
approved but does not exist.", name)));
+ }
+
public void add(final LicenseSetFactory other) {
this.families.addAll(other.families);
this.licenses.addAll(other.licenses);
@@ -133,7 +164,7 @@ public class LicenseSetFactory {
/**
* Set the log level for reporting collisions in the set of license
families.
* <p>NOTE: should be set before licenses or license families are
added.</p>
- * @param level The log level to use.
+ * @param level the log level to use.
*/
public void logFamilyCollisions(final Log.Level level) {
families.setLogLevel(level);
@@ -141,7 +172,7 @@ public class LicenseSetFactory {
/**
* 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) {
families.setDuplicateOption(state);
@@ -149,7 +180,7 @@ public class LicenseSetFactory {
/**
* Sets the log level for reporting license collisions.
- * @param level The log level.
+ * @param level the log level.
*/
public void logLicenseCollisions(final Log.Level level) {
licenses.setLogLevel(level);
@@ -177,7 +208,7 @@ public class LicenseSetFactory {
/**
* Adds a license to the list of licenses. Does not add the license to the
list
* of approved licenses.
- * @param license The license to add to the list of licenses.
+ * @param license the license to add to the list of licenses.
*/
public void addLicense(final ILicense license) {
if (license != null) {
@@ -189,8 +220,8 @@ public class LicenseSetFactory {
/**
* Adds a license to the list of licenses. Does not add the license to the
list
* of approved licenses.
- * @param builder The license builder to build and add to the list of
licenses.
- * @return The ILicense implementation that was added.
+ * @param builder the license builder to build and add to the list of
licenses.
+ * @return the ILicense implementation that was added.
*/
public ILicense addLicense(final ILicense.Builder builder) {
if (builder != null) {
@@ -204,7 +235,7 @@ public class LicenseSetFactory {
/**
* Adds multiple licenses to the list of licenses. Does not add the
licenses to
* the list of approved licenses.
- * @param licenses The licenses to add.
+ * @param licenses the licenses to add.
*/
public void addLicenses(final Collection<ILicense> licenses) {
this.licenses.addAll(licenses);
@@ -214,7 +245,7 @@ public class LicenseSetFactory {
/**
* Adds a license family to the list of families. Does not add the family
to the
* list of approved licenses.
- * @param family The license family to add to the list of license families.
+ * @param family the license family to add to the list of license families.
*/
public void addFamily(final ILicenseFamily family) {
if (family != null) {
@@ -225,7 +256,7 @@ public class LicenseSetFactory {
/**
* Adds a license family to the list of families. Does not add the family
to the
* list of approved licenses.
- * @param builder The licenseFamily.Builder to build and add to the list of
+ * @param builder the licenseFamily.Builder to build and add to the list of
* licenses.
*/
public void addFamily(final ILicenseFamily.Builder builder) {
@@ -235,7 +266,7 @@ public class LicenseSetFactory {
}
/**
- * 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 approveLicenseCategory(final String familyCategory) {
@@ -243,8 +274,8 @@ public class LicenseSetFactory {
}
/**
- * Adds a license family category (id) to the list of approved licenses
- * @param familyCategory the category to add.
+ * Removes a license family category (id) from the list of approved
licenses.
+ * @param familyCategory the category to remove.
*/
public void removeLicenseCategory(final String familyCategory) {
removedLicenseCategories.add(ILicenseFamily.makeCategory(familyCategory));
@@ -269,7 +300,7 @@ public class LicenseSetFactory {
/**
* Test for approved family category.
* @param family the license family to test, must be in category format.
- * @return return {@code true} if the category is approved.
+ * @return {@code true} if the category is approved.
*/
private boolean isApprovedCategory(final ILicenseFamily family) {
return approvedLicenseCategories.contains(family.getFamilyCategory())
&& !removedLicenseCategories.contains(family.getFamilyCategory());
@@ -289,18 +320,21 @@ public class LicenseSetFactory {
* @param filter the types of LicenseFamily objects to return.
* @return a SortedSet of ILicense objects.
*/
- public SortedSet<ILicense> getLicenses(final LicenseFilter filter) {
+ public UnmodifiableSortedSet<ILicense> getLicenses(final LicenseFilter
filter) {
+ SortedSet<ILicense> result;
switch (filter) {
case ALL:
- return Collections.unmodifiableSortedSet(licenses);
+ result = licenses;
+ break;
case APPROVED:
- SortedSet<ILicense> result = new TreeSet<>();
+ result = new TreeSet<>();
licenses.stream().filter(getApprovedLicensePredicate()).forEach(result::add);
- return result;
+ break;
case NONE:
default:
- return Collections.emptySortedSet();
+ result = Collections.emptySortedSet();
}
+ return (UnmodifiableSortedSet<ILicense>)
UnmodifiableSortedSet.unmodifiableSortedSet(result);
}
/**
@@ -329,7 +363,7 @@ public class LicenseSetFactory {
* Gets the License ids based on the filter.
*
* @param filter the types of License Ids to return.
- * @return The list of all licenses in the category regardless of whether
or not it is used by an ILicense implementation.
+ * @return a set of all licenses in the category regardless of whether it
is used by an ILicense implementation.
*/
public SortedSet<String> getLicenseCategories(final LicenseFilter filter) {
SortedSet<String> result = new TreeSet<>();
@@ -354,7 +388,7 @@ public class LicenseSetFactory {
* Gets the License ids based on the filter.
*
* @param filter the types of License Ids to return.
- * @return The list of all licenses in the category regardless of whether
or not it is used by an ILicense implementation.
+ * @return a set of all licenses in the category regardless of whether it
is used by an ILicense implementation.
*/
public SortedSet<String> getLicenseIds(final LicenseFilter filter) {
Predicate<ILicense> approved = l ->
(isApprovedCategory(l.getLicenseFamily()) ||
@@ -390,7 +424,6 @@ public class LicenseSetFactory {
ILicenseFamily searchFamily =
ILicenseFamily.builder().setLicenseFamilyCategory(familyId)
.setLicenseFamilyName("searching proxy").build();
ILicense target = new ILicense() {
-
@Override
public String getId() {
return licenseId;
@@ -449,6 +482,9 @@ public class LicenseSetFactory {
* @return the matching license or {@code null} if not found.
*/
public static Optional<ILicense> search(final ILicense target, final
SortedSet<ILicense> licenses) {
+ if (licenses == null) {
+ return Optional.empty();
+ }
SortedSet<ILicense> part = licenses.tailSet(target);
return Optional.ofNullable((!part.isEmpty() &&
part.first().compareTo(target) == 0) ? part.first() : null);
}
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/license/SimpleLicense.java
b/apache-rat-core/src/main/java/org/apache/rat/license/SimpleLicense.java
index e4286ab9..3e7d699b 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/license/SimpleLicense.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/license/SimpleLicense.java
@@ -49,7 +49,7 @@ public class SimpleLicense implements ILicense {
/** The name of this license */
@ConfigComponent(type = ComponentType.PARAMETER, desc = "The name of this
license.")
private final String name;
- /** The ID for this license. Must be unique */
+ /** The ID for this license. Must be unique. */
@ConfigComponent(type = ComponentType.PARAMETER, desc = "The ID for this
license.")
private final String id;
@@ -171,7 +171,7 @@ public class SimpleLicense implements ILicense {
/**
* Sets the ID of the license. If the ID is not set then the ID of the
license
* family is used.
- * @param id the ID for the license
+ * @param id the ID for the license.
* @return this builder for chaining.
*/
@Override
@@ -197,7 +197,7 @@ public class SimpleLicense implements ILicense {
/**
* Sets the name of the license. If the name is not set then the name
of the
* license family is used.
- * @param name the name for the license
+ * @param name the name for the license.
* @return this builder for chaining.
*/
@Override
@@ -218,7 +218,7 @@ public class SimpleLicense implements ILicense {
throw new ConfigurationException("'matcher' must not be null");
}
if (licenseFamilies == null) {
- throw new ImplementationException("'licenseFamilies' must not
be null");
+ throw new ImplementationException("License builder
'licenseFamilies' must not be null");
}
if (StringUtils.isBlank(familyCategory)) {
throw new ImplementationException("License 'family' must be
specified");
@@ -226,7 +226,7 @@ public class SimpleLicense implements ILicense {
String familyCat = ILicenseFamily.makeCategory(familyCategory);
Optional<ILicenseFamily> family =
licenseFamilies.stream().filter(f ->
f.getFamilyCategory().equals(familyCat)).findFirst();
- if (!family.isPresent()) {
+ if (family.isEmpty()) {
throw new ConfigurationException(String.format("License family
'%s' not found.", familyCategory));
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/DefaultsTest.java
b/apache-rat-core/src/test/java/org/apache/rat/DefaultsTest.java
index bfd5f31e..884e9d76 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/DefaultsTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/DefaultsTest.java
@@ -19,29 +19,28 @@
package org.apache.rat;
import java.util.Arrays;
-import java.util.Set;
import java.util.TreeSet;
+import org.apache.commons.collections4.set.UnmodifiableSortedSet;
import org.apache.rat.license.ILicense;
import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
-
-public class DefaultsTest {
+class DefaultsTest {
private static final String[] FAMILIES = { "BSD-3", "GPL ", "AL ",
"OASIS", "W3CD ", "W3C ", "MIT ", "CDDL1" };
@Test
- public void defaultConfigTest() {
+ void defaultConfigTest() {
Defaults defaults = Defaults.builder().build();
- Set<ILicense> licenses =
defaults.getLicenseSetFactory().getLicenses(LicenseFilter.ALL);
+ UnmodifiableSortedSet<ILicense> licenses =
defaults.getLicenseSetFactory().getLicenses(LicenseFilter.ALL);
- Set<String> names = new TreeSet<>();
+ TreeSet<String> names = new TreeSet<>();
licenses.forEach(x ->
names.add(x.getLicenseFamily().getFamilyCategory()));
assertThat(names).hasSize(FAMILIES.length);
- names.removeAll(Arrays.asList(FAMILIES));
+ Arrays.asList(FAMILIES).forEach(names::remove);
assertThat(names).isEmpty();
}
}
diff --git
a/apache-rat-core/src/test/java/org/apache/rat/analysis/HeaderCheckWorkerTest.java
b/apache-rat-core/src/test/java/org/apache/rat/analysis/HeaderCheckWorkerTest.java
index b00aec08..9583f47e 100644
---
a/apache-rat-core/src/test/java/org/apache/rat/analysis/HeaderCheckWorkerTest.java
+++
b/apache-rat-core/src/test/java/org/apache/rat/analysis/HeaderCheckWorkerTest.java
@@ -21,8 +21,11 @@ package org.apache.rat.analysis;
import java.io.StringReader;
-import java.util.Collections;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import org.apache.commons.collections4.set.UnmodifiableSortedSet;
import org.apache.rat.Defaults;
import org.apache.rat.api.Document;
import org.apache.rat.configuration.builders.AnyBuilder;
@@ -31,29 +34,36 @@ import org.apache.rat.testhelpers.TestingDocument;
import org.apache.rat.license.ILicense;
import org.apache.rat.testhelpers.TestingLicense;
import org.apache.rat.testhelpers.TestingMatcher;
-import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
-public class HeaderCheckWorkerTest {
+class HeaderCheckWorkerTest {
+
+ /**
+ * Create an unmodifiable sorted set from members
+ */
+ private UnmodifiableSortedSet<ILicense> asLicenses(ILicense... licenses) {
+ SortedSet<ILicense> inner = new TreeSet<>(List.of(licenses));
+ return (UnmodifiableSortedSet<ILicense>)
UnmodifiableSortedSet.unmodifiableSortedSet(inner);
+ }
@Test
- public void emptyInputIsUnknownTest() throws RatHeaderAnalysisException {
+ void emptyInputIsUnknownTest() throws RatHeaderAnalysisException {
final Document subject = new TestingDocument("subject");
subject.getMetaData().setApprovalPredicate(Defaults.builder().build().getLicenseSetFactory().getApprovedLicensePredicate());
ILicense matcher = new TestingLicense("test", "test");
- HeaderCheckWorker worker = new HeaderCheckWorker(new TestingMatcher(),
new StringReader(""), Lists.list(matcher), subject);
+ HeaderCheckWorker worker = new HeaderCheckWorker(new TestingMatcher(),
new StringReader(""), asLicenses(matcher), subject);
worker.read();
assertThat(subject.getMetaData().unapprovedLicenses().count()).isEqualTo(1);
assertThat(subject.getMetaData().unapprovedLicenses().toList().get(0).getLicenseFamily()).isEqualTo(ILicenseFamily.UNKNOWN);
}
@Test
- public void generatedFileDetectionTest() throws Exception {
+ void generatedFileDetectionTest() throws Exception {
final Document subject = new TestingDocument(new
StringReader("Generated from configure.ac by autoheader"), "subject");
IHeaderMatcher matcher = new
AnyBuilder().setResource("/org/apache/rat/generation-keywords.txt").build();
- HeaderCheckWorker worker = new HeaderCheckWorker(matcher,
subject.reader(), Collections.emptyList(), subject);
+ HeaderCheckWorker worker = new HeaderCheckWorker(matcher,
subject.reader(), asLicenses(), subject);
worker.read();
assertThat(subject.getMetaData().getDocumentType()).isEqualTo(Document.Type.IGNORED);
}
diff --git
a/apache-rat-core/src/test/java/org/apache/rat/license/LicenseSetFactoryTest.java
b/apache-rat-core/src/test/java/org/apache/rat/license/LicenseSetFactoryTest.java
index 13bf945b..ba0bf80c 100644
---
a/apache-rat-core/src/test/java/org/apache/rat/license/LicenseSetFactoryTest.java
+++
b/apache-rat-core/src/test/java/org/apache/rat/license/LicenseSetFactoryTest.java
@@ -18,7 +18,12 @@
*/
package org.apache.rat.license;
+import java.util.Arrays;
+import java.util.Optional;
import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.rat.ConfigurationException;
import org.apache.rat.Defaults;
import org.apache.rat.analysis.UnknownLicense;
import org.apache.rat.testhelpers.TestingLicense;
@@ -27,6 +32,8 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatNoException;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
public class LicenseSetFactoryTest {
@@ -165,4 +172,74 @@ public class LicenseSetFactoryTest {
.as("Found unapproved id " + licenseId)
.isFalse();
}
+
+ @Test
+ void familySearchTest() {
+ SortedSet<ILicenseFamily> families = new
TreeSet<>(Arrays.asList(APPROVED_FAMILIES));
+ ILicenseFamily actual =
LicenseSetFactory.familySearch(APPROVED_FAMILIES[0], families);
+ assertThat(actual).isEqualTo(APPROVED_FAMILIES[0]);
+ actual =
LicenseSetFactory.familySearch(APPROVED_FAMILIES[2].getFamilyCategory(),
families);
+ assertThat(actual).isEqualTo(APPROVED_FAMILIES[2]);
+ actual = LicenseSetFactory.familySearch("not a real category",
families);
+ assertThat(actual).isNull();
+ ILicenseFamily family =
ILicenseFamily.builder().setLicenseFamilyCategory("***").setLicenseFamilyName("testing").build();
+ actual = LicenseSetFactory.familySearch(family, families);
+ assertThat(actual).isNull();
+ }
+
+ @Test
+ void validateTest() {
+ LicenseSetFactory underTest = new LicenseSetFactory();
+
+ assertThatThrownBy(underTest::validate)
+ .hasMessageContaining("At least one license must be defined")
+ .isInstanceOf(ConfigurationException.class);
+
+ // set up builder and add a license
+ SortedSet<ILicenseFamily> families = new TreeSet<>();
+
families.add(ILicenseFamily.builder().setLicenseFamilyCategory("test").setLicenseFamilyName("testing
family").build());
+ ILicense.Builder builder =
ILicense.builder().setLicenseFamilies(families);
+ underTest.addLicense(builder.setFamily("test").setMatcher(new
TestingMatcher())
+ .setName("test1").build());
+
+ assertThatNoException().isThrownBy(underTest::validate);
+ }
+
+ @Test
+ void addNullLicense() {
+ LicenseSetFactory underTest = new LicenseSetFactory();
+
assertThat(underTest.getLicenses(LicenseSetFactory.LicenseFilter.ALL)).isEmpty();
+ underTest.addLicense((ILicense) null);
+
assertThat(underTest.getLicenses(LicenseSetFactory.LicenseFilter.ALL)).isEmpty();
+ ILicense result = underTest.addLicense((ILicense.Builder) null);
+
assertThat(underTest.getLicenses(LicenseSetFactory.LicenseFilter.ALL)).isEmpty();
+ assertThat(result).isNull();
+ }
+
+ @Test
+ void addNullFamily() {
+ LicenseSetFactory underTest = new LicenseSetFactory();
+
assertThat(underTest.getLicenseFamilies(LicenseSetFactory.LicenseFilter.ALL)).isEmpty();
+ underTest.addFamily((ILicenseFamily) null);
+
assertThat(underTest.getLicenseFamilies(LicenseSetFactory.LicenseFilter.ALL)).isEmpty();
+ underTest.addFamily((ILicenseFamily.Builder) null);
+
assertThat(underTest.getLicenseFamilies(LicenseSetFactory.LicenseFilter.ALL)).isEmpty();
+ }
+
+ @Test
+ void searchTest() {
+ assertThat(LicenseSetFactory.search("theFamily", "TheLicense",
null)).isEmpty();
+
+ assertThat(LicenseSetFactory.search("theFamily", "TheLicense", new
TreeSet<>())).isEmpty();
+
+ SortedSet<ILicense> set =
licenseSetFactory.getLicenses(LicenseSetFactory.LicenseFilter.ALL);
+
assertThat(LicenseSetFactory.search(APPROVED_FAMILIES[0].getFamilyCategory(),
"TheLicense", set)).isEmpty();
+
+ Optional<ILicense> optLicense = LicenseSetFactory.search("AL",
"AL2.0", set);
+ assertThat(optLicense).isNotEmpty();
+ ILicense license = optLicense.get();
+
assertThat(license.getLicenseFamily().getFamilyCategory()).isEqualTo(ILicenseFamily.makeCategory("AL"));
+ assertThat(license.getId()).isEqualTo("AL2.0");
+ assertThat(license.getName()).isEqualTo("Apache License 2.0");
+ }
}
diff --git
a/apache-rat-tools/src/main/java/org/apache/rat/documentation/velocity/RatTool.java
b/apache-rat-tools/src/main/java/org/apache/rat/documentation/velocity/RatTool.java
index 820e246e..ca1adadf 100644
---
a/apache-rat-tools/src/main/java/org/apache/rat/documentation/velocity/RatTool.java
+++
b/apache-rat-tools/src/main/java/org/apache/rat/documentation/velocity/RatTool.java
@@ -24,11 +24,11 @@ import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.SortedSet;
import java.util.TreeSet;
import java.util.stream.Collectors;
import org.apache.commons.cli.Option;
+import org.apache.commons.collections4.set.UnmodifiableSortedSet;
import org.apache.commons.lang3.StringUtils;
import org.apache.rat.CLIOption;
import org.apache.rat.CLIOptionCollection;
@@ -187,9 +187,8 @@ public class RatTool {
* @return the set of Matchers.
*/
public Set<Matcher> matchers() {
- MatcherBuilderTracker tracker = MatcherBuilderTracker.instance();
Set<Matcher> documentationSet = new
TreeSet<>(Comparator.comparing(Matcher::getName));
- for (Class<?> clazz : tracker.getClasses()) {
+ for (Class<?> clazz : MatcherBuilderTracker.instance().getClasses()) {
Description desc = DescriptionBuilder.buildMap(clazz);
documentationSet.add(new Matcher(desc, null));
}
@@ -246,7 +245,7 @@ public class RatTool {
* @return a list of license property descriptions.
*/
public List<Description> licenseProperties() {
- SortedSet<ILicense> licenses =
licenseSetFactory.getLicenses(LicenseSetFactory.LicenseFilter.ALL);
+ UnmodifiableSortedSet<ILicense> licenses =
licenseSetFactory.getLicenses(LicenseSetFactory.LicenseFilter.ALL);
Description licenseDescription =
DescriptionBuilder.build(licenses.first());
List<Description> descriptions = new
ArrayList<>(licenseDescription.filterChildren(d -> d.getType() ==
ComponentType.PARAMETER));
descriptions.sort(Comparator.comparing(Description::getCommonName));
@@ -258,7 +257,7 @@ public class RatTool {
* @return the list of defined licenses.
*/
public List<License> licenses() {
- Set<ILicense> licenses =
licenseSetFactory.getLicenses(LicenseSetFactory.LicenseFilter.ALL);
+ UnmodifiableSortedSet<ILicense> licenses =
licenseSetFactory.getLicenses(LicenseSetFactory.LicenseFilter.ALL);
return
licenses.stream().map(License::new).collect(Collectors.toList());
}
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index bd96c2fc..120786a1 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -68,6 +68,9 @@ in order to be properly linked in site reports.
</release>
-->
<release version="1.0.0-SNAPSHOT" date="xxxx-yy-zz" description="Current
SNAPSHOT - release to be done">
+ <action issue="RAT-564" type="add" dev="claudenw">
+ Internal change to let LicenseSetFactory return unmodifiable license
sets.
+ </action>
<action issue="RAT-563" type="add" dev="claudenw">
Internal change: rename IReportable and IReportableListWalker to
clarify interface structure, when doing RAT scans.
</action>